3

在下面的测试脚本中,我运行了一个基本的协同进程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 &

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

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

4

2 回答 2

3

如其他地方所述,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 手册页说它不受支持。

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

于 2017-11-10T00:37:55.257 回答
2

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

Coproc 文件描述符对子shell 不可用。它们是使用管道实现的,并且在子外壳中打开管道文件描述符会导致进程挂起并且无法正确终止,从而导致非常难以追踪和重现的错误。

于 2012-08-30T03:23:41.363 回答