linux – 如果之后使用管道,为什么wait生成“不是这个shell的子
在下面我创建一个后台进程并等待它完成.
$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) 我每次都可以重现等待错误. 也许等待$! command在错误的shell中查找子进程. 有相关问题q1和q2.但是在内置等待之后没有管道使用. 更新 我对&和bash之间的bash中的运算符优先级有误解.和|. @randomir在他的answer中指出了这一点.添加花括号使得等待先前的后台进程等待.例如: { bash -c "sleep 5 | false" & wait $! ; } | true 这不会返回相同的等待错误. 解决方法
这里有两个要点:
> wait(内置shell)只能等待(shell的)子进程 所以,当你说: cmd & wait $! 然后cmd在你当前的shell中运行,在后台运行,而wait(作为shell的内置)可以等待cmd的PID,因为cmd是那个shell的子代(因此是等待的子代). 另一方面,当你说: cmd & wait $! | cmd2 那么cmd仍然在你当前的shell中运行,但是管道会引入一个新的子shell用于等待(一个新的bash进程),其中cmd不是它的子进程,而wait不能等待它的兄弟(它的父进程的子进程). 作为shell语法的另一个澄清 – &运算符(以及;,&&和||)分隔管道,形成列表.因此,列表是一系列管道,而管道是由|分隔的一系列命令. 这意味着上面的最后一个例子相当于: cmd & { wait $! | cmd2; } 而不是这个: { cmd & wait $! ; } | cmd2 这相当于你的预期. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |