Shell脚本中的多任务并发执行

正常状况下,Shell脚本中的命令是串行执行的,当一条命令执行完才会执行接下来的命令。好比下面这段代码:bash

#!/bin/bash
for i in {1..10};do
echo $i 
done
echo "END"

执行结果:网络

1
2
3
4
5
6
7
8
9
10
END

能够看到,循环体中的“echo $i”命令是串行执行的。可是若是所执行的命令耗时比较长,这就会致使整个程序的执行时间很是长,甚至可能致使程序执行时卡在那里,长时间失去响应。
好比咱们须要完成这样一个任务:编写一个脚本,扫描192.168.80.0/24网络里,当前在线的主机有哪些,能ping通就认为在线。
要完成这个任务,编写脚本并不复杂,下面是写好的代码:多线程

#!/bin/bash
for i in {1..254};do
        ip="192.168.80.$i"
        ping -c 2 $ip &> /dev/null && echo $ip is up 
done

这里对脚本中使用的ping命令稍做说明。Linux中的ping命令在执行后会接二连三地发包,于是脚本中的ping命令使用了“-c”选项,指定只发2次包,若是能收到响应,就认为目标主机在线。
这个脚本在逻辑上并无问题,可是在执行后因为要对网络中的254个IP地址轮流执行ping命令,耗时很是长,并且此时的脚本没法使用Ctrl+C强制终止,只能使用Ctrl+Z转入后台,而后再用kill命令强制结束进程。并发

[root@localhost ~]# bash ping.sh
192.168.80.1 is up
192.168.80.2 is up
^C
^Z
[1]+  已中止               bash ping.sh
[root@localhost ~]# jobs -l                             #查看后台工做任务
[1]+ 101100 中止                  bash ping.sh
[root@localhost ~]# kill -9 101100                      #强制结束进程
[root@localhost ~]# 
[1]+  已杀死               bash ping.sh

实际上在这个脚本中所循环执行的ping命令之间并无依赖关系,也就是说没必要非要等到“ping 192.168.80.1”结束以后才能接着执行“ping 192.168.80.2”,全部的这些ping命令彻底能够并发执行。
若是是使用Python,那么能够借助于多线程技术来实现命令的并发执行,而Shell不支持多线程,于是只能采用多进程的方式。具体的实现方法很简单,就是在要并发执行的命令后面加上“&”,将其转入后台执行,这样就能够在执行完一条命令以后,没必要等待其执行结束,就当即转去执行下一条命令。
咱们仍是以以前的代码为例,在循环体中的echo命令以后加上“&”:ide

#!/bin/bash
for i in {1..10};do
echo $i &
done
echo "END"

执行结果:线程

[root@localhost ~]# bash test.sh
END
[root@localhost ~]# 1
2
3
6
7
4
8
9
10
5

能够看到,在并发执行时不能保证命令的执行顺序,并且本应在整个循环执行结束以后再执行的echo "END"命令,却在程序一开始就被执行了。因此在并发执行时,咱们一般都须要保证在循环体中的全部命令都执行完后再向后执行接下来的命令,这时就可使用 wait命令来实现。在Shell中使用wait命令,至关于其它高级语言里的多线程同步。
下面对代码进行改进,增长wait命令:code

#!/bin/bash
for i in {1..10};do
echo $i &
done
wait
echo "END"

这样执行结果就正常了:进程

[root@localhost ~]# bash test3.sh
6
7
2
3
4
8
9
10
5
1
END

了解了程序并发执行的原理以后,咱们对ping脚本也一样进行改进:ip

#!/bin/bash
for i in {1..254};do
        ip="192.168.80.$i"
        ping -c 2 $ip &> /dev/null && echo $ip is up &
done
wait

此时脚本的执行速度将大大提升:资源

[root@localhost ~]# bash ping.sh
192.168.80.10 is up
192.168.80.20 is up
192.168.80.2 is up
192.168.80.1 is up
192.168.80.135 is up

于是当要循环执行的命令之间没有依赖关系时,彻底能够采用并发执行的方式,这样能够大幅提升代码执行效率。固然并发执行也有缺陷,就是当须要并行执行的命令数量特别多,特别是所执行的命令占用的系统资源很是多时,可能会将整个系统的资源所有耗尽,影响其它程序的运行,于是还能够借助其它技术来限制并发执行的进程数量,因为比较复杂,本文就不作介绍了。

相关文章
相关标签/搜索