Linux Shell核心编程指南
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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命令开启子进程的方式执行脚本文件却不受任何影响,为什么呢?希望大家可以自己思考这个问题!