https://www.jianshu.com/p/701952ffb755ruby
正常狀況下,Shell腳本是串行執行的,一條命令執行完纔會執行接下來的命令。以下代碼:bash
# !/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----"
腳本執行的結果以下:spa
1 2 3 5 4 ----end---- 10 7 8 9 6
能夠看到,這樣不能保證命令的執行順序,有的時候須要保證for循環全部命令執行完後再向後執行接下來的命令。可使用 wait 實現code
# !/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----
問題尚未結束,當須要並行執行的命令數量特別多的時候,特別是執行命令的資源佔用較多時,直接用 & 實現並行容易將服務器資源佔用打滿,影響其餘程序運行。
使用管道和令牌原理實現併發控制。get
#!/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>&- # 關閉文件描述符的寫