2016-12-14 162 views
0

我有一組腳本,例如並行執行命令和等待

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

哦,你說得對。混合起來。你有沒有嘗試過你的想法? –

回答

2

您需要的唯一真正改變是避免在您的模式中引用*。如果您使用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 
3

你可以使用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實際運行正確。