hac*_*cks 5 bash command subshell
运行命令后
{ sleep 5; } &
Run Code Online (Sandbox Code Playgroud)
输出ps
是(输出1)
PID TTY TIME CMD
972 ttys000 0:00.27 -bash
2556 ttys000 0:00.00 -bash
2557 ttys000 0:00.00 sleep 5
Run Code Online (Sandbox Code Playgroud)
而对于
( sleep 5 ) &
Run Code Online (Sandbox Code Playgroud)
出ps
是(输出 2)
PID TTY TIME CMD
972 ttys000 0:00.28 -bash
2566 ttys000 0:00.00 sleep 5
Run Code Online (Sandbox Code Playgroud)
()
导致子shell环境,我希望在这种情况下为“输出1”,因为它会导致子进程分叉,而我希望{ sleep 5; } &
在当前shell中执行时为“输出2” 。这可能看起来是一个愚蠢的问题,但我真的不明白这种行为。
我在这里缺少什么?
Mic*_*mer 11
bash将运行一个子shell的最后一个或唯一的命令与exec
如果它的数字可以安全地这样做,作为优化。您可以使用以下方法清楚地验证这一点pstree
:
$ pstree $$
bash---pstree
$ ( pstree $$ )
bash---pstree
$ ( pstree $$ ; echo)
bash---bash---pstree
$
Run Code Online (Sandbox Code Playgroud)
这就是为什么您仅( sleep 5 )
显示为sleep
命令,而没有中间外壳的原因。在上面的最后一个例子中,echo
强制 shell 在pstree
完成后做一些事情,所以有一个真正的 shell 可以使用;在中间情况下,生成的 shell 只是立即exec
s pstree
,因此它看起来与第一种情况相同(标准fork-exec)。许多贝壳都这样做。
另一方面,在后台运行的任何东西都需要产生一个新进程:从根本上说,这就是“后台”。在括号中的命令做通常在当前shell中运行,但如果他们在后台运行是不可能发生的。为了在后台命令运行时父 shell 可以继续做它正在做的任何事情,必须创建一个新的 shell 来运行整个{ ... }
。因此
$ { pstree $$ ; }
bash---pstree
$ { pstree $$ ; } &
bash---bash---pstree
Run Code Online (Sandbox Code Playgroud)
在这种情况下,是否有另一个尾随命令没有区别。Bash 记录了以下行为&
:
如果命令由控制运算符“
&
”终止,则 shell 在子 shell 中异步执行命令。这称为在后台执行命令。shell 不等待命令完成,返回状态为 0(真)。
$ read &
$ pstree $$
[1] 32394
[1]+ Stopped read
$ pstree $$
bash-+-bash
`-pstree
Run Code Online (Sandbox Code Playgroud)
我的 shell 现在有两个孩子:一个bash
runningread
和pstree
打印该输出的命令。
确实,shell 可以进行进一步优化并将其应用于背景,{ ... }
就像它对括号内的子shell 所做的那样,但事实并非如此。其他一些 shell 可能会这样做,但我还没有在快速测试中找到一个。这是一个非常罕见的情况并且形式上不同,并且有一些奇怪的极端情况。
归档时间: |
|
查看次数: |
3783 次 |
最近记录: |