【问题标题】:How to wait for any job to finished using shell script?如何使用 shell 脚本等待任何工作完成?
【发布时间】:2014-07-17 08:50:07
【问题描述】:

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

类似的东西

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?

我已经阅读过内置的 wait shell,但它会等待所有作业完成,并且我需要只有其中一个这样做。 有什么想法吗?

【问题讨论】:

  • 你可以参考这个link
  • 使用gnu parallel
  • 第一个链接对我没有用,因为它建议轮询。但这需要时间,而且我的脚本是速度测试,不能浪费一秒钟。
  • 你不能让他们在完成后运行另一个脚本吗?
  • MyScript{1,2,3}.sh 提供什么MyScript4.sh 要求,无论哪一个提供它都没有关系?

标签: bash shell process background jobs


【解决方案1】:

启动一个长时间运行的进程,三个后台进程中的每一个都会在它们完成后尝试杀死,然后等待该进程终止,然后再运行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

【讨论】:

    【解决方案2】:

    我建议您启动一个计数器,该计数器在执行每个脚本之前递增 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
    

    【讨论】:

      【解决方案3】:

      在MyScript1-3.sh 末尾添加这些行

      if mkdir /tmp/mylock ; then
        ./MyScript4.sh
      fi
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-19
        • 2015-09-06
        • 1970-01-01
        • 2016-05-23
        • 2017-12-16
        • 1970-01-01
        相关资源
        最近更新 更多