如何限制bash中函数中使用的线程/子进程的数量
我的问题是如何更改此代码,使其仅使用4个线程/子进程如何限制bash中函数中使用的线程/子进程的数量,bash,Bash,我的问题是如何更改此代码,使其仅使用4个线程/子进程 TESTS="a b c d e" for f in $TESTS; do t=$[ ( $RANDOM % 5 ) + 1 ] sleep $t && echo $f $t & done wait 您可以使用作业内置: for f in $TESTS; do running=($(jobs -rp)) while [ ${#running[@]} -ge 4 ] ; do sleep 1
TESTS="a b c d e"
for f in $TESTS; do
t=$[ ( $RANDOM % 5 ) + 1 ]
sleep $t && echo $f $t &
done
wait
您可以使用
作业
内置:
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
这个经过测试的脚本一次运行5个作业,并将尽快重新启动一个新作业(因为当我们得到一个SIGCHLD时,sleep 10.9被杀死了。更简单的版本可以使用直接轮询(将sleep 10.9更改为sleep 1,并摆脱陷阱)
!/usr/bin/bash
set-o监视器
陷阱“pkill-P$$-f'sleep 10\.9'>&/dev/null”SIGCHLD
总工作=15
numjobs=5
工作时间=10
curjobs=0
声明-pidlist
dojob()
{
插槽=$1
时间=$(回声“$RANDOM*10/32768”| bc-l)
使用args$time回显开始作业$slot
睡眠时间&
pidlist[$slot]=`jobs-p%%`
curjobs=$($curjobs+1))
totaljobs=$($totaljobs-1))
}
#开始
而[$curjobs-lt$numjobs-a$totaljobs-gt 0]
做
dojob$curjobs
完成
#投票决定是否停止工作,并在我们有工作时重新启动
而[$totaljobs-gt 0]
做
对于((i=0;$i<$curjobs;i++)
做
if!kill-0${pidlist[$i]}>&/dev/null
然后
dojob$i
打破
fi
完成
睡眠10.9>&/dev/null
完成
等待
一个有趣的问题。我尝试使用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中运行其他后台作业)我使用
并行
(属于moreutils
包的一部分)找到了解决此问题的另一个方法
-j4
代表-jmaxjobs
-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 Parallel专为此类任务而设计:
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
观看介绍视频了解更多信息:
这些不是线程,而是子过程。你能考虑接受一个答案,并在你的问题中改变“线程”到“子进程”吗?用错误的词使得在Web上更难找到!!)-这可能是一个非常有效率的<代码>作业-r>代码>没有它,您将计算bash告诉您哪些作业已经完成的行数。这个解决方案非常好。我只是把线插在正确的地方,砰的一声!我喜欢我根本不需要改变我的脚本结构
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
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