后台进程重定向到 COPROC

Posted

技术标签:

【中文标题】后台进程重定向到 COPROC【英文标题】:Background process redirect to COPROC 【发布时间】:2012-06-03 01:07:10 【问题描述】:

在下面的测试脚本中,我运行一个基本的协同进程,内置的 echo 在后台运行,附加其标准输出:

#!/bin/bash
# TEST 1
coproc /bin/sleep 100
echo >&$COPROC[1] &

脚本总是失败,没有明显的原因,给出输出:

./test.sh: line 4: $COPROC[1]: Bad file descriptor

我想知道正确的语法是否应该是这个(在重定向之前移动和号):

#!/bin/bash
# TEST 2
coproc /bin/sleep 100
echo & >&$COPROC[1]

第二个例子似乎可以工作,因为它在执行期间没有报告错误,但是使用这种语法,实际上不会执行重定向;事实上,考虑一下另一个测试:

#!/bin/bash
# TEST 3
/bin/echo abc & >xfile

测试 3 创建文件 xfile,但不向其中写入任何内容。奇怪的是,在重定向后再次尝试定位 & 使 echo 工作正常:

#!/bin/bash
# TEST 4
/bin/echo abc >xfile &

测试 4 在字符串 abc 中创建文件 xfile

了解导致coproc 重定向错误的原因或正确的语法是什么?

【问题讨论】:

在 TEST 2 和 TEST 3 中,& 终止前面的命令,因此输出重定向将应用于后面的 (null) 命令,而不是后台进程。由于没有终止 & 的 TEST 1 很好,我想知道它是否可能是 bash 本身的解析错误。 【参考方案1】:

如其他地方所述,coproc 将其文件描述符安排在子 shell 中关闭。您可以使用

来解决这个问题
coproc  whatever; 
exec WHATEVER[0]<&$COPROC[0]- WHATEVER[1]>&$COPROC[1]-

如果使用 4.3 版之前的 Bash,您必须为输入和输出变量使用单独的变量:

exec IN<&$COPROC[0]- OUT>&$COPROC[1]-

如果使用 4.1 之前的 Bash,您将不得不使用固定的文件描述符编号:

exec 4<&$COPROC[0]- 5>&$COPROC[1]- ; IN=4 OUT=5

对于交互式 shell,您可能需要考虑 disown

这种安排还有一个好处是您可以使用多个协同进程,即使 Bash 手册页说它不受支持。

正如其他地方所讨论的,请注意在进程之间共享管道的局限性。

【讨论】:

【参考方案2】:

你已经在别处得到了答案http://lists.gnu.org/archive/html/bug-bash/2012-06/msg00027.html:

Coproc 文件描述符对子shell 不可用。他们是 使用管道实现,并使管道文件描述符在 subshel​​ls 导致进程挂起并且不能正确终止,这 导致非常难以追踪和重现的错误。

【讨论】:

收到我的那封电子邮件后,我已经很满意谷歌可以为其他(极少数)求职者提供答案。 命名管道(mkfifomktemp 用于脚本中的临时管道)可能更健壮/可预测:因此更容易在脚本中使用而不会出现问题。我未能对使用 coproc -- gitorious.org/rpush-cat/rpush-cat/blobs/continue-coproc/… 运行在 ssh 上的命令读取的信息做出有效的简单反应,因此我改用了 mkfifo

以上是关于后台进程重定向到 COPROC的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统理论操作学习26LInux的后台运行,重定向输出,前后台进程转换和管理

linux后台运行&符号nohup命令输出重定向等使用方法

nohup和&后台运行,进程查看及终止 详解

如何关掉 docker 后台服务进程

nohup和&后台运行,进程查看及终止

nohup和&后台运行,进程查看及终止