博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Shell脚本中的多任务并发执行
阅读量:5772 次
发布时间:2019-06-18

本文共 2183 字,大约阅读时间需要 7 分钟。

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

#!/bin/bashfor i in {1..10};doecho $i doneecho "END"

执行结果:

12345678910END

可以看到,循环体中的“echo $i”命令是串行执行的。但是如果所执行的命令耗时比较长,这就会导致整个程序的执行时间非常长,甚至可能导致程序执行时卡在那里,长时间失去响应。

比如我们需要完成这样一个任务:编写一个脚本,扫描192.168.80.0/24网络里,当前在线的主机有哪些,能ping通就认为在线。
要完成这个任务,编写脚本并不复杂,下面是写好的代码:

#!/bin/bashfor 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.sh192.168.80.1 is up192.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命令之后加上“&”:

#!/bin/bashfor i in {1..10};doecho $i &doneecho "END"

执行结果:

[root@localhost ~]# bash test.shEND[root@localhost ~]# 12367489105

可以看到,在并发执行时不能保证命令的执行顺序,而且本应在整个循环执行结束之后再执行的echo "END"命令,却在程序一开始就被执行了。所以在并发执行时,我们通常都需要保证在循环体中的所有命令都执行完后再向后执行接下来的命令,这时就可以使用 wait命令来实现。在Shell中使用wait命令,相当于其它高级语言里的多线程同步。

下面对代码进行改进,增加wait命令:

#!/bin/bashfor i in {1..10};doecho $i &donewaitecho "END"

这样执行结果就正常了:

[root@localhost ~]# bash test3.sh67234891051END

了解了程序并发执行的原理之后,我们对ping脚本也同样进行改进:

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

此时脚本的执行速度将大大提高:

[root@localhost ~]# bash ping.sh192.168.80.10 is up192.168.80.20 is up192.168.80.2 is up192.168.80.1 is up192.168.80.135 is up

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

转载于:https://blog.51cto.com/yttitan/2409618

你可能感兴趣的文章
链表基本操作的实现(转)
查看>>
邮件发送1
查看>>
[转] libcurl异步方式使用总结(附流程图)
查看>>
编译安装LNMP
查看>>
[转]基于display:table的CSS布局
查看>>
crm 02--->讲师页面及逻辑
查看>>
AS3.0 Bitmap类实现图片3D旋转效果
查看>>
Eigen ,MKL和 matlab 矩阵乘法速度比较
查看>>
带三角的面包屑导航栏(新增递增数字)
查看>>
Web应用程序安全与风险
查看>>
codeforces 984 A. Game
查看>>
CSS居中
查看>>
One Person Game(概率+数学)
查看>>
CodeForces 258B Little Elephant and Elections :于1-m中找出七个数,使六个数里面的4和7个数比第七个数严格小:数位dp+dfs...
查看>>
MAP
查看>>
手把手教你测——上网快鸟
查看>>
用javascript获取地址栏参数
查看>>
一起谈.NET技术,你应该知道的15个Silverlight诀窍
查看>>
商教助手!解析夏普液晶高清宽屏投影机系列
查看>>
云南去年有望实现151万贫困人口净脱贫
查看>>