在 shell 中考虑这个命令:ls|less
现在我们知道ls
和less
是作为两个不同的进程运行的。我们知道 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。
这些流程ls
并less
没有太多共同点;只是前者的标准输出通过管道传输到后者的标准输入中。
答案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