为什么在子shell中不执行单命令管道?

时间:2018-03-30 17:24:02

标签: bash

版本4.4.19的bash手册页说:

  

管道

     

管道是由一个控制操作符||&分隔的一个或多个命令的序列。管道的格式是:

     

[time [-p]] [ ! ] command [ [|||&] command2 ... ]

不确定。那讲得通。然后,在该部分的后面:

  

管道中的每个命令都作为一个单独的进程执行(即在子shell中)。

同样合理,也很容易证明:

$ pwd
/Users/ravron
$ ls | grep src  # yes, src _does_ exist
src
$ cd src | true  # cd in subshell has no effect on parent session
$ pwd
/Users/ravron

但是,我注意到上面的管道定义的措辞使得即使是简单的命令也是管道。毕竟,在语法中,除command之外的所有内容都是可选的:

[time [-p]] [ ! ] command [ [|||&] command2 ... ]

现在,当然,运行甚至单个命令 - 在man bash术语中,“简单命令” - 在子壳中实际上是非常无用的。 cd不起作用,变量设置不起作用等等。然而,现实 - 简单的命令,尽管匹配(相当简并)管道的语法,不在子壳中执行 - 似乎在手册的几率。在列表表格中,这是我的理解:

  • 管道的语法意味着简单的命令也是管道。
  • 手册页说管道中的命令在子shell中运行。
  • 简单命令不会在子shell中运行。

我错过了什么,或者这是man bash中无可否认的无关紧要的错误?

2 个答案:

答案 0 :(得分:3)

手册简直不精确。 POSIX规范(第2.12节)更明确(我添加了粗体):

  

此外,多命令管道的每个命令都在一个   子shell 环境;但是,作为扩展,中的任何或所有命令   管道可以在当前环境中执行。所有其他   命令应在当前的shell环境中执行。

默认情况下,

bash将每个子shell的实现位置作为子进程。 (lastpipe 4.2中引入的bash选项允许最终命令在当前shell环境/进程中执行。)

shell的语法说管道可以包含一个或多个命令,但是shell的语义区分了一个命令的管道和两个或多个命令的管道。

答案 1 :(得分:1)

手册永远不会定义单词" subshel​​l"。虽然您可能直观地假设子shell始终是原始shell的子进程,但是单个命令的退化情况使用原始shell进程作为子shell。

其他一些shell更进一步,总是在原始shell的管道中运行最后一个命令。