我的問題是如何更改此代碼,以便它將只使用4個線程/子進程?如何限制在bash中使用的線程/子進程的數量
TESTS="a b c d e"
for f in $TESTS; do
t=$[ ($RANDOM % 5) + 1 ]
sleep $t && echo $f $t &
done
wait
我的問題是如何更改此代碼,以便它將只使用4個線程/子進程?如何限制在bash中使用的線程/子進程的數量
TESTS="a b c d e"
for f in $TESTS; do
t=$[ ($RANDOM % 5) + 1 ]
sleep $t && echo $f $t &
done
wait
您可以通過使用jobs
內建做這樣的事情:
for f in $TESTS; do
running=($(jobs -rp))
while [ ${#running[@]} -ge 4 ] ; do
sleep 1 # this is not optimal, but you can't use wait here
running=($(jobs -rp))
done
t=$[ ($RANDOM % 5) + 1 ]
sleep $t && echo $f $t &
done
wait
此測試腳本運行在一個時間晚五組的工作,並會盡快爲它(因重啓新工作睡眠10.9殺當我們得到一個SIGCHLD。這方面的一個簡單的版本可以使用直接輪詢(更改休眠10.9睡1,擺脫陷阱)。
#!/usr/bin/bash
set -o monitor
trap "pkill -P $$ -f 'sleep 10\.9' >&/dev/null" SIGCHLD
totaljobs=15
numjobs=5
worktime=10
curjobs=0
declare -A pidlist
dojob()
{
slot=$1
time=$(echo "$RANDOM * 10/32768" | bc -l)
echo Starting job $slot with args $time
sleep $time &
pidlist[$slot]=`jobs -p %%`
curjobs=$(($curjobs + 1))
totaljobs=$(($totaljobs - 1))
}
# start
while [ $curjobs -lt $numjobs -a $totaljobs -gt 0 ]
do
dojob $curjobs
done
# Poll for jobs to die, restarting while we have them
while [ $totaljobs -gt 0 ]
do
for ((i=0;$i < $curjobs;i++))
do
if ! kill -0 ${pidlist[$i]} >&/dev/null
then
dojob $i
break
fi
done
sleep 10.9 >&/dev/null
done
wait
有趣的問題1上。我試圖用xargs來找到這個方法。
試試這個:
seq 10 | xargs -i --max-procs=4 bash -c "echo start {}; sleep 3; echo done {}"
--max-procs=4
將保證不超過四個子過程同時運行。
輸出將是這樣的:
start 2
start 3
start 1
start 4
done 2
done 3
done 1
done 4
start 6
start 5
start 7
start 8
done 6
done 5
start 9
done 8
done 7
start 10
done 9
done 10
注意,執行順序可能不會按照您提交的順序的命令。正如你可以看到2個1.前開始
快速和骯髒的解決方案:某處插入此行您for
循環內:
while [ $(jobs | wc -l) -ge 4 ] ; do sleep 1 ; done
(假設你還沒有擁有在同一個shell中運行其他後臺作業)
這可能比'jobs -r'更有效率 - 沒有它,你會計算bash告訴你哪些作業已經完成的行數。 – Mat
這個解決方案非常棒。我只是在正確的地方插入線,並繁榮! 我喜歡,我根本不需要改變我的腳本結構 –
我已經發現了使用moreutils
包的parallel
(部分這一問題的另一解決方案。)
parallel -j 4 -i bash -c "echo start {}; sleep 2; echo done {};" -- $(seq 10)
-j 4
代表-j maxjobs
-i
使用參數{}
--
劃你的論點
此命令的輸出將是:
start 3
start 4
start 1
start 2
done 4
done 2
done 3
done 1
start 5
start 6
start 7
start 8
done 5
done 6
start 9
done 7
start 10
done 8
done 9
done 10
GNU並行是專爲這種任務:
TESTS="a b c d e"
for f in $TESTS; do
t=$[ ($RANDOM % 5) + 1 ]
sem -j4 sleep $t && echo $f $t
done
sem --wait
觀看介紹視頻,以瞭解更多:
這些都不是線程,但子流程。 –
您能否考慮接受答案並將「線索」更改爲您的問題中的「子流程」?使用錯誤的詞語會使網站難以找到! ;-) – Peque