并行执行命令和等待
问题描述:
我有一组脚本,例如并行执行命令和等待
01_some_stuff1
02_some_stuff2
03_some_stuff3a
03_some_stuff3b
04_some_stuff4a
04_some_stuff4b
这些脚本应按照它们的编号顺序运行,并且具有相同编号的脚本应该并行运行。
我的第一个想法是重复的可能数字
for n in $(seq -f %02.0f 0 99); do
for s in "${n}_*"; do
export CURRENT_JOB="${s}"
"${s}" &
done
wait
done
这是一种安全的方法?有没有更优雅的解决方案可以为内部循环元素设置不同的环境?
答
您需要的唯一真正改变是避免在您的模式中引用*
。如果您使用bash
4.0或更高版本,则可以使用大括号扩展来消除对seq
的依赖。
# for n in $(seq -f %02.0f 0 99); do
for n in {00..99}; do
for s in "${n}"_*; do
export CURRENT_JOB="${s}"
"${s}" &
done
wait
done
答
你可以使用GNU并行这样的:
#!/bin/bash
# Don't barf if no matching files when globbing
shopt -s nullglob
for n in $(printf "%02d " {1..4}); do
# Get list (array) of matching scripts
scripts=(${n}_*)
if [ ${#scripts[@]} -gt 0 ]; then
parallel --dry-run -k 'CURRENT_JOB={} ./{}' ::: ${scripts[@]}
fi
echo barrier
done
样本输出
CURRENT_JOB=01_some_stuff1 ./01_some_stuff1
barrier
CURRENT_JOB=02_some_stuff2 ./02_some_stuff2
barrier
CURRENT_JOB=03_some_stuff3a ./03_some_stuff3a
CURRENT_JOB=03_some_stuff3b ./03_some_stuff3b
CURRENT_JOB=03_some_stuff3c ./03_some_stuff3c
barrier
CURRENT_JOB=04_some_stuff4a ./04_some_stuff4a
CURRENT_JOB=04_some_stuff4b ./04_some_stuff4b
barrier
取出echo barrier
和--dry-run
实际运行正确。
这其实并不是一种安全的方法。如果脚本'04_some_4c'很短并且在'04_some_4a'之前完成,你的脚本将运行'05_some5a',而4a仍在运行,因为'wait'只在最后一个在后台启动的作业中等待。我建议一个解决方案,将启动进程的PID('$!')保存在一个数组中。然后你可以迭代它并等待每个进程。 –
@MoritzSauter:bash manpage说:“如果没有给出n,则所有当前活动的子进程都被等待”不仅是最后一个启动的作业 – urzeit
哦,你说得对。混合起来。你有没有尝试过你的想法? –