分享一个在Linux下模拟多线程的并发脚本,使用这个脚本可以同时批量执行相关命令,比起普通for/while循环只能顺序一条一条执行的效率高,在管理大批服务器时非常的实用。
     以下脚本功能是通过scp(也可选rsync)向上千台服务器传更新包,脚本运行后同时在后台有50个scp进程向服务器传包。

#!/bin/bash
#过滤服务器IP
ip=`cat iplist.txt|grep -v "#"|awk '{print $1}'` 
#目标路径
dir='/usr/local/src'  
#自定义并发数,根据自身服务器性能或应用调整大小,开始千万别定义太大,避免管理机宕机
thead_num=50 
#以进程ID号命名管道文件
tmp_fifo_file="/tmp/$$.fifo" 
#创建临时管道文件 
mkfifo $tmp_fifo_file  
#以读写方式打开tmp_fifo_file管道文件,文件描述符为4,也可以取3-9任意描述符 
exec 4<>$tmp_fifo_file  
#删除临时管道文件,也可不删除
rm -f $tmp_fifo_file    
#利用for循环向管道中输入并发数量的空行
for ((i=0;i<$thead_num;i++))  
do
#输出空行
         echo "" 
#输出重导向到定义的文件描述符4上 
done >&4  
#循环所有要执行的服务器
for i in $ip  
do
#从管道中读取行,每次一行,所有行读取完毕后执行挂起,直到管道有空闲的行
         read -u4  
                {
#所有要批量执行的命令都放在大括号内,scp是一个简单实例,可替换任意其他命令及命令组,1000为服务器端的端口
                         scp -P 1000 $1 $i:$dir 
#暂停3秒,给系统缓冲时间,达到限制并发进程数量  
                        sleep 3
#再写入一个空行,使挂起的循环继续执行
                        echo "" >&4  
                }&  #放入后台执行
done
 wait  #等待所有后台进程执行完成
exec 4>&-  #删除文件描述符
exit 0



--------------------------------低调的分割线------------------------------------
如果管理机与其他服务器没有建立ssh信任,也可将expect自动应答命令添加到并发脚本的循环体当中,修改如下:

#!/bin/bash
 ip=`cat iplist.txt|grep -v "#"|awk '{print $1}'`
 dir='/usr/local/src'
 answer="yes"     #定义yes/no应答变量
passwd="123456"  #服务器密码
thead_num=50
 tmp_fifo_file="/tmp/$$.fifo"
 mkfifo $tmp_fifo_file
 exec 4<>$tmp_fifo_file
 rm -f $tmp_fifo_file
 for ((i=0;i<$thead_num;i++))
 do
         echo ""
 done >&4
 for i in $ip
 do
         read -u4
                 {
                         expect <&4
                 }&
 done
 wait
 exec 4>&-
exit 0