2016-11-29 20 views
1

我想達成什麼是這樣的:如何執行具有併發性和等待限制的多個命令?

#!/bin/sh 
concurrency_limit 3 

#takes 5 min 
(/usr/bin/my-process-1 --args1 && /usr/bin/my-process-2 --args1) & 
#takes 10 min 
(/usr/bin/my-process-1 --args2 && /usr/bin/my-process-2 --args2) & 
#takes 15 min 
(/usr/bin/my-process-1 --args3 && /usr/bin/my-process-2 --args3) & 
#takes 5 min 
(/usr/bin/my-process-1 --args4 && /usr/bin/my-process-2 --args4) & 
#takes 10 min 
(/usr/bin/my-process-1 --args5 && /usr/bin/my-process-2 --args5) & 
#takes 20 min 
(/usr/bin/my-process-1 --args6 && /usr/bin/my-process-2 --args6) & 

wait max_limit 1200 
echo all processes complete 

總體預期的最長執行時間爲20分鐘( - + 1分鐘),並假設我有3個CPU核心可用,我不希望有超過3個進程在同一時間運行。

在腳本開始的第3個過程開始。

5分鐘後:第1道工序完成,第4道工序開始。

第10分鐘:第2和第4過程結束並且第5過程開始。

第15分鐘:第3個過程結束。

第20分鐘:第5個過程結束。第六個過程沒有進一步的等待而死亡。

我做了很多的研究計算器,但我找不到類似的使用情況:

How to wait in bash for several subprocesses to finish and return exit code !=0 when any subprocess ends with code !=0?

https://www.codeword.xyz/2015/09/02/three-ways-to-script-processes-in-parallel/

http://www.gnu.org/software/parallel/

任何幫助或意見,將不勝感激感謝。

+0

我的回答或任何其他問題是否解決了您的問題?如果是這樣,請考慮接受它作爲您的答案 - 通過點擊投票計數旁邊的空心綠色勾號/複選標記。如果沒有,請說出什麼不起作用,以便我或其他人可以進一步幫助您。謝謝。 http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 –

回答

1

你可以用xargs做到這一點。例如下面將運行函數「FUNC」用於使用3個並行處理參數3,3,4,1,4和15 6次,並在10秒殺死它:

function func { echo args:$1; sleep $1; echo done; } 
export -f func 

function worktodo { echo -e 3\\n 3\\n 4\\n 1\\n 4\\n 15 | xargs -P 3 -I {} sh -c 'func "[email protected]"' _ {}; } 
export -f worktodo 

timeout 10 sh -c "worktodo" || echo "timeout" 
1

這裏的一個骨架,使用SIGINT到父母和子流程之間的溝通。

設置計數許多過程是如何繁忙,當一個結束,開始另一個陷阱:

trap '{ let Trapped++; }' INT # start another child 

初始化到你要多少並行運行:

Trapped=$ATONCE # 3 in your case 

然後根據需要循環,並開始孩子:

while true 
do 
    # Assuming there's more work to do. You need to decide when to terminate 
    do_work & 

    while [ $Trapped -le 0 ] 
     wait   # race condition, interruptible by SIGINT 
     local rc=$? # ... 
    done 
done 

然後在do_work你需要事端g像:

call-external-process with parms 

# Deal with problems 
[[ $? -ne 0 ]] && { .... } 

# Now tell parent we're done 
kill -INT $$ 

這是一個粗糙的想法。缺少的是當你沒有更多的流程啓動時你如何知道,它需要更好的錯誤處理,但希望你能明白。將會有3個進程始終運行,一個進程在一個進程結束時開始,直到沒有什麼可做的事情。

2

除非我錯過了一些東西,我認爲GNU並行將很容易爲你做到這一點。

如果你犯了一個名爲jobs文件,其中包含:

./my-process-1 --args1 && ./my-process-2 --args1 
./my-process-1 --args2 && ./my-process-2 --args2 
./my-process-1 --args3 && ./my-process-2 --args3 
./my-process-1 --args4 && ./my-process-2 --args4 
./my-process-1 --args5 && ./my-process-2 --args5 
./my-process-1 --args6 && ./my-process-2 --args6 

然後你可以看到什麼GNU並行將做使用--dry-run如下:

parallel --dry-run -j 3 -k -a jobs 

輸出

./my-process-1 --args1 && ./my-process-2 --args1 
./my-process-1 --args2 && ./my-process-2 --args2 
./my-process-1 --args3 && ./my-process-2 --args3 
./my-process-1 --args4 && ./my-process-2 --args4 
./my-process-1 --args5 && ./my-process-2 --args5 
./my-process-1 --args6 && ./my-process-2 --args6 

如果my-process-1需要3秒並且my-process-2需要5秒,則整體需要16秒,因爲前3行並行執行並且每行需要8秒,則接下來的3行將並行執行並且進一步採用8行秒。

+0

謝謝你的答案。但執行的總時限如何? – motto

+0

'超時120並行...' –

相關問題