Shell脚本模拟多线程

举报
qshujun 发表于 2017/11/28 14:46:43 2017/11/28
【摘要】 背景: 最近经常用Shell处理一些循环任务,在一个循环中并不需要太多的cpu资源,但是需要占用一定时间。shell是一个典型面向过程脚本,这样逐个执行循环需要消耗大量时间。比如在80台主机情况下,我的批量后台操作一个“ifconfig”执行就需要用约5分钟执行完;批量nmap扫描tcp端口需要大约3分钟,而默认情况下扫描udp竟然需要大概50天!思路: Shell中可

背景:

        最近经常用Shell处理一些循环任务,在一个循环中并不需要太多的cpu资源,但是需要占用一定时间。shell是一个典型面向过程脚本,这样逐个执行循环需要消耗大量时间。比如在80台主机情况下,我的批量后台操作一个“ifconfig”执行就需要用约5分钟执行完;批量nmap扫描tcp端口需要大约3分钟,而默认情况下扫描udp竟然需要大概50天!

思路:

        Shell中可以使用“&”将某个子进程放到后台执行,我再使用fifo类型文件计数来控制放到后台执行的子进程的数量,最后用wait等全部子进程执行完,继续往下走,借此原理可以曲线实现多进程并发处理任务的目的。

示例:

以一个非常简单的例子来说明多进程对执行效率提升的帮助:循环0-99整数,与10取余,并按结果sleep,目的是让每个进程执行的时间有较大差异,方便看出子进程的执行情况

传统写法:

#!/bin/bash

fn_num ()                    #用于测试的函数,传进来一个整数与10取余,并按照结果sleep
{                            #目的是让每个进程执行的时间有较大差异,方便看出子进程情况
   a=$1
   b=$(( $a % 10 ))
   echo "--->$a"                #标记子进程开始执行
   sleep $b
   echo "<------------------$a"    #标记子进程执行结束
}

for (( i=0;i < 100;i++ ))
do
{
    fn_num $i
}
done
echo "over"

使用“多进程”写法

#!/bin/bash

THREAD_NUM=10        #定义进程数量
if [[ -a tmp ]];then        #防止计数文件存在引起冲突
    rm tmp                    #若存在先删除
fi
mkfifo tmp                    #创建fifo型文件用于计数
exec 9<>tmp

for (( i=0;i<$THREAD_NUM;i++ ))        #向fd9文件中写回车,有多少个进程就写多少个
do
    echo -ne "\n" 1>&9
done

fn_num ()                    #用于测试的函数,传进来一个整数与10取余,并按照结果sleep
{                            #目的是让每个进程执行的时间有较大差异,方便看出子进程情况
   a=$1
   b=$(( $a % 10 ))
   echo "--->$a"                #标记子进程开始执行
   sleep $b
   echo "<------------------$a"    #标记子进程执行结束
}

for (( i=0;i < 100;i++ ))
do
{
    read -u 9                #read一次,就减去fd9中一个回车
    {                        #当fd9中没有回车符时,脚本就会停住,达到控制进程数量的目的
        fn_num $i
        echo -ne "\n" 1>&9    #某个子进程执行结束,向fd9追加一个回车符,补充循环开始减去的那个
    }&

}
done

wait                        #等待所有后台子进程结束

echo "over"
rm tmp

看下执行过程:


单进程:

 每次循环只按照顺序读取一个数字,执行完毕再读取下一个,直至结束,总共耗时7m31s

linux-100:/home/admin/tmp # time sh test.sh
--->0
<------------------0
--->1
<------------------1
--->2
<------------------2
--->3
<------------------3
--->4
<------------------4
--->5
<------------------5
……………………
<------------------96
--->97
<------------------97
--->98
<------------------98
--->99
<------------------99
over

real    7m30.990s
user    0m0.012s
sys    0m0.108s

多进程:

一次读入十个整数,并进入后台同时执行,执行完的返回结果结束子进程,再读入一个数;最后所有子进程执行完毕,退出循环,总共耗时50s

linux-100:/home/admin/tmp # time sh test.sh 
--->0
--->1
--->2
--->4
--->3
--->6
--->8
--->9
<------------------0
--->5
--->7
--->10
<------------------10
--->11
<------------------1
--->12
<------------------11
--->13
<------------------2
--->14
<------------------12
<------------------3
--->15
--->16
<------------------4
…………………………
<------------------86
<------------------79
--->99
<------------------94
<------------------87
<------------------88
<------------------95
<------------------89
<------------------96
<------------------97
<------------------98
<------------------99
over

real    0m50.124s
user    0m0.008s
sys    0m0.180s

通过以上对比发现,单进程需要451秒的任务,在10个进程并行执行只需要50s;若增大进程数,所需时间会更短。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。