【发布时间】:2020-12-14 12:20:43
【问题描述】:
我试图了解顺序命令组(在 GNU bash 手册中称为“列表”)如何与 POSIX sh 定义或其实现中的管道一起使用。例如以下代码:
if test-expr1; then
cmd1; cmd2; cmd3; ...
fi | { cmd4; cmd5; ...; } | cmd6
这里,管道有两个连续的“列表”和一个命令,其中cmd2 在cmd1 完成之后执行,cmd5 在cmd4 之后执行。但是,这三个都是并行运行的,因此管道不会阻塞。
我的第一个猜测是,对于这些“列表”中的每一个,都会创建一个带有单独 PID 的子 shell,它按顺序执行所有命令,但不会阻止 shell 生成其他进程——如果 shell开始等待cmd1 完成。但这是不正确的,因为即使在管道命令列表中,echo $$ 仍会报告相同的 PID。
问题是:fork()/waitpid() 究竟是如何实现正确行为的?
【问题讨论】:
-
对于
{ list; }没有创建子shell。对于( list ),创建了一个子shell:Command grouping -
Wrt 这是不正确的,因为 echo $$ 仍然报告相同的 PID,不,你错了。 $ 的值在子 shell 中不会改变。
-
尽管立即获得了一些支持,但这个问题的范围并不合理。 POSIX sh 针对各种操作系统开发的实现有很多,如何在一个答案中解释每个 shell 如何实现管道?
-
我明白了,但我仍然不明白这里需要什么样的答案。比如,等待
cmd1完成的是子shell,而不是父shell。除非在后台启动,否则管道确实会阻塞父 shell。除了对您的预测进行此类更正外,我看不出在回答这个问题时还能提供什么。整个问题似乎是基于对我的一连串误解。 -
您是否尝试过使用
set -x跟踪执行或检查系统调用跟踪工具(如strace或truss)生成的输出?这应该让您对正在发生的事情有所了解。