Will()构造总是启动一个子shell?

时间:2011-05-08 16:07:58

标签: linux bash shell

当前的shell是

$ echo $$
23173

注意ps的父级是当前shell

$ ( ps -o pid,ppid,cmd )
  PID  PPID CMD
 8952 23173 ps -o pid,ppid,cmd
23173 23169 bash

但是在这里,ps的父亲是子shell(bash)

$ ( echo hello ; ps -o pid,ppid,cmd )
hello
  PID  PPID CMD
 8953 23173 bash
 8954  8953 ps -o pid,ppid,cmd
23173 23169 bash

bash正在进行优化吗?为什么额外的回声会产生差异并在第3种情况下产生子壳?

2 个答案:

答案 0 :(得分:6)

是的,您所看到的是优化。从技术上讲,(…)结构总是按照定义启动子shell。大多数情况下,子shell在一个单独的子进程中运行。这可确保子shell中完成的所有操作都保留在子shell中。如果bash可以保证这种隔离属性,则可以自由使用它喜欢的任何实现技术。

在片段( ps -o pid,ppid,cmd )中,很明显没有任何东西可以影响父shell,因此bash中的优化使得它不会为子shell分叉一个单独的进程。片段( echo hello ; ps -o pid,ppid,cmd )太复杂,优化器无法识别不需要子shell。

如果您试验ksh,您会注意到它的优化程序更具攻击性。例如,它也不会为( echo hello ; ps -o pid,ppid,cmd )分叉子进程。

答案 1 :(得分:1)

可以通过简单地“执行”命令来实现由单个简单命令而不是多个命令的列表或管道组成的子shell,即用所调用命令的进程替换子shell。如果子shell更复杂,则不可能使用简单的exec,子shell必须保持不变以管理命令序列。

从您的诊断中,无法区分bash优化,其中由简单命令组成的子shell优化为“直接”fork和被调用命令的exec或子shell的fork,后跟exec的exec命令叫。这并不奇怪,因为差异(几乎?)完全是学术性的。