在bash中启动n个子进程并等待一切都完成

时间:2016-06-06 15:30:48

标签: bash ffmpeg multiple-processes

我想测试几个ffmpeg设置并运行多个命令作为'子流程'。不过,我不想一次启动4个以上的进程。有什么好办法呢?也许类似于在bg中运行进程之前捕获进程id并等待它们不再在进程列表中?还是xargs?

这里的脚本没有'排队':

#!/bin/bash

for crf in 10 15 20 23 25 30 35 ; do
    for vid_preset in medium slow veryslow; do
        ffmpeg -r 25 -i pics/pic_%04d.png -vcodec libx264 -crf $crf -vpre $vid_preset anim_crf$crf\_$vid_preset.mp4
    done
done

1 个答案:

答案 0 :(得分:1)

一种非常简单的方法是在后台运行每个ffmpeg进程,然后等待它们完成,然后再转到下一个crf值。

for crf in 10 15 20 23 25 30 35 ; do
    for vid_preset in medium slow veryslow; do
        ffmpeg -r 25 -i pics/pic_%04d.png -vcodec libx264 \
               -crf $crf -vpre $vid_preset anim_crf${crf}_${vid_preset}.mp4 &
    done
    wait
done

如果您安装了parallel,则可以使用它以繁忙的方式运行所有21个进程。

# Run 4 jobs at a time, starting a new job whenever one completes.
parallel -j 4 ffmpeg -r 25 -i pics/pic_%04d.png \
         -vcode libx264 -crf {1} -vpre {2} \
         anim_crf{1}_{2}.mp4 ::: 10 15 20 23 25 30 35 ::: medium slow veryslow

{1}由第一个输入源(第一个:::之后),{2}中的一个选项替换为第二个输入源。一个例子更简单地解释了:

$ parallel echo {1} {2} ::: a b c :: 1 2
a 2
a 1
b 1
b 2
c 1
c 2

bash 4.3或更高版本(引入wait -n时)的混乱方法:

max_jobs=4
running=()
for c in 10 15 20 23 25 30 35; do
  for v in medium slow veryslow; do
    ffmpg ... &
    running+=($!)
    # If we're at capacity, wait for a job to complete
    if (( ${#running[@]} == $max_jobs )); then
      wait -n
      # Any where from 0 to max_jobs - 1 could still be running
      running=( $(jobs -p) )
    fi
  done
done