前面寫了一篇shell多進程的文章,多進程實現起來非常簡單,但是當有大量任務,如有一百個很大的日誌文件需要分析 此時若同時並行100個進程,那io肯定要爆,所以必須要控制併發數 linux 有兩種管道:匿名管道和命名管道 匿名管道即常用的'|',命名管道可以使用mkfifo命令創建 管道有一個特性: ...
前面寫了一篇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
程式邏輯相當於造一個令牌桶,進程從中拿令牌,獲取到令牌才可以執行,否則就阻塞
程式輸出如下: