击子shell /管道 - 这部分在子shell执行? [英] Bash subshell/pipelines - which parts are executing in subshells?
问题描述
在一<一href=\"http://stackoverflow.com/questions/9108181/append-output-of-one-command-to-the-output-of-another-in-a-single-command/9108410#comment11442552_9108410\">comment在另一个帖子,@JonathanLeffler指出:
In a comment on another post, @JonathanLeffler stated that:
{...} | somecommand在子壳运行,并且不影响
父shell。演示:
{ ... } | somecommand is run in a sub-shell and doesn't affect the parent shell. Demo:
X = PQR;回声$ X; {X = ABC;回声$ X; } |猫;回声$ X
(带输出PQR,ABC,PQR三线)
(with output PQR, ABC, PQR on three lines)
确实
james@bodacious-wired:tmp$X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
PQR
ABC
PQR
然而,男人庆典
表示, {...}
不在一个子shell执行:
However, man bash
says that { .. }
does not execute in a subshell:
{ list; }
list is simply executed in the current shell environment. list must be
terminated with a newline or semicolon. This is known as a group command.
那么是什么回事?为男人庆典
错了吗?我知道一个管道的每个部分子shell执行;但我不认为这是如何引起的观察到的行为。例如:
So what's going on here? Is man bash
wrong? I know that each part of a pipeline executes in a subshell; but I don't see how that causes the observed behaviour. For instance:
james@bodacious-wired:tmp$X=PQR; echo $X | sed; X=ABC; echo $X | sed; echo $X
PQR
ABC
ABC
编辑补充:
有几个人使用建议回声$$
来表明事情(或者不是)一个子shell的部分。这是不是在所有有用的,因为 $
在参数扩展阶段,这恰好长在执行任何命令之前被扩大了。
A few people have suggested using echo $$
to show that things are (or are not) parts of a subshell. This is not at all useful, as the $$
gets expanded during the parameter expansion stage, which happens long before any commands are executed.
作为一个例子:
james@bodacious-wired:tmp$echo 1$$; ps; ( echo 2$$; ps ); echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
7894 ttys000 0:00.00 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
james@bodacious-wired:tmp$
您可以看到 PS
的第二次调用发生子shell里面,具有pid 7894
;但 2呼应$$
仍然显示在bash的变量扩张阶段取代的价值,它催生了子shell之前
You can see that the second invocation of ps
happened inside a subshell, with pid 7894
; but echo 2$$
still shows the value that bash substituted in the variable expansion phase, before it spawned the subshell
有关的对比,并表明 {...}
做的不的产卵子shell:
For contrast, and demonstrating that { .. }
does not spawn a subshell:
james@bodacious-wired:tmp$echo 1$$; ps; { echo 2$$; ps; }; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.23 -bash
只是为了证明@nos是正确的,管道添加到上面:
Just to prove that @nos is correct, add a pipeline to the above:
james@bodacious-wired:tmp$echo 1$$; ps; { echo 2$$; ps; } | sed ; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
7945 ttys000 0:00.00 -bash
7946 ttys000 0:00.00 sed
31194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
如所预期的,壳产卵2子shell,一个用于管道的两侧。
As expected, the shell spawns two subshells, one for each side of the pipeline.
推荐答案
一个流水线的每一侧变成一个子shell最少。
Each side of a pipeline becomes a subshell at least.
X = PQR;回声$ X; {X = ABC;回声$ X; } |猫;回声$ X
将会使,ATLEAST {X = ABC子shell /进程;回声$ X; }
和猫
。
will make a subshell/process of , atleast { X=ABC; echo $X; }
and cat
.
管道中的每个命令被作为一个单独的过程(即,在子shell)执行。 ,从人的bash
"Each command in a pipeline is executed as a separate process (i.e., in a subshell)." , from man bash
如果你不是做
X = PQR;回声$ X; {X = ABC;回声$ X; };回音|猫;回声$ X
您会看到这事后回声$ X
显示ABC。
You'll see afterwards that echo $X
shows ABC.
有这么命令在子shell执行过其它方式,例如如果背景子命令: {X = SUB;睡眠1; }&安培;
,该组将在一个子shell中运行,而只是 {X = SUB;睡眠1; }
不会的。
There's other ways that commands are executed in subshells too, e.g. if you background a subcommand: { X=SUB ; sleep 1; } &
, that group will run in a subshell, whereas just { X=SUB ; sleep 1; }
will not.
如果你想组命令,总是以一个子shell执行,使用括号,(X = ABC;回声$ X)。
而不是括号
If you want to group commands that always execute in a subshell, use parenthesis, (X=ABC ; echo $X)
instead of braces.
这篇关于击子shell /管道 - 这部分在子shell执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!