bash - 检索协同进程的输出和退出代码
问题描述
我必须在bash
. 所以我最终得到了以下结果,但奇怪的是,我不知道它为什么会起作用:
coproc { sleep 30 && echo "Output" && exit 3; }
# Saving the coprocess's PID for later, as COPROC_PID apparently unsets when its finished
COPROC_PID_backup=$COPROC_PID
# Retrieving the coprocess's output
output=$(cat <&$COPROC)
# Retrieving the coprocess's exit code
wait $COPROC_PID_backup
# Echoing out the results
echo $?
echo $output
我“成功”得到以下输出:
3
Output
这里有很多我不明白的事情:
- 如何
cat
从该文件描述符中读取协同进程的输出?我认为这些取决于过程。因此,如果bash
扩展$COPROC
为51
,那么这个改写应该意味着“stdin
从这个进程的FD 51
流中读取”; coproc
如果协同进程结束,则在和命令之间调用cat
命令会使后者失败,并给出错误bash: $COPROC : ambiguous redirection
,例如,如果我使用 while 循环等待:
coproc { sleep 30 && echo "Output" && exit 3; }
while kill -0 $COPROC_PID_backup &>/dev/null ; do
sleep 1
done
output=$(cat <&$COPROC) # Fails
- 如何
wait
获取协同进程的退出代码,因为它已经结束。被存储直到它被读取一次?如果有,在哪里?
我一定误解了重定向是如何工作的,因为我真的不明白如何cat
能够获得协同进程的输出。
PS:测试是在交互式外壳中完成的。
解决方案
cat <&$COPROC
因此,如果 bash 扩展
$COPROC
为51
,那么这个改写应该意味着“从这个进程的 FD 51 的流中读取标准输入”;
不,这意味着:fork 一个单独的进程(它将从其父进程继承dup2(51, 0)
所有打开的 fds),使 fd 0(stdin)成为 fd 51 的别名(就是这样<&
做的)然后 exec cat
,它将再次继承所有打开的 fds(包括stdin = 0),除了那些标有O_CLOEXEC
(我敢打赌$COPROC
= 51的情况)。
注意它$COPROC
实际上是一个数组:使用数组作为简单变量 inbash
将检索它的第一个元素:$COPROC
与 相同${COPROC[0]}
,即它的读取端。
在和命令
sleep
之间放置一个命令会使后者失败,并给出错误 bash: ;coproc
cat
$COPROC : ambiguous redirection
bash
$COPROC
一旦协进程终止,将取消设置变量(或任何协进程名称)。所以cat <&$COPROC
会产生与cat <&$no_such_variable
. 例子:
$ coproc foo { true; }; sleep 1; echo foo=$foo; true <&$foo
[5] 4658
[5] Done coproc foo { true; }
foo=
bash: $foo: ambiguous redirect
$ coproc foo { sleep 2; }; sleep 1; echo foo=$foo; true <&$foo
[5] 4664
foo=61
在第二种情况下,协同进程将比sleep 1
.
如何
wait
获取协同进程的退出代码,因为它已经结束。被存储直到它被读取一次?如果有,在哪里?
bash
将自称为wait(2)
或waitpid(2)
类似的系统调用,并将子进程的状态存储在其内存中的某个位置。请注意,bash 正在贪婪地等待它的孩子;在脚本关心它们之前,它不会留下僵尸进程wait
(正如一些评论所暗示的那样)。这就是为什么$!
或者您$COPROC_PID_backup
并不总是可靠的原因——当您使用它们时,它们可能已经被重用于另一个进程。
推荐阅读
- r - 取消组合 SparkR 数据框
- r - 循环读取工作表并将工作表添加为 R 中的另一列
- csv - 在 xslt 中将 CSV 记录长度限制为 100 个字符
- javascript - 为 Socket.io ID 分配用户名
- file - 无法上传文件
- javascript - 增量变量不更新角度模板中的数组列表
- ios - 使用 UIImagePickerController 更改图像时,图像会更改,然后应用程序会返回上一页?
- python - 如何在 python 中解码这个字符串?
- java - 远程调试器挂起最新版本的 IntelliJ IDEA 2018.3
- angular - 在 Angular httpclient 获取请求上覆盖基本 URL