bas*_*ful 30 shell bash shell-script subshell
我似乎误解了创建子 shell 的 Bash 规则。我认为括号总是会创建一个子shell,它作为自己的进程运行。
然而,情况似乎并非如此。在代码片段 A(如下)中,第二个sleep命令不在单独的 shell 中运行(由pstree在另一个终端中确定)。但是,在代码片段 B 中,第二个sleep命令确实在单独的 shell中运行。片段之间的唯一区别是第二个片段在括号内有两个命令。
有人可以解释一下何时创建子shell的规则吗?
代码片段 A:
sleep 5
(
sleep 5
)
Run Code Online (Sandbox Code Playgroud)
代码片段 B:
sleep 5
(
x=1
sleep 5
)
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 25
括号总是开始一个子shell。发生的事情是 bash 检测到这sleep 5是该子shell执行的最后一个命令,因此它调用exec而不是fork+ exec。该sleep命令在同一进程中替换子shell。
换句话说,基本情况是:
( … )创建一个子外壳。原始进程调用fork和wait。在子进程中,这是一个子shell:
sleep是需要子进程的子进程的外部命令。子shell调用fork和wait。在子进程中:
exec.exit.wait 在子shell中完成。wait 在原始过程中完成。优化是:
( … )创建一个子外壳。原始进程调用fork和wait。在子进程中,它是一个子shell,直到它调用exec:
sleep 是一个外部命令,它是这个进程需要做的最后一件事。exec.exit.wait 在原始过程中完成。当您在调用 之后添加其他内容时sleep,需要保留子外壳,因此不会发生这种优化。
当您在调用 之前添加其他内容时sleep,可以进行优化(ksh 会这样做),但 bash 不会这样做(这种优化非常保守)。
来自高级 Bash 编程指南:
“一般来说,脚本中的外部命令会派生出一个子进程,而 Bash 内置命令不会。因此,与外部命令等效项相比,内置命令执行速度更快,使用的系统资源更少。”
再往下一点:
“括号之间嵌入的命令列表作为子shell运行。”
例子:
[root@talara test]# echo $BASHPID
10792
[root@talara test]# (echo $BASHPID)
4087
[root@talara test]# (echo $BASHPID)
4088
[root@talara test]# (echo $BASHPID)
4089
Run Code Online (Sandbox Code Playgroud)
使用 OPs 代码的示例(睡眠时间较短,因为我不耐烦):
echo $BASHPID
sleep 2
(
echo $BASHPID
sleep 2
echo $BASHPID
)
Run Code Online (Sandbox Code Playgroud)
输出:
[root@talara test]# bash sub_bash
6606
6608
6608
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14826 次 |
| 最近记录: |