击子shell /管道 - 这部分在子shell执行? [英] Bash subshell/pipelines - which parts are executing in subshells?

查看:74
本文介绍了击子shell /管道 - 这部分在子shell执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一<一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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