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

於是當要循環執行的命令之間沒有依賴關係時,徹底能夠採用併發執行的方式,這樣能夠大幅提升代碼執行效率。固然併發執行也有缺陷,就是當須要並行執行的命令數量特別多,特別是所執行的命令佔用的系統資源很是多時,可能會將整個系統的資源所有耗盡,影響其它程序的運行,於是還能夠藉助其它技術來限制併發執行的進程數量,因爲比較複雜,本文就不作介紹了。

相關文章
相關標籤/搜索