Search code examples
bashshellprocessbackgroundjobs

How to wait for any job to finished using shell script?


I have multiple scripts that I launch in background. What I want to do is to launch another script when any of previous has finished execution (theese scripts have unpredictable execution time, so I don't know which of them finish first).

Something like this

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?

I've read about wait shell builtin but it waits for all jobs to finish, and I need when only one of them does this. Any ideas?


Solution

  • Start a long-running process which each of the three background processes will try to kill once they've completed, then wait for that process to die before running MyScript4.sh. This does require that you not use exec to execute MyScript{1,2,3}.sh, so hopefully that is not a hard requirement.

    # 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
    

    A similar option is to use a blocking read on a named pipe. (As presented, this has the additional drawback that only one of the background jobs can finish, as the other two will block trying to write to starter until somebody reads two more lines from it.)

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