前面寫了一篇shell多進程的文章,多進程實現起來非常簡單,但是當有大量任務,如有一百個很大的日志文件需要分析
此時若同時並行100個進程,那io肯定要爆,所以必須要控制並發數
linux 有兩種管道:匿名管道和命名管道
匿名管道即常用的'|',命名管道可以使用mkfifo命令創建
管道有一個特性:只有讀寫同時存在時,數據才可以在管道中傳遞,否則讀或者寫操作將會被阻塞
下面的腳本中即利用管道的此特性來控制並發數
# worker模擬一些耗時函數
function worker() {
echo $1
sleep 10
echo "$1"":done"
}
# 創建管道,並關聯文件描述符,最后刪除管道文件是避免腳本退出后有遺留垃圾文件,影響下一次運行
# 刪除管道文件后,因為程序還在運行中,管道還是可用的,此時用lsof |grep $tmpfifo可以看到delete狀態的管道文件,等程序運行完結束后,系統會自動清理這個文件
tmpfifo=/tmp/tmp.fifo
mkfifo $tmpfifo
exec 1000<>$tmpfifo
rm -f $tmpfifo
# 先向管道中寫入3個空行,控制並發數量,其實此時並沒有寫入而是等下面的read操作時才實際寫入。
for ((i=1;i<=3;i++))
do
echo "">&1000 &
done
# read -u從文件描述符中讀取一行,然后執行相關操作,若讀不到則會阻塞在這里,從而實現進程控制
for ((j=1;j<=10;j++))
do
read -u1000
{
worker $j
# 執行完成后寫回管道
echo "">&1000
} &
done
wait
程序邏輯相當於造一個令牌桶,進程從中拿令牌,獲取到令牌才可以執行,否則就阻塞
程序輸出如下: