• 朝花夕拾-4-shell


    引言

    shell,我们常常会用到,以其强大的功能,会帮助我们解决非常多棘手的问题。近期遇到一个问题,要跑非常多case,假设串行的执行,须要非常久。能不能让他们并行起来,但又不能全部case都并行执行呢?,由于全部case同一时候执行,机器会挂掉的。


    1,方式1

    比較直接的一种方式是,维护两个文件队列(*.start和*.stop)分别记录全部case的执行状态,然后依据并发数量来获取和分配资源。

    代码例如以下:

    multi.sh:

    #!/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

    须要注意的是採用这样的方式的话,须要获得每一个case的结束状态,这个能够通过case执行结束时的输出log中分析得到。

    尽管有awk等强大的工具,可是,分析获得不同case的结束信息仍然是一项艰巨的任务。

    有没有其它的方式呢?

    有。


    2,方式2

    细致分析全部的cases開始,结束的情景,发现和fifo文件的特性非常相似,于是就想到用fifo来实现并发控制。

    例如以下:

    multi.sh:

    #!/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
    " >>${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
    " >>${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}
    


    从中能够发现,我们不须要再为获得case的结束状态而烦恼了。

    以下是执行结果,一共15个case,每一个case执行1秒,并发数量设置为3,全部case执行完须要6.4秒左右。





    3,shell參数传递

    平时我们在使用shell脚本时,往往要向脚本中指定參数,这些參数能够直接写在命令行的后面,可是这样做对參数顺序要求非常强,使用起来比較困难。

    这时我们能够通过在參数前面添加标示来实现。


    #!/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,小结

    shell非常久都不用了,本小结就当“朝花夕拾”吧。


  • 相关阅读:
    HDOJ线段树专题(A Simple Problem with Integers)
    COJ1183(计算表达式的值)
    理解匈牙利算法求二分匹配
    COJ1143(走迷宫)
    COJ1184格林布的地雷
    POJ2387(Til the Cows Come Home)
    POJ3264(Balanced Lineup)
    调用android手机微博客户端发送微博
    用位来保存信息
    为什么类的成员变量是自身类型时只可以声明
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4070930.html
Copyright © 2020-2023  润新知