后台进程重定向到 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 不可用。他们是 使用管道实现,并使管道文件描述符在 subshells 导致进程挂起并且不能正确终止,这 导致非常难以追踪和重现的错误。
【讨论】:
收到我的那封电子邮件后,我已经很满意谷歌可以为其他(极少数)求职者提供答案。 命名管道(mkfifo
和 mktemp
用于脚本中的临时管道)可能更健壮/可预测:因此更容易在脚本中使用而不会出现问题。我未能对使用 coproc
-- gitorious.org/rpush-cat/rpush-cat/blobs/continue-coproc/… 运行在 ssh
上的命令读取的信息做出有效的简单反应,因此我改用了 mkfifo
。以上是关于后台进程重定向到 COPROC的主要内容,如果未能解决你的问题,请参考以下文章