2012-08-09 192 views
3

我有3個進程在後臺執行a.sh,b.sh,c.sh。如何在這種情況下繼續執行後臺進程

./a.sh & 
pid_a=$! 

./b.sh & 
pid_b=$! 

./c.sh & 
pid_c=$! 

我需要確保所有三個進程都運行,直到最長進程終止。如果c.sh需要10秒,a.sh需要3秒,b.sh需要5秒來執行個別執行時間,我需要再次執行a.sh,b.sh以確保它們存在,直到c.sh完成。

我想這種做法,這顯然沒在上面的場景

./a.sh & 
while ps -p $! > /dev/null; do 

./b.sh & 
pid_b=$! 

./c.sh & 
pid_c=$! 

wait $pid_c 
done 

我如何得到這個工作?

回答

1

您可以使用臨時文件爲標誌,以表明當每個過程的完成第一次。在後臺循環中運行每個腳本,直到其他兩個腳本都至少完成一次。

flag_dir=$(mktemp -d flagsXXXXX) 
flag_a=$flag_dir/a 
flag_b=$flag_dir/b 
flag_c=$flag_dir/c 

(until [[ -f $flag_b && -f $flag_c ]]; do ./a.sh; touch $flag_a; done;) & 
(until [[ -f $flag_a && -f $flag_c ]]; do ./b.sh; touch $flag_b; done;) & 
(until [[ -f $flag_a && -f $flag_b ]]; do ./c.sh; touch $flag_c; done;) & 

# Each until-loop runs until it sees the other two have completed at least one 
# cycle. Wait here until each loop finishes. 
wait 

# Clean up 
rm -rf "$flag_dir" 
0

首先,您可以使用kill -0來測試c.sh的進程狀態,而不是使用wait等待它終止。

其次,你可以使用2個單獨的進程監控腳本a.sh的狀態和b.sh

第三,這種假設c.sh是運行時間最長的進程。

因此,監控過程1將執行以下操作:

# I have pid_c 
./a.sh & 
pid_a=$! 
while wait $pid_a; do 
    if kill -0 $pid_c; then 
     ./a.sh& 
     pid_a=$! 
    fi 
done 

和監視處理2執行以下操作:

# I have pid_c 
./b.sh & 
pid_b=$! 
while wait $pid_b; do 
    if kill -0 $pid_c; then 
     ./b.sh & 
     pid_b=$! 
    fi 
done 

因此,你分別監視2個進程。但是,如果您還需要監視它們,然後將監視器產生爲2個後臺作業,並且簡單的wait將等待c.sh以及2個監視器。

注意:kill -0 $PID返回0如果$PID正在運行或1如果$PID已終止。

+0

工作正常,但在我的問題,我不知道哪個是最長的運行過程!因此,我不能假設。 – marc 2012-08-09 11:58:58

0

[注意這隻適用於bash。 ksh93的kill的行爲不同。]

只要有你被允許殺,kill -0將返回成功至少一個過程。根據需要調整時間間隔。

#! /bin/bash 
interval=1 
pids= && for t in 2 3; do 
    (sleep $t && echo slept $t seconds) & pids=${pids:+$pids }$! 
done 

while (kill -0 $pids) 2>& -; do 
    sleep $interval 
    # optional reporting: 
    for pid in $pids; do 
     (kill -0 $pid) 2>&- && echo $pid is alive 
    done 
done 

結果:

6463 is alive 
6464 is alive 
slept 2 seconds 
[1]- Done     eval sleeper $t 
6464 is alive 
slept 3 seconds 
[2]+ Done     eval sleeper $t 

內建kill是不相符的關於錯誤:

$ ksh -c 'kill -0 571 6133 && echo ok || echo no' 
kill: 571: permission denied 
no 
$ bash -c 'kill -0 571 6133 && echo ok || echo no' 
bash: line 0: kill: (571) - Operation not permitted 
ok