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