Shell 都以串行的方式自上而下执行命令,不适用需要大量作业的场景。

学习此篇shell脚本进程并发,能够大大提高工作效率~

通过wait 和 & 后台符号 可以实现并行,但无法控制进程数。

{
task
}&
done
wait

{} 将主执行程序变为一个块,使用&放入后台

wait 函数等待所有后台进程执行程序,否则继续执行后续命令直到整个脚本结束

通过有名管道控制并发进程数

创建一个fifo文件, 作为进程池, 里面存放一定数目的"令牌".作业运行规则如下: 所有作业排队依次领取令牌; 每个作业运行前从进程池中领取一块令牌, 完成后再归还令牌; 当进程池中没有令牌时, 要运行的作业只能等待. 这样就能保证同时运行的作业数等于令牌数.

管道 = = 》有名管道、无名(匿名)管道

有名管道:mkfilo 创建一个管道文件

有名管道: “cat 1.file | grep ‘xxx’ ” “|” ==》创建一个无名管道,直接作为两个进程的数据通道

exec 自行定义,绑定文件操作符

系统默认三个文件操作符 0、1、2 = = 》 stdin、stdout、stderr

ls /proc/self/fd

模板

#!/bin/bash
trap "exec 6>&-;exec 6<&-;wxit 0" 2
#接受2 程序终止(interrupt)信号 "ctrl c" 后的操作。关闭fd6
tmp_fifofile=/tmp/$$.fifo //$$ 进程pid
mkfifo $tmp_fifofile //创建为进程pid的管道
//我常用$((RANDOM)),大概率的避免与已有文件重复
exec 6<>$tmp_fifofile //以6为文件描述符fd打开管道 <>代表读写
rm $tmp_fifofile
thread=250 //定义并发进程数量,上文的令牌数量
#在fd6中放入$thread 个空行作为令牌
for ((i=0; i<=$thread;i++))
do
echo
done >&6
for i in `` //可以省略,直接在{}括号内添加执行命令
do
read -u6 //read 读取行,领取令牌
{ echo >& 6 //归还令牌
}& //{ }&放入后台
done
wait //等待所有后台子进程结束
exec 6>&- //关闭fd6
exec 6<&- //关闭fd6

结束

学术不精。欢迎评论一起讨论!~

附上一个自己写的使用并发,检查大批量站点的域名检测脚本

将待检查的脚本放入指定目录就行了~

#!/bin/bash

#创建今日目录
if [ ! -d "./$(date +%y-%m-%d)" ];then
mkdir -p /script/$(date +%y-%m-%d)
fi
dir=/script/$(date +%y-%m-%d) function global()
{
#第一次curl检测
tmp_fifofile=/tmp/$(($RANDOM%1000)).fifo
mkfifo $tmp_fifofile
exec 6<>$tmp_fifofile
rm $tmp_fifofile
thread=256
for ((i=0; i<=$thread;i++))
do
echo
done >&6 for ((i=0;i<=$thread;i++))
do
echo >&6
done for i in `cat /script/domain/$url`
do
read -u6
{
code=$(curl -o /dev/null --retry 2 --connect-timeout 10 -s -w %{http_code} $i)
echo "$code $i" >> $dir/$url-first.log
echo >& 6
}& done
wait
exec 6>&-
exec 6<&-
grep -v '200\|301\|302' $dir/$url-first.log |tail -n +2 |awk -F' ' '{print $2}' > $dir/$url-second.log
rm -f $dir/$url-first.log
#第二次wget检测
tmp_fifofile=/tmp/$(($RANDOM%1000)).fifo
mkfifo $tmp_fifofile
exec 6<>$tmp_fifofile
rm $tmp_fifofile
thread=128
for ((i=0; i<=$thread;i++))
do
echo >&6
done for i in `cat $dir/$url-second.log`
do
read -u6
{
wget -T 10 --spider -t 2 $i &>/dev/null $i >> /dev/null
if [ $? = 0 ];then
echo $i >> /dev/null
else
echo $i >> $dir/$url-third.log
fi
echo >& 6
}&
done
wait
exec 6>&-
exec 6<&-
rm -f $dir/$url-second.log #第三次curl检测
tmp_fifofile=/tmp/$(($RANDOM%1000)).fifo
mkfifo $tmp_fifofile
exec 6<>$tmp_fifofile
rm $tmp_fifofile
thread=128
for ((i=0; i<=$thread;i++))
do
echo >&6
done for i in `cat $dir/$url-third.log`
do
read -u6
{
code=$(curl -o /dev/null --retry 2 --connect-timeout 10 -s -w %{http_code} $i)
echo "$code $i" >> $dir/$url-fourth.log
echo >& 6
}& done
wait
exec 6>&-
grep -v '200\|301\|302' $dir/$url-fourth.log |tail -n +2 >> $dir/last.log
rm -f $dir/$url-third.log
rm -f $dir/$url-fourth.log } function last (){
grep -v '200\|301\|302' $dir/last.log |awk -F' ' '{print $2}' >> $dir/last2.log
rm -f $dir/last.log
tmp_fifofile=/tmp/last.fifo
mkfifo $tmp_fifofile
exec 6<>$tmp_fifofile
rm $tmp_fifofile
thread=64
for ((i=0; i<=$thread;i++))
do
echo
done >&6 for ((i=0;i<=$thread;i++))
do
echo >&6
done for i in `cat $dir/last2.log`
do
read -u6
{
code=$(curl -o /dev/null --retry 2 --connect-timeout 10 -s -w %{http_code} $i)
echo "$code $i" >> $dir/last3.log
echo >& 6
}&
done
wait
exec 6>&-
exec 6<&-
rm -f $dir/last2.log
echo "请手动复核以下域名:" > $dir/$(date +%H-00)domain.log
grep -v '200\|301\|302' $dir/last3.log >> $dir/$(date +%H-00)domain.log
rm -f $dir/last3.log
} function main ()
{
tmp_fifofile=/tmp/main.fifo
mkfifo $tmp_fifofile
exec 8<>$tmp_fifofile
rm $tmp_fifofile
thread=2
for ((i=0; i<=$thread;i++))
do
echo
done >&8 for url in `ls -l /script/domain/ | tail -n +2 | awk -F' ' '{print $9}'`
do
read -u8
{
global $url
echo >& 8
}& done
wait
exec 8>&-
exec 8<&- } main
last
mail -s "检测结果来自xx服务器 :" xxxxxxxx@qq.com < $dir/$(date +%H-00)domain.log

