【Linux】Shell腳本中的多任務併發執行

Shell腳本中的多任務併發執行

需求

  1. 實現一個腳本能夠使用ping檢測網絡的連通性
  2. 可以同時檢測多個IP地址, 並且將檢測結果輸出

分析

正常情況下,Shell腳本中的命令是串行執行的,當一條命令執行完纔會執行接下來的命令。例如:

#!/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.0.0/24網絡裏某個區間網段有哪些主機在線,能ping通就認爲在線。下面是寫好的代碼:

#!/bin/bash
for i in {65,66,67,72,73,68};do
        ip="192.168.0.$i"
        ping -c 2 $ip &> /dev/null && echo $ip is up 
done

這裏對腳本中使用的ping命令稍作說明:Linux中的ping命令在執行後會連續不斷地發包,而且使用了“-c”選項,指定只發2次包,如果能收到響應,就認爲目標主機在線。

從邏輯上看,這個腳本沒有問題,但是由於要對網絡中的多個IP地址輪流執行ping命令,在執行後耗時將非常長,而且此時的腳本無法使用Ctrl+C強制終止,只能使用Ctrl+Z轉入後臺,然後再用kill命令強制結束進程。

 [root@localhost ~]# bash pinghost.sh
192.168.0.65 is up
192.168.0.66 is up
^C
^Z
[1]+  已停止               bash pinghost.sh
[root@localhost ~]# jobs -l                             #查看後臺工作任務
[1]+ 12496 停止                  bash pinghost.sh
[root@localhost ~]# kill -9 12496                      #強制結束進程
[root@localhost ~]# 
[1]+  已殺死               bash pinghost.sh

實際上,在這個腳本中所循環執行的ping命令之間並沒有依賴關係,也就是說不必非要等到“ping 192.168.0.65”結束之後才能接着執行“ping 192.168.0.66”,所有的這些ping命令完全可以併發執行

如果是使用Python,則可以藉助於多線程技術來實現命令的併發執行,而Shell不支持多線程,因此只能採用多進程的方式。具體的實現方法就是在要併發執行的命令後面加上“&”,將其轉入後臺執行,這樣就可以在執行完一條命令之後,不必等待其執行結束,就立即轉去執行下一條命令。修改後的代碼如下:

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

執行結果如下:

1
2
3
4
8
END
5
10
6
9

可見,在併發執行時不能保證命令的執行順序,而且本應在整個循環執行結束之後再執行的echo "END"命令,卻在程序一開始就被執行了。所以在併發執行時,我們通常都需要保證在循環體中的所有命令都執行完後再向後執行接下來的命令,這時就可以使用 wait命令來實現
在Shell中使用wait命令,相當於其它高級語言裏的多線程同步。修改代碼如下:

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

此時的執行結果如下:

1
2
3
4
5
8
6
9
7
10
END

這樣執行結果就正常了。

代碼

回到我們的問題上來,如果要檢測多個IP的網絡連通性,也可以使用上述過程的思路,代碼如下:

#!/bin/bash
for i in {65,66,67,72,73,68};do
        ip="192.168.0.$i"
        ping -c 2 $ip &> /dev/null && echo $ip is up &
done
wait

網絡的檢測結果如下:

[root@localhost ~]# bash pinghost.sh
192.168.0.65 is up
192.168.0.66 is up
192.168.0.72 is up
192.168.0.73 is up
192.168.0.67 is up
192.168.0.68 is up

因此,當在循環執行的命令之間沒有依賴關係時,完全可以採用併發執行的方式,這樣可以大幅提高代碼執行效率。

當然,併發執行也有缺陷,就是當需要並行執行的命令數量特別多,特別是所執行的命令佔用的系統資源非常多時,可能會將整個系統的資源全部耗盡,影響其它程序的運行,因此還可以藉助其它技術來限制併發執行的進程數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章