|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
$ t& R/ H; K; H2 e引言) \6 q/ q* e0 s
shell,我们经常会用到,以其强大的功能,会帮助我们解决很多棘手的问题。最近遇到一个问题,要跑很多case,如果串行的执行,需要很久。能不能让他们并行起来,但又不能所有case都并行运行呢?,因为所有case同时运行,机器会挂掉的。
6 M- U( s2 H: p0 S- R$ e& z) m1 A3 {! p! L3 R' K
1,方式1. C" i' r$ a+ ~ J
比较直接的一种方式是,维护两个文件队列(*.start和*.stop)分别记录所有case的运行状态,然后根据并发数量来获取和分配资源。4 I& F8 F2 d" G
4 D6 K9 C F$ F代码如下:% N- G5 Y6 }. a0 N
0 `6 T9 X$ `* v) N2 _) F7 {
multi.sh:
' p- q* {) `+ E) U6 k
# P6 J, D4 s9 K8 K& H- { G+ v- #!/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
, U4 W: f2 n2 k7 G' s1 r 6 ~) f8 n: c$ _2 D8 f
需要注意的是采用这种方式的话,需要获得每个case的结束状态,这个可以通过case运行结束时的输出log中分析得到。
) u: ]" K' |) ~* y. `& U3 K虽然有awk等强大的工具,但是,分析获得不同case的结束信息仍然是一项艰巨的任务。
6 Z0 J3 r9 T0 ~1 N; e* i' p& q, T( Z' @. }2 Y
有没有其他的方式呢?
' v1 J6 [* U, c/ u/ N$ c/ ~) k& K. @. V: Y, N, P
有。+ J! V: c7 P3 ` y7 A7 \
6 b0 Y. g4 a5 E, k3 |1 [. B+ H$ w1 F* F; p
2,方式2
' ?, H$ L6 O% M E! D/ b仔细分析所有的cases开始,结束的情景,发现和fifo文件的特性很类似,于是就想到用fifo来实现并发控制。+ t0 l# Z8 M- L) Q
) e7 g( c8 C6 O6 d
如下:
" d% h) H7 C8 S% ?" L
# h) b# S8 U6 {0 D7 \/ G6 |" ~multi.sh:
5 n! b/ J0 f7 N8 w: k2 a, ?/ Z [, S' t0 B; j1 _2 y; q
- #!/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}
5 a X; D' P' F$ U9 X3 ~1 J( @" E 6 H ^" q4 L4 W$ t- z5 i& C
: B( {* K: R5 d# a- j8 o: \. M从中可以发现,我们不需要再为获得case的结束状态而烦恼了。
/ F1 T' D* H5 H, }7 y* ]+ y) G/ y. |5 K: Q8 V
下面是运行结果,一共15个case,每个case运行1秒,并发数量设置为3,所有case运行完需要6.4秒左右。2 m' n; V' h) z! p7 A4 r9 v
% Z- U, @5 U1 _' m( H' S
: E) x9 n" M: P( U
f0 w! A8 n. v6 w* `3,shell参数传递. i' ^+ E) H1 V% S+ B
' m0 ~0 K5 h4 Y4 P, J+ @7 \
2 u& c( E, W# A, L5 Q平时我们在使用shell脚本时,往往要向脚本中指定参数,这些参数可以直接写在命令行的后面,但是这样做对参数顺序要求很强,使用起来比较困难。
0 J2 d) H& q' P( ?- R6 Y3 N4 n0 ~3 h( H" C8 _ m' c4 q
这时我们可以通过在参数前面增加标示来实现。
5 F; b( x: k5 n( I- k' H
' q; d# I" F( ~4 x0 q5 i- #!/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}"$ C2 Z# O: `7 M
5 S l* _# y# N/ l0 ?
/ D" h# ?% l5 X* U: a验证结果:( c1 {1 z$ ~8 j8 b
# z+ j1 U6 K- U+ t+ l
- g8 i2 p) a$ B5 h! v; f$ L2 V0 _8 g$ {; }" b0 F
, E s6 w/ s0 D) g$ ~ J0 S4,小结) X, l0 A" l0 @ m
5 n5 E) v8 {9 W% xshell很久都不用了,本小结就当“朝花夕拾”吧。
5 V! J6 [: H" b& r( e$ P3 u* ^
# Q [1 J( X4 N% J6 @& W5 Y- N1 w# K; r6 _" m7 ]! Y w. P: B0 a
|
|