Locations of visitors to this page

Wednesday, May 27, 2009

co-process in shell Shell中的协进程

co-process in shell
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 CoprocessesThe 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:

Website Analytics

Followers