并行执行命令和等待

问题描述:

我有一组脚本,例如并行执行命令和等待

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 

这是一种安全的方法?有没有更优雅的解决方案可以为内部循环元素设置不同的环境?

+0

这其实并不是一种安全的方法。如果脚本'04_some_4c'很短并且在'04_some_4a'之前完成,你的脚本将运行'05_some5a',而4a仍在运行,因为'wait'只在最后一个在后台启动的作业中等待。我建议一个解决方案,将启动进程的PID('$!')保存在一个数组中。然后你可以迭代它并等待每个进程。 –

+0

@MoritzSauter:bash manpage说:“如果没有给出n,则所有当前活动的子进程都被等待”不仅是最后一个启动的作业 – urzeit

+0

哦,你说得对。混合起来。你有没有尝试过你的想法? –

您需要的唯一真正改变是避免在您的模式中引用*。如果您使用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实际运行正确。