十五年测试老手,长期负责WEB\APP 项目测试,目前主要负责团队管理工作。

Linux Shell实现模拟多进程并发执行

上一篇 / 下一篇  2011-06-14 13:45:20 / 个人分类:liunx相关

在bash中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。我们就先实现第一种情况:51Testing软件测试网$VpuY*bZ0P)ca

实例一:正常情况脚本

R1hk0v5d*Q$Vxw,X0

———————————————————————————–

c!S-uzu s`R0

#!/bin/bash
%Q$p7e m*Y2n&U0
;dzQ;_D8Rs0for ((i=0;i<5;i++));do
OX/V6f4_y Lt b0 {
WJ#zQz-Ng/O an0 sleep 1;echo 1>>aa && echo ”done!”51Testing软件测试网%z#KE.r N9Co
 }51Testing软件测试网 `5w?)Kgo
done
}Y-@9N,b~0cat aa|wc -l
7| e8O7HX T0rm aa51Testing软件测试网:x]E)luVOenr-U5z

———————————————————————————–51Testing软件测试网\b*SfhuL

这种情况下,程序顺序执行,每个循环3s,共需15s左右。

on v)_9\0

$ time bash test.sh51Testing软件测试网s)v2__F5A?;J7{
done!51Testing软件测试网? x9?!~4u4[R9Y^&W {8K3H
done!51Testing软件测试网u8hm'pN"Z+b
done!
pJ;kz&T0gJ.~"t0done!
g+M%xP6t5_ Z)t,bu0done!
$Q-L,] pq_5MQ7LpC_05
0I`G%i3L:N0J051Testing软件测试网/R1hl,Ee _ A
real    0m15.030s51Testing软件测试网G]X#N!p'}Yg
user    0m0.002s51Testing软件测试网%vOY U7pk O%]}
sys     0m0.003s

0{-L*p0j.U3{WtE0

实例二:“多进程”实现

7Je0F b)v f{0

———————————————————————————–51Testing软件测试网Th e H(J8}5i[%y"M^

#!/bin/bash51Testing软件测试网 Pa{ `9jR$} l4\
51Testing软件测试网"}f|A0q*_,S
for ((i=0;i<5;i++));do
q'L5^Y;aqJ&r0 {
0R+Wh7cN,B"A0 sleep 3;echo 1>>aa && echo ”done!”
'y\ VGA'l&g-f x0 } &51Testing软件测试网Qiy C.{
done
D,I^4AbM0wait51Testing软件测试网$S:fcGk8i*n/FgU
cat aa|wc -l
x#\ DU)^'x;^ s4Va'V0rm aa

6E%B`_+L+F,RFt)M0

———————————————————————————–51Testing软件测试网_u:LABG n ISZ9E,t

这个实例实际上就在上面基础上多加了一个后台执行&符号,此时应该是5个循环任务并发执行,最后需要3s左右时间。

'tEQo]i8L0

$ time bash test.sh51Testing软件测试网;g-HOJGJ!@U
done!
G*{sT+@ W'g'u0done!
"I"_0sG_Q0done!
9M ug7M-I0done!51Testing软件测试网? T8FO'zTbz
done!51Testing软件测试网1L&aQL5X"MB;}
551Testing软件测试网]J TU5f3gR8X

J;o&p,q/@.n&aN,{\0real    0m3.011s51Testing软件测试网u8i]5S#\"N7`
user    0m0.002s51Testing软件测试网Tw A(k'e#XR
sys     0m0.004s

b'KO YY0

效果非常明显。51Testing软件测试网x{ ?D,SE-? L

这里需要说明一下wait的左右。wait是等待前面的后台任务全部完成才往下执行,否则程序本身是不会等待的,这样对后面依赖前面任务结果的命令来说就可能出错。例如上面wc -l的命令就报错:不存在aa这个文件。51Testing软件测试网0g?Bm;t7ek

以上所讲的实例都是进程数目不可控制的情况,下面描述如何准确控制并发的进程数目。51Testing软件测试网t7z `4C1f*P:?*{e

——————————————————————————————————————

.}S^L4X0

#!/bin/bash51Testing软件测试网B2VT#T"q%mz5V [(h0X4~
# 2006-7-12, by wwy
:Bx:n8@q1GQ0#———————————————————————————–
l5i4I})I{:A0# 此例子说明了一种用wait、read命令模拟多线程的一种技巧51Testing软件测试网9IL1L*j#I
# 此技巧往往用于多主机检查,比如ssh登录、ping等等这种单进程比较慢而不耗费cpu的情况51Testing软件测试网Lb'Mr4K
# 还说明了多线程的控制51Testing软件测试网5_#G-{ K$[$iz
#———————————————————————————–51Testing软件测试网 s/N A5T%ru%jl
51Testing软件测试网*ey9HP(_Ph$u

zZ[6eo$t?^-]0u0function a_sub { # 此处定义一个函数,作为一个线程(子进程)51Testing软件测试网V%A"Z~-a'\H*u$X
sleep 3 # 线程的作用是sleep 3s
G N$K`.UNJ3]N0}
-FW ^KlV7p*E0
6P}:UsPbD051Testing软件测试网v)a b#Kd\r5m@9K
tmp_fifofile=”/tmp/$.fifo”51Testing软件测试网T}%Tgk~'wi
mkfifo $tmp_fifofile      # 新建一个fifo类型的文件51Testing软件测试网VJYWqk
exec 6<>$tmp_fifofile      # 将fd6指向fifo类型
s `B tt&~V0S6U/m/ZN0rm $tmp_fifofile
UA/{3R%i_051Testing软件测试网2D|2AI\*bh6o

5T/J_FB-tQ n9WH0thread=15 # 此处定义线程数51Testing软件测试网:_"q8S&l'kl*x\[L
for ((i=0;i<$thread;i++));do51Testing软件测试网0Nx?kZ9j
echo51Testing软件测试网Ptp| DZi\
done >&6 # 事实上就是在fd6中放置了$thread个回车符
5] zg BR[*~ p;\p!Z0
PQF o;? Zh*J0
W$t*rZU$JTl"]0for ((i=0;i<50;i++));do # 50次循环,可以理解为50个主机,或其他
%}p Td4I-v-_ KbN051Testing软件测试网,k7l/EXZ/VR
read -u6
$d%d8ZK&iC8q0# 一个read -u6命令执行一次,就从fd6中减去一个回车符,然后向下执行,51Testing软件测试网&i(@#Wa%g
# fd6中没有回车符的时候,就停在这了,从而实现了线程数量控制
l:GQ F? k&{H051Testing软件测试网t N:a8q:{fVd x h
{ # 此处子进程开始执行,被放到后台
0Q/Ly#Q]5R l&j0 a_sub && { # 此处可以用来判断子进程的逻辑
y \x8`,dS @E0 echo ”a_sub is finished”51Testing软件测试网a!wbr lU@8aQ F3^
 } || {51Testing软件测试网-n0MZ,FCn3`0b
 echo ”sub error”51Testing软件测试网vd2GOb-WgwJ(K
 }
#[)v*Y+Z3`*@o!^2kI4U0 echo >&6 # 当进程结束以后,再向fd6中加上一个回车符,即补上了read -u6减去的那个51Testing软件测试网8Q*?X wG
} &51Testing软件测试网YD"|8|5S;M%cD
51Testing软件测试网 hwl"\Q0w+i
done51Testing软件测试网&c?2Y#R(otI+K3O

