gpt4 book ai didi

linux - 如果之后使用管道,为什么 wait 会生成 “ is not a child of this shell” 错误?

转载 作者:IT王子 更新时间:2023-10-29 00:57:23 24 4
gpt4 key购买 nike

在下文中,我创建了一个后台进程并等待它完成。

$ bash -c "sleep 5 | false"  &  wait $!
[1] 46950
[1]+ Exit 1 bash -c "sleep 5 | false"
$ echo $?
1

这有效,提示在 5 秒后返回。

但是,如果我在它之后再使用一个管道,wait 会返回一个错误。

$ bash -c "sleep 5 | false"  &  wait $!  | true
[1] 49493
-bash: wait: pid 49493 is not a child of this shell
hbaba@mbp-005063:~/misc$ echo $?
0
hbaba@mbp-005063:~/misc$ ps -T -f
UID PID PPID C STIME TTY TIME CMD
980771313 49493 69771 0 12:56AM ttys056 0:00.00 bash -c sleep 5 | false
980771313 49498 49493 0 12:56AM ttys056 0:00.00 sleep 5
0 49555 69771 0 12:56AM ttys056 0:00.01 ps -T -f

这里发生了什么?


我正在使用 bash 版本 GNU bash,版本 3.2.57(1)-release (x86_64-apple-darwin15)

我每次都可以重现等待错误。我认为这与每个管道都是一个单独的子 shell 有关。 https://unix.stackexchange.com/a/127346/212862

也许等待$!命令在错误的 shell 中查找子进程。错误消息提到 49493 pid。这确实是 bash -c … 命令的正确 pid。 ps -T 显示了这一点。

有相关问题q1q2 .但是在它们中,在 wait 内置之后没有管道使用。

更新

我对 bash 中 &| 之间的运算符优先级有误解。 @randomir 在他的 answer 中指出了这一点.添加花括号使 wait 等待先前的后台进程。例如:

{ bash -c "sleep 5 | false"  &  wait $! ; } | true

这不会返回相同的等待错误。

最佳答案

这里有两个关键点需要注意:

  • wait(内置 shell)只能等待(shell 的) child
  • 管道中的每个命令都在单独的子 shell 中运行

所以,当你说:

cmd & wait $!

然后 cmd 在您当前的 shell 中在后台运行,wait(作为 shell 的内置)可以在 cmd 上等待的 PID,因为 cmd 是该 shell 的子级(因此是 wait 的子级)。

另一方面,当你说:

cmd & wait $! | cmd2

然后 cmd 仍然在您当前的 shell 中运行,但是管道为 wait 引入了一个新的子 shell(一个新的 bash 进程),其中 cmd 不是它的 child ,并且 wait 不能等待它的兄弟 (其 parent 的 child )。

作为对 shell 语法的额外说明 - & 运算符(以及 ;&&||) 分隔管道,形成列表。因此,列表管道 的序列,管道| 分隔的命令序列。

这意味着上面的最后一个例子等同于:

cmd & { wait $! | cmd2; }

并且:

{ cmd & wait $! ; } | cmd2

这等同于您的预期。

关于linux - 如果之后使用管道,为什么 wait 会生成 “<pid> is not a child of this shell” 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46752794/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com