bash协处理器中的行缓冲



我正在尝试使用bashcoproc,但遇到了困难,很可能是缓冲问题。我有一个复杂的命令,它接受来自stdin的面向行的输入,并在每行输入中将一行打印到stdout。在命令行中,该命令每行运行良好,但当我将其放入协处理器并从${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(或其他通用命令)在协处理器中进行行缓冲?


经过更多的实验,我发现我可以在没有协处理器的情况下重新创建类似的行为,而只是在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在交互模式下将对其stdout进行行缓冲,但除此之外,它将使用更大的缓冲区。

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

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
$ 

相关内容

  • 没有找到相关文章

最新更新