多線程是對于linux系統來講是小菜了,下面小編為各位整理一篇linux中shell模擬多線程執行任務詳解,希望文章可以幫助到各位。
shell本身是不能實現多線程的,但是可以通過啟動子進程,并將子進程放入后臺執行來模擬多線程,為了在提高腳本執行效率的同時又不明顯增加負載的作用,還需要對同時放入后臺的進程數做下限制,代碼如下:
- #!/bin/bash
- set -x # 開啟調試模式
- #判斷是否有參數
- if [ $# != 1 ];then
- echo "您輸入的參數有誤"
- exit -1
- fi
- # 允許的最大進程數
- MAX_THREAD_NUM=5
- tmp_fifo_file=/tmp/$$.fifo # 以腳本運行的當前進程ID號作為文件名
- mkfifo "$tmp_fifo_file" # 新建一個隨機fifo管道文件
- exec 9<>"$tmp_fifo_file" # 定義文件描述符9指向這個fifo管道文件
- rm "$tmp_fifo_file"
- # 預先寫入指定數量的換行符到fifo管道文件中,一個換行符代表一個進程
- for((i=0;i<$MAX_THREAD_NUM;i++));do
- echo
- done >&9
- # 循環讀出url并判斷狀態碼
- while read line
- do
- {
- # 進程控制
- read -u 9 # 從文件描述符9中讀取行,實際指向fifo管道
- {
- isok=`curl -I -L -m 60 -o /dev/null -s -w %{http_code} $line`
- if [ "$isok" = "200" ];then
- echo $line "OK"
- else
- echo $line $isok
- fi
- echo >&9 # ,當前進程結束,往fifo管道文件中寫入一個空行
- }& //Vevb.com
- }
- done < $1 wait echo '執行結束' exec 9>&- # 刪除文件描述符9
- exit 0
腳本的任務是對一個url列表中的網址進行判斷,判斷這些網址是否可以繼續訪問,具體方法是,通過curl獲取http的狀態碼來判斷.
上面紅色部分{}中的語句被放進子進程中在后臺執行,當fifo中5個空行讀完后,循環繼續等待 read 中讀取fifo數據,當后臺的子進程完成任務后,排隊往fifo輸入空行,這樣fifo中又有了數據,循環繼續執行.
下面看看shell執行的結果,代碼如下:
- # bash scanUrl.sh url.txt
- + '[' 1 '!=' 1 ']'
- + MAX_THREAD_NUM=5
- + tmp_fifo_file=/tmp/Vevb.com
- + mkfifo /tmp/Vevb.com
- + exec
- + rm /tmp/Vevb.com
- + (( i=0 ))
- + (( i<5 ))
- + echo
- + (( i++ ))
- + (( i<5 ))
- + echo
- + (( i++ ))
- + (( i<5 ))
- + echo
- + (( i++ ))
- + (( i<5 ))
- + echo
- + (( i++ ))
- + (( i<5 ))
- + echo
- + (( i++ ))
- + (( i<5 ))
- + read line
- + read -u 9
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9 # fifo文件中的5個空行讀完了,等待其它子進程寫入fifo
- + isok=200
- + '[' 200 = 200 ']'
- + echo http://Vevb.com / OK
- http://Vevb.com / OK
- + echo # 這個子進程完成任務,寫入fifo一個空行,啟動一個子進程
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + read -u 9
- + isok=200
- + '[' 200 = 200 ']'
- + echo http://50vip.com/ OK
- http://50vip.com/ OK
- + echo
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /info/
- + read line
- + read -u 9
- + isok=200
- + '[' 200 = 200 ']'
- + echo http://361a.net/ OK
- http://361a.net/ OK
- + echo
- ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /
- + read line
- + wait # 輸入文件中的url都已經處理完成或在子進程中處理,等待所有子進程結束
- + isok=200
- + '[' 200 = 200 ']'
- + echo http://Vevb.com / OK
- http://Vevb.com / OK
- + echo
- + isok=000
- + '[' 000 = 200 ']'
- + echo http://5imovie.org/ 000
- http://5imovie.org/ 000
- + echo
- + isok=200
- + '[' 200 = 200 ']'
- + echo http://Vevb.com / OK
- http://52ixwebhosting.com/ OK
- + echo
- + isok=404
- + '[' 404 = 200 ']'
- + echo http://Vevb.com /info/ 404
- http://Vevb.com /info/ 404
- + echo
- + isok=000
- + '[' 000 = 200 ']'
- + echo http://Vevb.com / 000
- http://42.hcocoa.com/ 000
- + echo
- + echo $'346211247350241214347273223346235237'
- 執行結束
- + exec
- + exit 0
下面我們再來看個例子,代碼如下:
- #!/bin/bash
- function pinghost {
- ping $1 -c 1 -w 10 |grep rtt|cut -d “/” -f6
- }
- tmp_fifofile=”/tmp/$.fifo” # 腳本運行的當前進程ID號作為文件名
- mkfifo $tmp_fifofile # 新建一個隨機fifo管道文件
- exec 6<>$tmp_fifofile # 定義文件描述符6指向這個fifo管道文件
- rm $tmp_fifofile
- thread=10
- for ((i=0;i<$thread;i++));do # for循環 往 fifo管道文件中寫入10個空行
- echo
- done >&6
- while read domain
- do
- read -u6 # 從文件描述符6中讀取行(實際指向fifo管道)
- {
- pinghost ${domain}; # 執行pinghost函數
- echo >&6 # 再次往fifo管道文件中寫入一個空行。
- }& # 放到后臺執行
- done</home/miotour/ip.txt
- wait #因為之前的進程都是后臺執行,因此要有wait來等待所有的進程都執行完畢后才算整個腳本跑完。
- exec 6>&- #刪除文件描述符6
- exit 0
說明:{} 這部分語句被放入后臺作為一個子進程執行,這部分幾乎是同時完成的,當fifo中10個空行讀完后 while循環.
繼續等待 read 中讀取fifo數據,當后臺的10個子進程后,按次序排隊往fifo輸入空行,這樣fifo中又有了數據,for語句繼續執行.
新聞熱點
疑難解答