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

问题:为什么脚本读取一行输出后 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

无论如何,我认为这个测试用例是不合适的。当您需要双向管道(即您需要与协同进程聊天)时,您需要一个协同进程。您可以使用单个数据库连接(数据库连接很耗费资源),然后来回处理您的查询和 shell 代码。

编辑(见下面的评论)。与标准输入缓冲相关的问题可以使用一些非标准工具来解决(在这种情况下使用 stdbuf 我相信是最新版本的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]}

输出:

~/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

我意识到这种方法有很多缺点......

于 2011-10-07T15:24:23.593 回答