Shell 脚本进程并发&进程数控制的更多相关文章

  1. linux使用shell脚本停止java进程

    使用shell脚本停止java进程,过程就是先查出对应的java进程pid,然后kill掉 - | 其中xxx是对应进程的关键词(即从查出的所有java进程中分辨出目标进程)

  2. Shell脚本统计文件行数

    Shell脚本统计文件行数 转自 http://www.jb51.net/article/61943.htm    示例:row_count.sh文件 awk '{print NR}' row_cou ...

  3. curl命令,curl实现post,curl监控网页shell脚本,curl多进程实现并控制进程数,

    cURL > Docs > Tutorial:  http://curl.haxx.se/docs/httpscripting.html 下载单个文件,默认将输出打印到标准输出中(STDO ...

  4. shell脚本--监控java进程存活脚本

    #!/bin/bash base_dir=/opt war_processor="tomcat" jar_processor="manager-server.jar pl ...

  5. Shell脚本笔记(七)控制Shell脚本

    控制Shell脚本 一.处理信号 1) SIGHUP本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联. ...

  6. 【Linux脚本学习案例】shell脚本多通道并发执行存储过程

    使用shell脚本开启多个子任务并发调用存储过程,存储过程按照通道处理数据,提高效率: 外层调用脚本: #!/bin/sh #------------------------------------- ...

  7. shell脚本执行查找进程,然后查杀进程

    shell 执行查找进程,然后查杀进程脚本如下: ps -ef | grep 'IOE' |grep -v 'grep'| awk '{print \$2}' |while read pid; do ...

  8. 使用shell脚本守护node进程

    现在开源的守护node进程的包有不少,比如forever,pm2,这里我就不再赘述了. 但是有的公司生产服务器是不能联网的,而这些包都需要全局安装,必须要网络环境.难道你nohup node app. ...

  9. Shell脚本检查memcache进程并自己主动重新启动

    修正版: #!/bin/sh #check memcache process and restart if down mm_bin="/usr/local/bin/memcached&quo ...

随机推荐

  1. 10th week task -2 Object 的起源

    Objective-C与C++.Java等面向对象语言类似,不过很多方面有所差别.若是用过另一种面向对象语言,那么就能理解Objective-C所用的许多范式与模版了.然而语法上也许会显得陌生,因为该 ...

  2. 使用canvas及js简单生成验证码方法

    在很多时候都需要用到验证码,前端验证码需要知道Html5中的canvas知识点.验证码生成步骤是:1.生成一张画布canvas 2.生成随机数验证码  3.在画布中生成干扰线  4.把验证码文本填充到 ...

  3. 解决C#调试ArcMap断点不能停的问题

    问题出在ArcMap bin\ArcMap.exe.config 默认是不支持NET4.0 <startup> <!--<supportedRuntime version=&q ...

  4. 【Linux】unix/Linux常用命令英文全称

    英文全称解释更容易理解 知其然,更要知其所以然 man: Manual 意思是手册,可以用这个命令查询其他命令的用法. pwd:Print working directory 显示当前工作路径. su ...

  5. qt 创建线程

    http://www.cnblogs.com/xinxue/p/6840315.html Qt 之 QtConcurrent 本文以 Qt 中的 QtConcurrent::run() 函数为例,介绍 ...

  6. log4j2单独的配置与使用&log4j2+slf4j的结合的配置与使用

    转载自:https://github.com/iamyong 一.log4j2单独的配置与使用 所用jar文件 log4j-api-2.8.2.jar log4j-core-2.8.2.jar 配置文 ...

  7. SDET面试之感受篇。

    某年某月的某一天,我来到了太监村的一栋大厦,因为早到了半个小时,拿出来提前准备好的code随便的翻看着. 人家都说,面试头五分钟就已经决定了,是否能面试成功.所以,面试真正的真谛可能就是相面.什么写c ...

  8. Vue项目中引入ElementUI

    前提:创建好的vue项目. 1.安装ElementUI 转到项目根目录,输入命令:#cnpm install element-ui --save-dev 2.在 main.js 引入并注册 impor ...

  9. AFN 切换BaseUrl

    在某个特定的接口需要修改baseurl时: 直接使用kvc: [_sessionManager setValue:[NSURL URLWithString:NEW_BASE_URL] forKey:@ ...

  10. 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...