在bash coproc中缓冲线

时间:2014-01-07 18:24:44

标签: bash buffering coproc

我正在尝试使用 coproc而我遇到了困难,最有可能是缓冲。我有一个复杂的命令,它接受来自stdin的面向行的输入,并在每行输入中打印一行到stdout。在命令行中,此命令在每行的基础上正常工作,但是当我将它放在一个coproc中并从${COPROC[0]} FD读取时,读取块。

我可以使用paste重新创建此行为,但不能使用cat重新创建此行为。我希望pastecat在传递任何参数时几乎都做同样的事情。直接在命令提示符下运行时就是这种情况:

$ cat
Hello World!<RETURN>
Hello World!^D
$ paste
Hello World!<RETURN>
Hello World!^D
$ 

RETURN^D已添加以供说明)

但是,当我将它们放在中时,它们的行为有所不同 - cat严格地是行缓冲的,而paste似乎使用更大的缓冲区运行:

$ coproc cat
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC cat
$ 
$ coproc paste
[3] 42657
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
#### read blocks here until ^C ####

我认为原因是paste根据连接的内容调整缓冲模式,而cat始终处于行缓冲模式。

有没有办法强制paste(或其他常规命令)在coproc中进行行缓冲?


经过一些实验后,我发现我可以在没有的情况下重新创建类似的行为,而只是在catpaste之间滚动:

$ cat | cat
Hello World!<RETURN>
Hello World!^D
$ cat | paste
Hello World!<RETURN>
Hello World!^D
$ paste | cat
Hello World!<RETURN>
#### command blocks here until ^C ####

RETURN^D已添加以供说明)

  • 首先我们将cat传递给cat,然后一路缓冲
  • 接下来我们将cat传递给paste并尽可能地获得行缓冲
  • 最后,我们将paste传递给cat并且没有获得行缓冲

这似乎表明paste将在交互模式下对其标准输出进行缓冲,但否则会使用更大的缓冲区。

1 个答案:

答案 0 :(得分:0)

强制行缓冲的一种方法是使用stdbuf coreutils工具(如果有):

stdbuf允许用户修改与程序相关的三个标准I / O流的缓冲操作。

对于coproc案例:

$ coproc stdbuf -oL paste
[3] 42751
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC stdbuf -oL paste
$ 

对于pastecat案例的简单管道:

$ stdbuf -oL paste | cat
Hello World!<RETURN>
Hello World!^D
$