|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
7 m+ e4 r! k+ M引言
8 T+ x+ v; `% S1 B Oshell,我们经常会用到,以其强大的功能,会帮助我们解决很多棘手的问题。最近遇到一个问题,要跑很多case,如果串行的执行,需要很久。能不能让他们并行起来,但又不能所有case都并行运行呢?,因为所有case同时运行,机器会挂掉的。- ]5 m- K! p+ u& l2 D; }' S
1 D% z' f! C: S8 q& I
1,方式1+ } Z. e2 i+ h0 Z* Y# r
比较直接的一种方式是,维护两个文件队列(*.start和*.stop)分别记录所有case的运行状态,然后根据并发数量来获取和分配资源。
1 T& p" n6 u4 X' ?7 C! W
) l$ M2 Z) |: ?4 h' U, e代码如下:. p: g2 ?% y H; J
' w" [- Z7 x( {3 x# @& `
multi.sh:9 e2 T, g8 ?, R1 {* |& _
9 _# o( L0 ^7 L. ?* z- \
- #!/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
- done7 e4 a2 L! S8 a* f) Y
% p2 e5 M$ A3 B! q2 X5 t( O3 T
需要注意的是采用这种方式的话,需要获得每个case的结束状态,这个可以通过case运行结束时的输出log中分析得到。
% {: ]4 I* w4 d6 {/ M虽然有awk等强大的工具,但是,分析获得不同case的结束信息仍然是一项艰巨的任务。9 n3 s6 O4 m# i2 N. b5 L- N6 y
/ F, h* z& k9 _1 d$ S2 N. ~5 S& {% M! B有没有其他的方式呢?
$ G* [! o: R. Z! [* G6 u! A- A; j7 U+ V& x' t
有。 w) Q+ q* e% d1 `9 u$ Z, e$ H
! [& m `/ Y3 @. L0 l
# D& }0 x k/ e1 f
2,方式2
& o* `0 A8 P. p; f/ O! l" n, R仔细分析所有的cases开始,结束的情景,发现和fifo文件的特性很类似,于是就想到用fifo来实现并发控制。. B& s' e7 J2 A
/ e; _3 a% R) p( ]; Y) p如下:( r& a8 u6 R6 b& @6 D% }
2 S, ^6 P8 ^7 R
multi.sh:: W7 ]7 b9 o4 S. [8 \# c% ^
* O" c1 R J8 P: i
- #!/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}! \* C, D/ ^" q8 W5 F
8 b7 j4 s1 O! b+ x
, h9 Z: H$ i4 c% R8 o ?& ~6 G
从中可以发现,我们不需要再为获得case的结束状态而烦恼了。
% j4 F! s0 m1 F. ~$ Q Y0 u. N o8 d9 P
下面是运行结果,一共15个case,每个case运行1秒,并发数量设置为3,所有case运行完需要6.4秒左右。
, R7 Y& Q: R$ \# y; B
4 |9 s4 n2 S. d5 E/ d6 d
1 S5 M1 z" U4 q6 P& x
0 S/ b9 {$ N+ v& O5 E
3,shell参数传递
2 i+ m9 {! ]' d0 L; Z; _$ R
/ R0 ~" m* A8 C' e2 u) _
$ V- b/ J! ~: n平时我们在使用shell脚本时,往往要向脚本中指定参数,这些参数可以直接写在命令行的后面,但是这样做对参数顺序要求很强,使用起来比较困难。* I0 e3 E0 r1 b/ K& G
: R3 H, N1 j4 j: B+ P V! X这时我们可以通过在参数前面增加标示来实现。1 R4 o+ i8 L$ |; D# q
7 d6 k' X# ]( F3 D Q- #!/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}"( ~+ _0 x- w' ?0 s& ~! ^
' Y' j, ^8 m" M) o
: K4 G4 y: z" V" V$ ?. G9 x2 g% |( x
验证结果:
, Y4 L+ o ~/ I" n/ e! z
2 `" k$ D5 K# b' o7 l! W
Z4 u, L6 T$ F% A) r5 b' B- q' _# j3 E4 X o1 }3 a" _7 V5 D
9 i/ H |2 ~" A' f2 M$ B( Z
4,小结
P I& ]3 s3 u, G# j! }. M. @5 B
shell很久都不用了,本小结就当“朝花夕拾”吧。
) L0 @. A* l& Y5 T: M+ ^3 P5 V* v( C9 M! v, ]9 T" E
: K$ C W. n* a ]. p- V7 j
|
|