Linux shell - process list
在命令行中可以指定要依次运行的一系列命令。这可以通过命令列表来实现,只需将命令之间以分号(;)分隔即可:
pwd;cd ~/Downloads;ls
在上面的例子中,所有命令依次执行,没有任何问题。不过这并不是进程列表。要想成为进程列表,命令列表必须将命令放入圆括号内:
(pwd;cd ~/Downloads;ls)
尽管多出来的圆括号看起来没什么太大的不同,但起到的效果确是非同寻常。圆括号的加入使命令列表摇身变成了进程列表,生成了一个子 shell 来执行这些命令。
进程列表是命令分组(command grouping)的一种。另一种命令分组是将命令放入花括号内,并在命令列表尾部以分号(;)作结。语法为:{ command; }。使用花括号进行命令分组并不会像进程列表那样创建子 shell。
要想知道是否生成了子 shell,需要使用命令输出一个环境变量的值。这个命令就是 echo $BASH_SUBSHELL。如果该命令返回 0,那么表明没有子 shell。如果该命令返回 1 或者其他更大的数字,则表明存在子 shell。
pwd;cd ~/Downloads;ls;echo $BASH_SUBSHELL
在输出结果的最后是数字 0。这表明并未创建子 shell 来执行这些命令。
如果改用进程列表,则结果就不一样了。
(pwd;cd ~/Downloads;ls;echo $BASH_SUBSHELL)
在输出结果的最后是数字 0。这表明并未创建子 shell 来执行这些命令。如果改用进程列表,则结果就不一样了。
这次在输出结果的最后是数字 1。这表明的确创建了子 shell 来执行这些命令。因此,进程列表就是使用圆括号包围起来的一组命令,它能够创建子 shell 来执行这些命令。甚至可以在进程列表中嵌套圆括号来创建子 shell 的子 shell:
(pwd;cd ~/Downloads;ls;(ls;echo $BASH_SUBSHELL))
注意,在第一个进程列表中,数字 1 表明有一个子 shell,这个结果和预期一样。但是在第二个进程列表中,在命令 echo $BASH_SUBSHELL 之外又多出了一对圆括号。这对圆括号在子 shell 中产生了另一个子 shell 来执行该命令。因此,数字 2 表示的就是这个子 shell。
子 shell 在 shell 脚本中经常用于多进程处理。但是,创建子 shell 的成本不菲(意思是要消耗更多的资源,比如内存和处理能力),会明显拖慢任务进度。在交互式 CLI shell 会话中,子 shell 同样存在问题,它并非真正的多进程处理,原因在于终端与子 shell 的 I/O 绑定在了一起。