I'm trying to use a bash coproc
and I'm running into difficulties, most likely with buffering. I have a complex command which accepts line-oriented input from stdin and prints a line to stdout, per line of input. At the command-line this command works fine on a per-line basis, but when I put it in a coproc and read from the ${COPROC[0]}
FD, the read blocks.
I can recreate this behavior with paste
, but not with cat
. I expect paste
and cat
to pretty much do the same thing when passed no parameters. This is the case when running directly at the command prompt:
$ cat
Hello World!<RETURN>
Hello World!^D
$ paste
Hello World!<RETURN>
Hello World!^D
$
(RETURN
and ^D
added for illustration)
But when I put these in a coproc, they behave differently - cat
is strictly line-buffered, whereas paste
appears to be operating with a much larger buffer:
$ 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 ####
I think the reason for this is that paste
adjusts its buffering mode, depending on what it is connected to, whereas cat
is always in line-buffering mode.
Is there any way to force paste
(or other general command) to be line buffered in the coproc?
After a bit more experimentation I found I can recreate similar behavior without coprocs and instead just piping between cat
and 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
and ^D
added for illustration)
- First we pipe
cat
tocat
and get line buffering all the way though - Next we pipe
cat
topaste
and also get line buffering all the way though - Lastly we pipe
paste
tocat
and don't get line buffering
This appears to indicate that paste
will line buffer its stdout when in interactive mode, but otherwise it will use a much bigger buffer.