
1.2 脚本文件的各种执行方式
编写好脚本文件后,接下来就是执行了。执行脚本文件的方式有很多种,有需要执行权限的方式、有不需要执行权限的方式、有开启子进程的方式、有不开启子进程的方式。
1)脚本文件自身没有可执行权限
如果暂时还没有给脚本文件可执行的权限,那么默认脚本是无法直接执行的,但bash或sh这样的解释器,可以将脚本文件作为参数(读取脚本文件中的内容)来执行脚本文件。
[root@centos7~]# ./first.sh -bash: ./first.sh: 权限不够 [root@centos7~]# bash first.sh hello the world [root@centos7~]# sh first.sh hello the world
通过以上3条命令的输出信息,我们可以看到,在没有执行权限的情况下,执行./(当前目录)下的first.sh脚本文件会出现报错信息,而使用bash和sh将first.sh脚本作为参数执行,就可以输出正确的信息“hello the world”。
2)脚本文件具有可执行权限
通过chmod命令可以给脚本文件分配执行权限,脚本文件一旦有了执行权限,就可以使用绝对路径或相对路径执行了。以下假设某个脚本文件,绝对路径为/root/first.sh,则执行脚本文件效果如下。
[root@centos7~]# chmod +x first.sh #分配可执行权限 [root@centos7~]# ./first.sh #使用相对路径执行(当前工作目录) hello the world [root@centos7~]# /root/first.sh #使用绝对路径执行 hello the world
3)开启子进程执行的方式
关于是否开启子进程,我们首先要了解什么是子进程,一般可以通过pstree命令来查看进程树,了解进程之间的关系。
[root@centos7~]# pstree #进程树查看器 systemd-+-ModemManager---2*[{ModemManager}] |-NetworkManager---2*[{NetworkManager}] |-atd |-chronyd |-crond |-irqbalance |-libvirtd---16*[{libvirtd}] |-lsmd |-lvmetad |-qemu-kvm---26*[{qemu-kvm}] ├—sshd—┬—sshd———bash———pstree | └—sshd———bash
通过以上输出,我们可以看到计算机启动的第一个进程是systemd,然后在这个进程下启动了N个子进程,如NetworkManager、atd、chronyd、sshd这些都是systemd的子进程。而在sshd进程下又有2个sshd的子进程,在2个sshd子进程下又开启了bash解释器子进程,而且在其中一个bash进程下面还执行了一条pstree命令。对于刚才我们说的不管是直接执行脚本,还是使用bash或sh这样的解释器执行脚本,都是会开启子进程的。下面通过一个脚本文件演示效果。
首先,打开一个命令终端,在该命令终端中编写脚本文件,并执行脚本文件。

然后,开启一个命令终端,在这个终端中通过pstree命令观察进程树。
[root@centos7~]# pstree systemd-+-ModemManager---2*[{ModemManager}] |-NetworkManager---2*[{NetworkManager}] … … ├—sshd—┬—sshd———bash———sleep.sh———sleep | └—sshd———bash———pstree
通过输出可以看到,在bash终端下开启了一个子进程脚本文件,通过脚本文件执行了一条sleep命令。
回到第一个终端,使用Ctrl+C组合键终止前面执行的脚本文件,使用bash命令再次执行该脚本。
[root@centos7~]# bash sleep.sh
最后,在第二个终端上使用pstree命令观察实验结果。
[root@centos7~]# pstree systemd-+-ModemManager---2*[{ModemManager}] |-NetworkManager---2*[{NetworkManager}] … … ├—sshd—┬—sshd———bash———bash———sleep | └—sshd———bash———pstree
结果类似,在bash进程下开启了一个bash子进程,在bash子进程下执行了一条sleep命令。
4)不开启子进程的执行方式
下面我们来看看不开启子进程的执行方式的案例,与之前的实验类似,我们需要开启两个命令终端。
首先,打开第一个终端,这次使用source或.(点)命令来执行脚本文件。
[root@centos7~]# source sleep.sh
或者
[root@centos7~]# . sleep.sh
然后,我们再打开第二个终端,通过pstree命令观察结果。
[root@centos7~]# pstree
systemd-+-ModemManager---2*[{ModemManager}] |-NetworkManager---2*[{NetworkManager}] … … ├—sshd—┬—sshd———bash———sleep | └—sshd———bash———pstree
通过实验结果可以看到,脚本文件中的sleep命令是直接在bash终端下执行的。
最后,我们编写一个特殊的脚本文件,内容如下。

对于这个脚本文件,分别使用开启子进程和不开启子进程的方式执行。
[root@centos7~]# bash exit.sh [root@centos7~]# source exit.sh
你可能已经发现了,source命令不开启子进程执行脚本文件会导致整个终端被关闭,而bash命令开启子进程的方式执行脚本文件却不受任何影响,为什么呢?希望大家可以自己思考这个问题!