在腳本里用&后台打開多個子進程,用wait命令可以使這些子進程並行執行。
例1:
fun1(){ while true do echo 1 sleep 1 done } fun2(){ while true do echo 2 sleep 1 done } fun1 & fun2 & wait
例2:
#!/bin/bash for ((i=0;i<5;i++)) do sleep 3;echo a done #運行需要15秒。 #!/bin/bash for ((i=0;i<5;i++)) do { sleep 3;echo a } & done wait #打開5個子進程並行,運行只需要3秒。
例3:
用管道fifo文件來處理並發,本例轉自https://my.oschina.net/sanpeterguo/blog/133304
相關知識:
read -u的介紹:https://www.cnblogs.com/maxgongzuo/p/6414474.html
mkfifo管道:https://www.cnblogs.com/maxgongzuo/p/6414466.html
eval和exec:https://www.cnblogs.com/maxgongzuo/p/6414453.html
#!/bin/bash #author : peterguo@tencent.com #date : 2013.05.24 #sub process do something function a_sub_process { echo "processing in pid [$$]" sleep 1 } #創建一個fifo文件 FIFO_FILE=/tmp/$.fifo mkfifo $FIFO_FILE #關聯fifo文件和fd6 exec 6<>$FIFO_FILE # 將fd6指向fifo類型 rm $FIFO_FILE #最大進程數 PROCESS_NUM=4 #向fd6中輸入$PROCESS_NUM個回車 for ((idx=0;idx<$PROCESS_NUM;idx++)); do echo done >&6 #處理業務,可以使用while for ((idx=0;idx<20;idx++)); do read -u6 #read -u6命令執行一次,相當於嘗試從fd6中獲取一行,如果獲取不到,則阻塞 #獲取到了一行后,fd6就少了一行了,開始處理子進程,子進程放在后台執行 { a_sub_process && { echo "sub_process is finished" } || { echo "sub error" } #完成后再補充一個回車到fd6中,釋放一個鎖 echo >&6 # 當進程結束以后,再向fd6中加上一個回車符,即補上了read -u6減去的那個 } & done #關閉fd6 exec 6>&-
關於例3,在實際應用中,進行了一些更改。
#!/bin/bash ####### env ######## first_taskid=1 PROCESS_NUM=3 ####### func ######## function do_process { local taskid=$2 [ $taskid -eq 1 ] && local gpuid=0 [ $taskid -eq 2 ] && local gpuid=1 [ $taskid -eq 3 ] && local gpuid=3 sh tran.sh $1 $taskid $gpuid & hang $1 $taskid $gpuid # wait # echo >&6 } function hang { while true do sleep 1800 ps -ef|grep "sh tran.sh $1 $2 $3" |grep -v grep [ $? -eq 0 ] && continue || break done echo >&6 } ######## fifo ######## FIFO_FILE=$(mktemp) # 建立一個隨機的不重名的臨時文件 rm $FIFO_FILE mkfifo $FIFO_FILE trap "rm $FIFO_FILE" 15 trap "rm $FIFO_FILE" 9 exec 6<>$FIFO_FILE for ((idx=0;idx<$PROCESS_NUM;idx++)); do echo done >&6 ######## main ########## for i in `cat tmp.txt` do read -u6 taskid=$(( $first_taskid % $PROCESS_NUM )) [ $taskid -eq 0 ] && taskid=$PROCESS_NUM do_process $i $taskid & ((first_taskid++)) done ######## end ######### exec 6>&- # 關閉fd6 rm $FIFO_FILE