|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
6 J1 s) ^5 c3 A8 T( U& T& R# }% U引言
4 Q3 M$ D7 c m; Gshell,我们经常会用到,以其强大的功能,会帮助我们解决很多棘手的问题。最近遇到一个问题,要跑很多case,如果串行的执行,需要很久。能不能让他们并行起来,但又不能所有case都并行运行呢?,因为所有case同时运行,机器会挂掉的。. n/ z8 {9 a; Z0 E* e
1 v% q. C3 Y! s0 {$ I
1,方式1
: ^. ~6 c% a" E' Q& U比较直接的一种方式是,维护两个文件队列(*.start和*.stop)分别记录所有case的运行状态,然后根据并发数量来获取和分配资源。
% F" }7 ]$ q# p5 R, E+ l
% G: J* d/ u$ m: t代码如下:
4 o' r% l0 k( m8 M) _, w2 t% _
* ^. E0 G8 _, U7 o. p4 smulti.sh:
& f7 s1 ~8 i8 L0 Q$ I: d9 L; X [' y% `3 `# @% K5 ?: ~* Y4 x+ f* M
- #!/bin/bash
- #Rill create to run cases parallel
- #2014-05-22
- #mkdir ./case_status
- #declare -i pc_num
- readonly pc_num = 3
- case_list = "a b c d e f"
- function get_start_num()
- {
- num = 0
- for var in $case_list
- do
- if [ -e $var.start -a -f $var.start]; then
- num = num + 1
- fi
- done
- return $num
- }
- function get_case_stop()
- {
- case $1 in
- "a")
- echo "get case: $1 not stop"
- rerurn 0
- ;;
- "b")
- echo "get case: $1 stop"
- return 1
- ;;
- "c")
- echo "get case: $1 not stop"
- rerurn 0
- ;;
- "d")
- echo "get case: $1 stop"
- rerurn 1
- ;;
- "e")
- echo "get case: $1 stop"
- rerurn 1
- ;;
- "f")
- echo "get case: $1 stop"
- rerurn 1
- ;;
- *)
- echo "case $1 not exist"
- exit 1;
- ;;
- }
- for each_d in ${case_list};
- do
- if [ get_start_num -lt $pc_num ];then
- if [ ! -e $each_d.start ]; then
- if [ ! -e $each_d.stop ]; then
- touch $each_d.start
- #start one new case
- else
- echo "$each_d already stoped"
- rm $each_d.start
- fi
- else
- if [ ! -e $each_d.stop ]; then
- echo "$each_d running......"
- if[ get_case_stop $each_d eq 1];then
- touch $each_d.stop
- rm $each_d.start
- fi
- else
- echo "$each_d error!"
- fi
- fi
- fi
- done
; m+ d: C7 y. k4 f7 F o2 s
9 A. F& {7 f. ~) l# y需要注意的是采用这种方式的话,需要获得每个case的结束状态,这个可以通过case运行结束时的输出log中分析得到。- a0 M' i$ K8 [! m# E0 L3 u% V# w7 U
虽然有awk等强大的工具,但是,分析获得不同case的结束信息仍然是一项艰巨的任务。6 B$ H# r& g% `$ ^' b
& N( U# Q% K0 w2 W/ s
有没有其他的方式呢?
$ C2 r- a" J* y8 B
$ I5 h+ q0 r1 h# R3 X( v有。
3 i+ R! ~- ?4 I6 Q
& W- y4 S$ y) o; [/ {' D- ^- p. U( ?! x' g$ G
2,方式29 ^1 x2 a6 \7 f0 H1 q% j
仔细分析所有的cases开始,结束的情景,发现和fifo文件的特性很类似,于是就想到用fifo来实现并发控制。4 e8 d8 P: S' u1 t; e
) g* p, x* U4 O+ U \% S如下:
( h+ `, T- l- }/ s8 ^5 L. l( Z, s5 A$ X! G) C4 i9 f6 {
multi.sh:- G0 Q! w: {! H) d8 ~) o2 S, _
' k$ Q" Y: f7 j: \& Z. G- #!/bin/bash
- #Rill create to run cases parallel
- #2014-05-22
- case_list="a b c d e f g h i j k l m n o"
- readonly parallel_num=3
- readonly fifo_id=9
- readonly fifo_name=fd2
- readonly log_name=log.log
- #create log file
- if [ -e ${log_name} -a -f ${log_name} ];then
- rm -f ${log_name}
- fi
- touch ${log_name}
- echo "all cases begin time:$(date +%Y-%m-%d-%H:%M:%S)" >>${log_name}
- #create fifo file
- if [ -e ${fifo_name} -a -f ${fifo_name} ];then
- rm -f ${fifo_name}
- fi
- mkfifo ${fifo_name}
- #bind fifo to fifo_id
- eval "exec ${fifo_id}<>${fifo_name}"
- #init fifo
- for (( idx=0;idx<${parallel_num};idx=idx+1 ))
- do
- echo -n -e "1\n" >>${fifo_name}
- done
- #multi main body
- for each_case in ${case_list};
- do
- read -u ${fifo_id}
- {
- echo "${each_case} start:$(date +%Y-%m-%d-%H:%M:%S)" >>${log_name}
- sleep 1 #case running
- echo "${each_case} stoped:$(date +%Y-%m-%d-%H:%M:%S)" >>${log_name}
- echo -ne "1\n" >>${fifo_name}
- } &
- done
- #wait all the cases stoped
- wait
- echo "all cases finish time:$(date +%Y-%m-%d-%H:%M:%S)" >>${log_name}
- #remove the fifo
- rm -f ${fifo_name}
/ P0 ~/ y5 N) ~: r$ y* y + R t6 `8 }/ H8 Z" ~$ U, ]& A) Q
' g c4 w+ }5 k3 e
从中可以发现,我们不需要再为获得case的结束状态而烦恼了。6 B$ r! ~2 e8 q5 Z- ^" J
" J) G, W8 E: \" h' D0 o& o下面是运行结果,一共15个case,每个case运行1秒,并发数量设置为3,所有case运行完需要6.4秒左右。
3 ~- m4 y0 k1 O0 j9 e2 W: u
' [' k/ ?2 i! n1 u# k9 @, b
$ z. A$ ~& {7 p, o- d1 ]+ M) `8 ?
5 l) L' x# }* \2 p+ p" t
3,shell参数传递, x7 }) z' g; r7 z0 w! ]
) X7 f- c- k2 C
% o2 a4 C) W1 E, @' Q/ P
平时我们在使用shell脚本时,往往要向脚本中指定参数,这些参数可以直接写在命令行的后面,但是这样做对参数顺序要求很强,使用起来比较困难。
5 [( b8 a+ i: V! M: B7 i7 [. X( L+ I
/ E7 T3 {% `1 m, t这时我们可以通过在参数前面增加标示来实现。
5 y% d& b( U9 y/ I: F# t. V
; _& m5 t$ w0 D0 M$ p1 a- #!/bin/bash
- #
- # shell test
- # Rill
- # 2014-09-28
- opr1=x
- opr2=x
- opr3=x
- while [ -n "$(echo $1 | grep '-')" ];do
- case $1 in
- -h | --help)
- echo "./test.sh -opr1 a -opr2 b -opr3 c"
- exit 0
- ;;
- -opr1)
- opr1=$2
- shift
- ;;
- -opr2)
- opr2=$2
- shift
- ;;
- -opr3)
- opr3=$2
- shift
- ;;
- esac
- shift
- done
- echo "opr1=${opr1} opr2=${opr2} opr3=${opr3}"( ^4 J. G6 {0 K4 d/ @' I
; v# ^; @" E. e3 Y7 n0 f o- ]2 c1 y) p* S j" f! _% B
验证结果:. d9 n' K8 d6 L; i; W, g
) f/ ? l, ^6 Z y! g) K& b
$ k" b9 W( G0 M6 n! a7 Z+ u+ q0 [- u" @8 B$ m4 I
1 V( m2 Z/ l/ A9 a5 k* J) v4,小结
, X4 X5 K* N8 T, l7 j& z" v* M# n) C0 j! q/ ?4 o5 `$ z; {
shell很久都不用了,本小结就当“朝花夕拾”吧。# u* j6 K2 e' W* L& ^, @0 A
1 U! h4 ~# |& q1 F: N. V6 G
/ F4 O2 v7 G0 s) R5 Z! g0 X, W1 m |
|