如何等待任何作业完成使用shell脚本?

时间:2014-05-28 08:26:43

标签: bash shell process background jobs

我在后台启动了多个脚本。 我想要做的是在以前的任何一个脚本完成执行时启动另一个脚本(theese脚本有不可预测的执行时间,所以我不知道它们中的哪一个先完成)。

像这样的东西

exec ./MyScript1.sh &
exec ./MyScript2.sh &
exec ./MyScript3.sh &

#Now wait until any of them finishes and launch ./MyScript4.sh
#What do I have to do?

我已经阅读了关于等待shell内置的内容,但它等待所有工作完成,我需要只有其中一个这样做。 有什么想法吗?

3 个答案:

答案 0 :(得分:0)

启动一个长时间运行的进程,三个后台进程中的每一个都会在完成后尝试终止,然后在运行MyScript4.sh之前等待该进程死掉。这确实要求您不要使用exec来执行MyScript{1,2,3}.sh,所以希望这不是一项艰难的要求。

# Assuming that 100,000 seconds is long enough 
# for at least one bg job to complete
sleep 100000 & sleep_pid=$!

{ MyScript1.sh; kill $sleep_pid 2>/dev/null; } &
{ MyScript2.sh; kill $sleep_pid 2>/dev/null; } &
{ MyScript3.sh; kill $sleep_pid 2>/dev/null; } &
wait $sleep_pid
MyScript4.sh

类似的选项是在命名管道上使用阻塞读取。 (如上所述,这有一个额外的缺点,即只有一个后台作业可以完成,因为其他两个将阻止尝试写入starter,直到有人从中读取两行。)

mkfifo starter
{ MyScript1.sh; echo foo > starter; } &
{ MyScript2.sh; echo foo > starter; } &
{ MyScript3.sh; echo foo > starter; } &
read < starter && MyScript4.sh

答案 1 :(得分:0)

我建议你启动一个计数器,在执行每个脚本之前递增1,并在完成后递减1。通过这种方式,您可以知道有多少同时运行。然后你只需要观察这个值高于或低于某个阈值的位置(假设为3)并运行一个额外的过程。

让我举个例子:

run_scripts.sh:

#!/bin/bash

#allowed simultaneous scripts 
num_scripts=3

#initialize counter
script_counter=0
echo $script_counter
echo $script_counter > ./script_counter

# for loop to run the scripts
for i in `seq 1 10`
do
    ./script1.sh &
    sleep 0.1
    script_counter=`head -n 1 ./script_counter`
    echo $script_counter

    # wait until the number of running scripts is lower than 4
    while [ $script_counter -gt $num_scripts  ]
    do
        sleep 0.5
        script_counter=`head -n 1 ./script_counter`
    done
done

script1.sh:

#!/bin/bash

# increment counter
script_counter=`head -n 1 ./script_counter`
script_counter=$(($script_counter + 1))
echo $script_counter > ./script_counter
#echo $script_counter

# your code goes here
rand_numb=$(($RANDOM%10+1))
sleep $rand_numb
######

# decrement counter
script_counter=`head -n 1 ./script_counter`
script_counter=$(($script_counter - 1))
echo $script_counter > ./script_counter
#echo $script_counter

答案 2 :(得分:0)

MyScript1-3.sh

的末尾添加这些行
if mkdir /tmp/mylock ; then
  ./MyScript4.sh
fi

这使用/tmp/mylock作为同步进程的锁。 只有运行mkdir命令的第一个进程成功并进入if块。 其他人都会失败。