0

フォローアップ

以下に示すように、coprocの明らかな使用が期待どおりに機能しないことを考えると、

$ 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

質問:スクリプトが1行の出力を読み取った後、coprocがなくなるのはなぜですか?

4

1 に答える 1

3

再現できません:

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

編集:私はそれを次のように再現しました:

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 -u v
s.sh: line 5: read: v: invalid file descriptor specification

編集:以下のコメントを参照してください。


コプロセスはすぐにタイムアウトするようです...システムが遅い可能性があります:)

いいえ、コプロセスとして実行されるコマンドは速すぎます。速度を落とすと、次のように機能します。


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

Anyway, I believe that this test case is not appropriate. You need a co-process when you need a two-way pipe (i.e. you need to chat with the co-process). You can use a single database connection (the database connections are resource expensive) and go back and forth with your queries and shell code.

Edit (see comments below). The issues related to the stdin buffering could be worked around with some non standard tools (in this case stdbuf is used (part of recent versions of the GNU coreutils, I believe):

~/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 realize this approach has many drawbacks ...

于 2011-10-07T15:24:23.593 に答える