跟进
鉴于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会消失?
答案 0 :(得分:4)
我无法重现:
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代码。
编辑(见下面的评论)。 与 stdin 缓冲相关的问题可以解决 使用一些非标准工具(在这种情况下使用 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
我意识到这种方法有许多缺点......