1

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

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

$ 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 中进行行缓冲?


经过更多的实验后,我发现我可以在没有的情况下重新创建类似的行为,而只需在catand之间进行管道连接paste

$ 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并一直获得行缓冲
  • 最后,我们通过管道pastecat不是行缓冲

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

4

1 回答 1

0

强制行缓冲的一种方法是使用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
$ 

对于pasteto catcase 的简单管道:

$ stdbuf -oL paste | cat
Hello World!<RETURN>
Hello World!^D
$ 
于 2014-01-07T18:58:12.587 回答