如何限制bash中函数中使用的线程/子进程数

men*_*kgs 22 bash

我的问题是如何更改此代码,以便它只使用4个线程/子进程?

TESTS="a b c d e"

for f in $TESTS; do
  t=$[ ( $RANDOM % 5 )  + 1 ]
  sleep $t && echo $f $t &
done
wait
Run Code Online (Sandbox Code Playgroud)

Lyn*_*nch 36

有趣的问题.我尝试使用xargs,我找到了一种方法.

试试这个:

seq 10 | xargs -i --max-procs=4 bash -c "echo start {}; sleep 3; echo done {}"
Run Code Online (Sandbox Code Playgroud)

--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
Run Code Online (Sandbox Code Playgroud)

请注意,执行顺序可能不遵循您提交顺序中的命令.如你所见,2开始于1之前.


mob*_*mob 13

快速而肮脏的解决方案:在for循环内的某处插入此行:

while [ $(jobs | wc -l) -ge 4 ] ; do sleep 1 ; done
Run Code Online (Sandbox Code Playgroud)

(假设您还没有在同一个shell中运行其他后台作业)

  • 对于`jobs -r`来说,这可能会更有效率 - 没有它,你会计算bash告诉你哪些工作已经完成的行. (4认同)

Lyn*_*nch 10

我找到了这个问题的另一个解决方案parallel(moreutils包的一部分.)

parallel -j 4 -i bash -c "echo start {}; sleep 2; echo done {};" -- $(seq 10)
Run Code Online (Sandbox Code Playgroud)

-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
Run Code Online (Sandbox Code Playgroud)


Mat*_*Mat 6

你可以使用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
Run Code Online (Sandbox Code Playgroud)


Ole*_*nge 5

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
Run Code Online (Sandbox Code Playgroud)

观看介绍视频以了解更多信息:

http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1