在我可以等待 coproc 之前,Bash 取消了 *_PID 变量的设置

Feu*_*mel 5 bash process

我正在尝试使用进程将异步进程的输出通过管道传输到其他 shell 命令,然后检查异步进程的退出状态:

coproc LS { ls dir; }
while IFS= read i; do echo "$i"; done <&"$LS" # Do something with the output.
wait "$LS_PID"; echo $? # Check exit status.
Run Code Online (Sandbox Code Playgroud)

问题是上面的代码不起作用,至少在 Bash 中不起作用4.3.46(1)-release。在之后while的语句已经执行,bash将取消设置$LS_PID(可能是因为它注意到,这一进程已经终止)。调用wait进程仍然有效,例如:

coproc LS { ls dir; }
P=$LS_PID
while IFS= read i; do echo "$i"; done <&"$LS" # Do something with the output.
wait "$P"; echo $? # Check exit status.
Run Code Online (Sandbox Code Playgroud)

这将打印02取决于目录是否存在。因此,我必须将 PID 保存到另一个变量中,这很不方便。但我对为什么会发生这种情况以及我是否可以影响这一点很感兴趣。

为什么$LS_PID在我之前未设置wait进程?这种行为是否记录在某处?是否有一个简单的解决方法,因为我认为这是一个常见的用例,既使用命令的输出又检查其退出代码。

Kus*_*nda 4

这是该变量的预期行为COPROC_PID,尽管 Bash 手册中没有记录。

正确的解决方法是完全按照你已经做过的事情去做;将 的值保存$COPROC_PID在一个变量中,当协进程退出时该变量不会被取消设置。

请注意,如果协进程在您有时间获取其 PID 之前退出,则这将不起作用,因此在使用变量之前确保变量具有值可能是谨慎的做法

参考:http://gnu-bash.2382.n7.nabble.com/Several-issues-with-coprocesses-regarding-exit-status-td11125.html

  • 或者使用“$!”代替“$LS_PID”,这样就没有问题。请注意,它与“$LS”变量相同。可能最好放弃 bash 中的 coprocs 或使用具有适当 coproc 实现的 shell,或者完全避免 coproc,因为通常有更好的方法来做事情。请参阅[如何在 Bash 中使用 coproc 命令?](//unix.stackexchange.com/a/86372) (2认同)