Bash coproc - unexpected behavior

Tracking

Given that the obvious use of coproc does not work, as I expected, as seen from:

$ cat test.sh coproc cat auto/etc/build.cfg while read -u ${COPROC[0]} BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS do echo hello done $ bash -x test.sh + read -u 63 BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS + cat auto/etc/build.cfg + echo hello hello + read -u BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS test.sh: line 2: read: BRANCH: invalid file descriptor specification 

Question: Why does coproc go away after the script reads one line of output?

0
source share
1 answer

I can not reproduce:

 bash-4.1 $ cat infile one two three four five bash-4.1 $ cat s.sh coproc cat infile while read -u ${COPROC[0]} v; do echo "$v" done bash-4.1 $ bash -x s.sh + read -u 63 v + cat infile + echo one one + read -u 63 v + echo two two + read -u 63 v + echo three three + read -u 63 v + echo four four + read -u 63 v + echo five five + read -u 63 v + echo '' + read -u 63 v 

Edit: I reproduced it as follows:

 bash-4.1 $ cat s.sh coproc cat infile sleep 1 while read -u ${COPROC[0]} v; do echo "$v" done bash-4.1 $ bash -x s.sh + sleep 1 + cat infile + read -uv s.sh: line 5: read: v: invalid file descriptor specification 

Edit: see comments below.


It seems that the collaborative process is running out quickly ... Maybe your system is slow :)

No, a command executed as a collaborative process is too fast, if you slow it down, it works:


 bash-4.1 $ cat s.sh coproc while read -r; do printf '%s\n' "$REPLY" sleep 1 done < infile sleep 1 while read -u ${COPROC[0]} v; do echo "$v" done bash-4.1 $ bash s.sh one two three four five 

In any case, I believe this test case is not suitable. You need a collaborative process when you need a two-way pipe (i.e. you need to talk to a joint process). You can use one database connection (database connections are expensive resources) and go back and forth with your queries and shell code.

Edit (see comments below). Issues related to stdin buffering may be with some non-standard tools (in this case stdbuf is used (I think this is part of the latest GNU coreutils):

 ~/t$ cat s coproc stdbuf -oL -i0 mysql printf '%s;\n' 'show databases' >&${COPROC[1]} printf '\n\nshowing databases, fisrt time ...\n\n\n' while read -t3 -u${COPROC[0]}; do printf '%s\n' "$REPLY" [[ $REPLY == test ]] && { printf '%s\n' 'test found, dropping it ...' printf '%s;\n' 'drop database test' >&${COPROC[1]} } done printf '\n\nshowing databases, second time ...\n\n\n' printf '%s;\n' 'show databases' >&${COPROC[1]} while read -t3 -u${COPROC[0]}; do printf '%s\n' "$REPLY" done printf '%s\n' quit >&${COPROC[1]} 

Output:

 ~/t$ bash s showing databases, fisrt time ... Database information_schema mysql sakila test test found, dropping it ... world showing databases, second time ... Database information_schema mysql sakila world 

I understand that this approach has many drawbacks ...

+4
source

All Articles