2012-06-03 33 views
2

在下面的测试脚本我运行一个基本的协进程,以使echo内置的,在后台运行,重视其标准输出:后台处理重定向到COPROC

#!/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重定向错误的原因有一些想法或正确的语法是什么?

+0

在TEST 2和TEST 3中,&终止前面的命令,所以输出重定向适用于下面的(空)命令,而不是后台进程。由于TEST 1没有终止&,我不知道它是否可能是bash iteself中的解析错误。 – chepner

回答

0

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

Coproc文件描述符不提供给子shell。他们使用管道实现了 ,并且在 中保留打开管道文件描述符会导致进程挂起并且不能正确终止,这导致很难跟踪并重现错误。

+0

在收到我的电子邮件后,我已经很满意谷歌可以为其他(很少)求职者提供答案。 – davide

+0

命名管道(在脚本中使用'mkfifo'和'mktemp'来实现临时管道)可能更加健壮/可预测:因此更容易在脚本中使用而不会出现问题。我没有对从'coproc'通过ssh'运行的命令读取的信息实施简单的反应 - https://gitorious.org/rpush-cat/rpush-cat/blobs/continue-coproc/ rpush-continue,所以我用'mkfifo'代替。 –

0

正如其他地方所指出的,coproc安排它的文件描述符在subhell中关闭。让您可以在使用

coproc { whatever; } 
exec {WHATEVER[0]}<&${COPROC[0]}- {WHATEVER[1]}>&${COPROC[1]}- 

如果使用之前版本4.3 bash,那么你将不得不使用不同的变量输入&输出变量:

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

如果使用bash 4.1之前,您“将不得不凑合着固定的文件描述符号:

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

对于你可能要考虑disown交互的shell。

这种安排也有好处,即使Bash手册页说不支持,也可以使用多个协处理器。

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