**Tips:**正常来说shell是不具备多线程能力的,也就是说shell本身是按顺序进行执行指令的,并不能并发执行。但是可以换个思路,通过遍历+后台执行的方式进行模拟多线程的方式。但是还有个问题就是如何去控制并发数量,比如你要批量往1w台机器上copy一个文件,如果不设置并发数,估计直接就带宽跑满game over了,不过也有对应的解决方案,往下看吧。

并发方案模型

  • 无并发设置
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    #!/bin/bash
    echo `date`
    echo "-----------Arvon.top Loop Begin-------------"
    for i in `seq 3`;do
        sleep 10
        echo $i
        echo `date`
    done
    echo "-----------Arvon.top Loop End-------------"
    echo `date`
    

    输出

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    Wed Aug 2 12:53:25 UTC 2017
    -----------Arvon.top Loop Begin-------------
    1
    Wed Aug 2 12:53:35 UTC 2017
    2
    Wed Aug 2 12:53:45 UTC 2017
    3
    Wed Aug 2 12:53:55 UTC 2017
    -----------Arvon.top Loop End-------------
    Wed Aug 2 12:53:55 UTC 2017
    
  • 无并发数设置 **Tips:**敲黑板,注意wait这个指令,需要在如果需要循环体内所有任务执行完成后再执行其他指令,需要在循坏外紧接着加上
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    #!/bin/bash
    echo `date`
    echo "-----------Arvon.top Loop Begin-------------"
    for i in `seq 3`;do
    {
        sleep 10
        echo $i
        echo `date`
    }&
    done
    wait
    echo "-----------Arvon.top Loop End-------------"
    echo `date`
    

    输出

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    Wed Aug 2 13:04:34 UTC 2017
    -----------Arvon.top Loop Begin-------------
    1
    2
    3
    Wed Aug 2 13:04:44 UTC 2017
    Wed Aug 2 13:04:44 UTC 2017
    Wed Aug 2 13:04:44 UTC 2017
    -----------Arvon.top Loop End-------------
    Wed Aug 2 13:04:44 UTC 2017
    
  • 有并发数设置 Tips:这里需要用到一种特殊的文件名称为有名管道(FIFO),这个具体会另写一篇,注意&6和read这些地方
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    #!/bin/bash
    
    server_list=`seq 10`
    thread=3
    
    # Create FIFO
    tmp_fifofile="/tmp/$$.fifo"
    mkfifo $tmp_fifofile
    exec 6<> $tmp_fifofile
    rm $tmp_fifofile
    
    for ((i=0;i<$thread;i++)); do
    echo
    done >& 6
    
    # user operation
    function user_scripts(){
        sleep 10
        echo `date`
    }
    echo `date`
    echo "-----------Arvon.top Loop Begin-------------"
    for i in ${server_list};do
    read -u6
    {
        user_scripts
        echo >&6
    }&
    done <&6
    wait
    exec 6>&-
    echo "-----------Arvon.top Loop End-------------"
    echo `date`
    

    输出

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    Wed Aug 2 14:12:03 UTC 2017
    -----------Arvon.top Loop Begin-------------
    Wed Aug 2 14:12:13 UTC 2017
    Wed Aug 2 14:12:13 UTC 2017
    Wed Aug 2 14:12:13 UTC 2017
    Wed Aug 2 14:12:23 UTC 2017
    Wed Aug 2 14:12:23 UTC 2017
    Wed Aug 2 14:12:23 UTC 2017
    Wed Aug 2 14:12:33 UTC 2017
    Wed Aug 2 14:12:33 UTC 2017
    Wed Aug 2 14:12:33 UTC 2017
    Wed Aug 2 14:12:43 UTC 2017
    -----------Arvon.top Loop End-------------
    Wed Aug 2 14:12:43 UTC 2017
    

实战小栗子

  • 例子1:需要
  • 本机上进行并行运行脚本
  • 每次并行需要不同的配置文件

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash

# cat server.csv | grep gid > confd/
for i in `cat server.csv | egrep -v "gid"`;do
    sid=`echo $i |awk -F',' '{print $2}'`
    cat server.csv | grep gid > confd/${sid}_server.csv
    echo $i >> confd/${sid}_server.csv
    {
    echo "./tool_refresh_gs -save -config confd/${sid}_server.csv  -out ${sid}"
    #./tool_refresh_gs -save -config confd/${sid}_server.csv  -out ${sid}
    }&
done
wait

不错的

写的很不错