谁在 shell 中分叉了管道命令的进程?

谁在 shell 中分叉了管道命令的进程?

在 shell 中考虑这个命令:ls|less

现在我们知道lsless是作为两个不同的进程运行的。我们知道 shell 分叉并创建一个子进程,该子进程ls使用一系列exec()函数之一加载程序。

我的问题是:谁分叉了执行命令的进程less?是 shell 还是正在执行命令的进程ls

答案1

一些实验:

$ yes | sleep 10m &
[1] 32395 32396
$ pstree -pa $(ps -o ppid= -p $(pgrep yes))
zsh,29630
  ├─pstree,32402 -pa 29630
  ├─sleep,32396 10m
  └─yes,32395

可以看出,两个进程的父进程都是shell。

使用更长的管道:

$ sleep 10m | sleep 10m | sleep 10m | sleep 10m &
[1] 32320 32321 32322 32323
$ pstree -pa $(ps -o ppid= -p $(pgrep sleep -o)) 
zsh,29630
  ├─pstree,32498 -pa 29630
  ├─sleep,32473 10m
  ├─sleep,32474 10m
  ├─sleep,32475 10m
  └─sleep,32476 10m

事实上,这些进程仍然是 shell 的子进程。

带有子外壳:

$ sleep 10m | ( sleep 10m | sleep 10m ) | sleep 10m &
[1] 595 596 597
$ pstree -pa $(ps -o ppid= -p $(pgrep sleep -o))     
zsh,29630
  ├─pstree,610 -pa 29630
  ├─sleep,595 10m
  ├─sleep,597 10m
  └─zsh,596
      ├─sleep,598 10m
      └─sleep,599 10m

答案2

这是外壳;正如您将通过ps命令看到的那样,在这种情况下,PPIDless将是 shell 的 PID。

这些流程lsless没有太多共同点;只是前者的标准输出通过管道传输到后者的标准输入中。

答案3

这取决于您使用的外壳。

尝试拨打:

yourshell -c 'echo bla | read VAR; echo $VAR'

并检查打印的内容。另一项检查是运行:

yourshell -c 'ps -f| more'

使用不同的 shell 并查看 PID 和 PPID。

每个 shell 使用自己不同的方法。

答案4

在那些对管道部分进行分叉的 shell 中,实际上总是由子进程进行分叉。这几乎就是它的全部工作。除了子进程通常无法幸存之外,通常会被被调用的进程替换。

sh -c 'echo "$$"
    sh -c "echo \"\$PPID\"" |
    cat'

14546
14546

...但是如果你只是给孩子任何事物还要做...

sh -c 'echo "$$"
    { sh -c "echo \"\$PPID\""; :; } |
    cat'

14556
14557

……它挂在身边。不过,你实际上不必忍受这一点。

sh -c 'echo "$$"
    { exec sh -c "echo \"\$PPID\""; :; } |
    cat'

14563
14563

相关内容