2012-08-09 112 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