Shell中的协进程
今日阅读第147期Log Buffer, 有重大发现
其中一篇文章"How to reuse connection in shell"提到了协同进程(coprocess)的概念, 介绍了使用协进程重用数据库连接的方法
1.文章中的例子
脚本1, 用嵌入文档(here document)重定向的方式, 向sqlplus发送命令序列, 运行2次, 取得2个表的行数.
countlines() {
c=$(sqlplus -s /nolog <<EOF | grep -v Connected
connect sarpt/sarpt
set feed off head off
select count(*) from $1;
EOF
)
echo there are $c lines in $1
}
countlines CHANNEL
countlines CHANNEL_STATE
运行结果$ time ksh script1 there are 70 lines in CHANNEL there are 116 lines in CHANNEL_STATE real 0m0.083s user 0m0.017s sys 0m0.024s
脚本2, 起一个sqlplus作为协同进程, 然后向协同进程发送命令/接受返回的结果
sqlplus -s /nolog |&
print -p "connect sarpt/sarpt"
read -p line
if [ $line != Connected. ]
then
exit 1
fi
print -p "set feed off head off"
countlines() {
print -p "select count(*) from $1;"
read -p line
read -p c
echo "there is $c lines in $1"
}
countlines CHANNEL
countlines CHANNEL_STATE
print -p disconnect
运行结果$ time ksh script2 there is 70 lines in CHANNEL there is 116 lines in CHANNEL_STATE real 0m0.042s user 0m0.001s sys 0m0.002s因为只起了一次sqlplus,重用了数据库连接,比第一种方式快了很多
2. 协进程
其实就是在命令后加上"|&", 后台的启动一个进程, 并自动创建一个双向的管道通信. 用"print -p"向协进程发送命令, 用"read -p"从协进程获取返回信息. 可以在Shell脚本里实现以交互的方式同另一个进程(协进程)的协同工作. 而前面script1中的嵌入文档(here document)方法只能一次性的向某进程发送全部命令, 不能在运行时根据返回结果, 动态的决定下步操作命令.
ksh协进程的使用,见Coprocesses and Background jobs
协进程是在ksh93(Korn Shell)提出的功能, 在bash(Bourne-Again Shell)中用不了. bash4.0才支持协进程, 调用方法跟ksh也有所不同, 请见bash manual 3.2.5 Coprocesses和The coproc keyword
3. 用命名管道(named pipe)实现协进程
脚本3, 显式的创建2个命名管道, 一个用于输入, 另一个用于输出
mkfifo p_in
mkfifo p_out
(trap "rm -f p_in p_out" 0; sqlplus -s /nolog <p_in >p_out; ) &
exec 4>p_in 5<p_out
echo "connect sarpt/sarpt" >&4
read line <&5
echo "set feed off head off" >&4
countlines() {
echo "select count(*) from $1;" >&4
read line <&5
read c <&5
echo "there is $c lines in $1"
}
countlines CHANNEL
countlines CHANNEL_STATE
echo disconnect >&4
exec 4>&- 5<&-
运行结果$ time ksh script3 there is 70 lines in CHANNEL there is 116 lines in CHANNEL_STATE real 0m0.045s user 0m0.002s sys 0m0.002s实现了类似ksh协进程的功能, 这可用于bash中
$ time bash script3 there is 70 lines in CHANNEL there is 116 lines in CHANNEL_STATE real 0m0.048s user 0m0.002s sys 0m0.005s文章Discovering Web Access Latencies Using Bash Co-Processing有一个更完善的例子
-fin-

No comments:
Post a Comment