shell 并发执行任务
#!/bin/bash # ref: https://blog.csdn.net/spch2008/article/details/51433353 token(){ pid=$1 # 判断是否有传入pid if [ -z "${pid}" ] then echo "please input pid" exit 1 fi # 设置并发数,默认为5 concurrency=5 if [ -n "$2" ] then concurrency=$2 echo "Concurrency: $2" fi # 创建有名管道,如果fd1不存在则创建 [ -e /tmp/fd1 ] || mkfifo /tmp/fd1 # 创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符999就有了有名管道文件的所有特性 # 为了让程序有一定的扩展性,不想写死fd,因而引入了变量。 # 因而引入eval命令,强制shell进行变量展开。 # eval exec "${fd}>file"简单的说,eval将右边参数整体作为一个命令,进行变量的替换,然后将替换后的输出结果给shell去执行。 eval exec "${pid}<>/tmp/fd1" # 关联后的文件描述符拥有管道文件的所有特性,所以这时候管道文件可以删除,我们留下文件描述符来用就可以了 [ -e /tmp/fd1 ] && rm -f /tmp/fd1 # 初始化并行数 for ((i=1;i<=3;i++)) do # &999代表引用文件描述符999,这条命令代表往管道里面放入了一个"令牌" echo ${i}>&${pid} done } main(){ pid=5 start_time=`date +%s` # 生成管道文件 token ${pid} # 循环获取服务包名 for file_name in `ls /root/spark/dependency/*.jar|head -10` do # 获取令牌 read -u${pid} name { # 根据文件名去掉版本后缀,获得服务名 # svc_name=${file_name%0.0.1*} # 获取启动参数 # get_para # 执行重启 # one_restart # 这一次命令执行到最后,把令牌放回管道 echo "pipi_num: ${name}, file_name: ${file_name}" sleep 1 echo ${name}>&${pid} } & done wait # 定义脚本运行的结束时间 stop_time=`date +%s` echo "TIME:`expr ${stop_time} - ${start_time}`" # 关闭文件描述符的读 eval exec "${pid}<&-" # 关闭文件描述符的写 eval exec "${pid}>&-" } main