3[ ^o?1J+a0wait # 等待所有的后台子进程结束51Testing软件测试网MA ? aC'G;p#Kh
exec 6>&- # 关闭df6
2u7iJYO2RF;c,y051Testing软件测试网d? RS#E2k2\X
51Testing软件测试网'T6tY&S0Z1PT
exit 0
${zJp'Y|:zz,X h0——————————————————————————————————————

1UR [EZ K2j D0

sleep 3s,线程数为15,一共循环50次,所以,此脚本一共的执行时间大约为12秒51Testing软件测试网__+P@6b

即:
$un+b,Y$BtP2C3w*G015×3=45, 所以 3 x 3s = 9s
,a0A7]RM+qO0(50-45=5)<15, 所以 1 x 3s = 3s51Testing软件测试网7_3j6bA+]
所以 9s + 3s = 12s

%g2h{ YZ'DV0

$ time ./multithread.sh >/dev/null

vhd!J(H/w7t;_0

real        0m12.025s
{]_~3m.}0user        0m0.020s51Testing软件测试网 X8r y;t.m8d[
sys         0m0.064s51Testing软件测试网Y8m$L|yd!u_q P

而当不使用多线程技巧的时候,执行时间为:50 x 3s = 150s。

(a3t6GWH(HeA0

此程序中的命令 mkfifo tmpfile和linux中的命令 mknod tmpfile p效果相同。

2}yH9},A8O+K'?W0

区别是mkfifo为POSIX标准,因此推荐使用它。该命令创建了一个先入先出的管道文件,并为其分配文件标志符6。管道文件是进程之间通信的一种方式,注意这一句很重要51Testing软件测试网%Qpp,@p1U*Qy Y T1[

exec 6<>$tmp_fifofile      # 将fd6指向fifo类型

'a M K(Ez^L'E0

如果没有这句,在向文件$tmp_fifofile或者&6写入数据时,程序会被阻塞,直到有read读出了管道文件中的数据为止。而执行了上面这一句后就可以在程序运行期间不断向fifo类型的文件写入数据而不会阻塞,并且数据会被保存下来以供read程序读出

;ny?W)d%EeW(q0

TAG: shell Shell

 

评分:0

我来说两句

Open Toolbar