在下面的测试脚本中,我运行一个基本的协同进程,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
重定向错误的原因或正确的语法是什么?
答案 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导致进程挂起并且没有正确终止,这就是 导致非常难以追踪和重现的错误。