所以我有一個while循環遍歷包含名稱的文本文件,然後在列表上執行後臺進程。這一切都很好,但當它結束時,我需要按Ctrl-C。一旦所有進程完成後,我如何執行SIGINT,因此我不必ctrl-c?殺死在while循環後臺進程中創建的PID
我需要在每個單獨的過程中完成嗎?或者我可以通過使用像睡覺這樣的循環來做到這一點?
這是我目前有的,但不是很有效。
while read BAR; do foo $BAR & done < bars.txt; pid=$!; wait; kill pid
所以我有一個while循環遍歷包含名稱的文本文件,然後在列表上執行後臺進程。這一切都很好,但當它結束時,我需要按Ctrl-C。一旦所有進程完成後,我如何執行SIGINT,因此我不必ctrl-c?殺死在while循環後臺進程中創建的PID
我需要在每個單獨的過程中完成嗎?或者我可以通過使用像睡覺這樣的循環來做到這一點?
這是我目前有的,但不是很有效。
while read BAR; do foo $BAR & done < bars.txt; pid=$!; wait; kill pid
現在你只收集最後 PID,所有你的後臺進程不會的PID。
如果您收集的PID,您可以單獨等待他們 - 它可以讓你檢查單個作業是否失敗,或看到它們中的哪一個實際上並沒有完成:
pids=()
while read bar; do
foo "$bar" & pids+=("$!")
done < bars.txt
for pid in "${pids[@]}"; do
echo "Checking exit status of $pid..."
if wait "$pid"; then
echo "$pid succeeded!"
else
echo "$pid failed!"
fi
done
如果你想跟蹤哪些具體值是成功還是失敗處理,你可以做得更好(使用bash 4.0或更高版本):
declare -A pids=()
while read -r bar; do
foo "$bar" & pids[$!]="$bar"
done < bars.txt
for pid in "${!pids[@]}"; do
bar=${pids[$pid]}
echo "Checking exit status of $pid (processing value $bar)..."
if wait "$pid"; then
echo "$pid (for $bar) succeeded!"
else
echo "$pid (for $bar) failed!"
fi
done
在上述任何一種情況下,wait
的每個調用都負責在相應的PID退出後返回。因此,當所有後臺任務都退出時,腳本將自行退出。
最後,力你的孩子退出,你可以建立,是以PID列表的優勢的信號處理程序:
shutdown() { kill "${pids[@]}"; } # or "${!pids[@]}" for the second example
trap shutdown 0
如果你真的想要一個班輪,你可以圍繞以下邏輯構建它(格式化以提高可讀性)。
while -r read BAR
do
foo "$BAR" &
done < bars.txt
wait
這將等待所有後臺任務完成(包括執行此命令之前啓動的任何後臺任務)。這有點粗糙(CharlesDuffy提出了一個解決方案,可以更好地跟蹤任務),但它有足夠短的單線程的可疑優勢。
while -r read BAR ; do foo "$BAR" & done < bars.txt ; wait
殺作業啓動他們之後(我不清楚你爲什麼會想這樣做),你也許可以做這樣的事情:
while -r read BAR ; do foo "$BAR" & done < bars.txt ; kill $(jobs -p)
再次,這將標誌着所有後臺工作,不僅僅是你剛剛發佈的工作。
不幸的是,我的後臺進程不能自行退出 –
隨着GNU並行它看起來像這樣:
parallel -j0 foo {} < bars.txt
echo $? jobs failed
如果你離開了-j0
它將運行每個CPU核心一個作業。
如果您需要確切的作業失敗知道,你可以使用一個joblog:
parallel --joblog jl -j0 foo {} < bars.txt
cat jl
它還確保不同作業中的輸出不會混合在一起,因此,如果您使用的輸出,保證您你不會從兩個不同的工作中獲得半條命。
GNU Parallel是一個通用的並行程序,可以很容易地在同一臺機器上或在您擁有ssh訪問權限的多臺機器上並行運行作業。
如果你想在4個CPU上運行32個不同的工作崗位,並行化直接的方式是在每個CPU上運行8個作業:
GNU並行,而不是產生一個新的進程時,一個完成 - 保持CPU的活躍,從而節省了時間:
安裝
您應該在您的軟件包管理器中安裝GNU Parallel,但是如果您的發行版沒有打包GNU Parallel,則可以執行個人安裝,但不需要root訪問權限。它可以在10秒內通過這樣來完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
對於其他安裝選項見http://git.savannah.gnu.org/cgit/parallel.git/tree/README
瞭解更多
查看更多的例子:http://www.gnu.org/software/parallel/man.html
觀看介紹視頻: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
走過t他教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
訂閱郵件列表,以獲得支持:https://lists.gnu.org/mailman/listinfo/parallel
不,我應該這樣做,但是反正有做在一個「襯」,所以我沒有執行一份文件?像我可以把等待在循環中然後殺死PID?或者這只是讓它再次同步? –
備份一下 - 爲什麼「殺死」呢?當我讀到這個問題時,你的後臺進程會自行退出,唯一的問題是調用它們的腳本不在退出......對嗎? –
如果你想要一個處理並行進程的單線程,順便說一句,你可能更好的是'xargs -P'或者GNU parallel。例如,一次最多可運行16個進程:'xargs -d $'\ n'-P 16 foo