1. 程式人生 > >Shell指令碼併發及併發數的控制

Shell指令碼併發及併發數的控制

https://www.jianshu.com/p/701952ffb755
正常情況下,Shell指令碼是序列執行的,一條命令執行完才會執行接下來的命令。如下程式碼:

!/bin/bash

for i in seq 1 10
do
echo $i
done

echo “----end----”
指令碼執行的結果如下:

1
2
3
4
5
6
7
8
9
10
----end----
echo $1 命令序列執行,如果命令耗時較長導致總時間較長。如果命令之間沒有互相依賴關係時,可以讓命令並行執行,並行執行的方法就是在命令後加上 & 符號。

!/bin/bash

for i in seq 1 10


do
echo $i &
done

echo “----end----”
指令碼執行的結果如下:

1
2
3
5
4
----end----
10
7
8
9
6
可以看到,這樣不能保證命令的執行順序,有的時候需要保證for迴圈所有命令執行完後再向後執行接下來的命令。可以使用 wait 實現

!/bin/bash

for i in seq 1 10
do
echo $i &
done

wait
echo “----end----”
指令碼執行的結果如下:

1
2
3
6
9
10
4
5
7
8
----end----
問題還沒有結束,當需要並行執行的命令數量特別多的時候,特別是執行命令的資源佔用較多時,直接用 & 實現並行容易將伺服器資源佔用打滿,影響其他程式執行。
使用管道和令牌原理實現併發控制。

#!/bin/bash
#Step1 建立有名管道
[ -e ./fd1 ] || mkfifo ./fd1

#建立檔案描述符,以可讀(<)可寫(>)的方式關聯管道檔案,這時候檔案描述符3就有了有名管道檔案的所有特性
exec 3<> ./fd1

#關聯後的檔案描述符擁有管道檔案的所有特性,所以這時候管道檔案可以刪除,我們留下檔案描述符來用就可以了
rm -rf ./fd1

#Step2 建立令牌
for i in seq 1 2;
do
# echo 每次輸出一個換行符,也就是一個令牌
echo >&3
done

#Step3 拿出令牌,進行併發操作
for line in seq 1 10

;
do
read -u3 # read 命令每次讀取一行,也就是拿到一個令牌
{
echo $line
echo >&3 # 執行完一條命令會將令牌放回管道
}&
done

wait

exec 3<&- # 關閉檔案描述符的讀
exec 3>&- # 關閉檔案描述符的寫
小禮物走一走,來簡書關注我

作者:不智魚
連結:https://www.jianshu.com/p/701952ffb755
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。