正常情況下桥温,Shell腳本是串行執(zhí)行的跛璧,一條命令執(zhí)行完才會執(zhí)行接下來的命令。如下代碼:
# !/bin/bash
for i in `seq 1 10`
do
echo $i
done
echo "----end----"
腳本執(zhí)行的結(jié)果如下:
1
2
3
4
5
6
7
8
9
10
----end----
echo $1
命令串行執(zhí)行迈倍,如果命令耗時較長導致總時間較長。如果命令之間沒有互相依賴關(guān)系時捣域,可以讓命令并行執(zhí)行啼染,并行執(zhí)行的方法就是在命令后加上 &
符號。
# !/bin/bash
for i in `seq 1 10`
do
echo $i &
done
echo "----end----"
腳本執(zhí)行的結(jié)果如下:
1
2
3
5
4
----end----
10
7
8
9
6
可以看到焕梅,這樣不能保證命令的執(zhí)行順序迹鹅,有的時候需要保證for循環(huán)所有命令執(zhí)行完后再向后執(zhí)行接下來的命令≌暄裕可以使用 wait 實現(xiàn)
# !/bin/bash
for i in `seq 1 10`
do
echo $i &
done
wait
echo "----end----"
腳本執(zhí)行的結(jié)果如下:
1
2
3
6
9
10
4
5
7
8
----end----
問題還沒有結(jié)束斜棚,當需要并行執(zhí)行的命令數(shù)量特別多的時候,特別是執(zhí)行命令的資源占用較多時该窗,直接用 & 實現(xiàn)并行容易將服務器資源占用打滿弟蚀,影響其他程序運行。
使用管道和令牌原理實現(xiàn)并發(fā)控制挪捕。
#!/bin/bash
# Step1 創(chuàng)建有名管道
[ -e ./fd1 ] || mkfifo ./fd1
# 創(chuàng)建文件描述符粗梭,以可讀(<)可寫(>)的方式關(guān)聯(lián)管道文件争便,這時候文件描述符3就有了有名管道文件的所有特性
exec 3<> ./fd1
# 關(guān)聯(lián)后的文件描述符擁有管道文件的所有特性,所以這時候管道文件可以刪除级零,我們留下文件描述符來用就可以了
rm -rf ./fd1
# Step2 創(chuàng)建令牌
for i in `seq 1 2`;
do
# echo 每次輸出一個換行符,也就是一個令牌
echo >&3
done
# Step3 拿出令牌,進行并發(fā)操作
for line in `seq 1 10`;
do
read -u3 # read 命令每次讀取一行滞乙,也就是拿到一個令牌
{
echo $line
echo >&3 # 執(zhí)行完一條命令會將令牌放回管道
}&
done
wait
exec 3<&- # 關(guān)閉文件描述符的讀
exec 3>&- # 關(guān)閉文件描述符的寫