后台流程重定向到COPROC

时间:2012-06-03 01:07:10

标签: bash ipc pipe io-redirection coproc

在下面的测试脚本中,我运行一个基本的协同进程,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在字符串xfile内创建文件abc

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

2 个答案:

答案 0 :(得分:2)

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

解决这个问题
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手册页说它不受支持。

正如其他地方所讨论的那样,要注意在进程之间共享管道的限制。

答案 1 :(得分:1)

你在其他地方得到了答案http://lists.gnu.org/archive/html/bug-bash/2012-06/msg00027.html

  

Coproc文件描述符不适用于子shell。他们是   使用管道实现,并打开管道文件描述符   子shell导致进程挂起并且没有正确终止,这就是   导致非常难以追踪和重现的错误。