15

I want to run some commands in parallel. When all of these commands are finished start the next one. I though the following approach will work

#!/bin/bash
command1 &
command2 &
command3 &&
command4

but it didn't. I need to run command4 when all the first three commands have been completely finished.

2 Answers 2

31
#!/bin/bash
command1 &
command2 &
command3 &

wait
command4

wait (without any arguments) will wait until all the backgrounded processes have exited.

The complete description of wait in the bash manual:

wait [-n] [n ...]

Wait for each specified child process and return its termination status. Each n may be a process ID or a job specification; if a job spec is given, all processes in that job's pipeline are waited for. If n is not given, all currently active child processes are waited for, and the return status is zero. If the -n option is supplied, wait waits for any job to terminate and returns its exit status. If n specifies a non-existent process or job, the return status is 127. Otherwise, the return status is the exit status of the last process or job waited for.

3
  • 1
    Another option is to save the PID of each child using something like PID1=$! and then wait for all of them with wait "$PID1" "$PID2" "$PID3". That is slightly more complicated, but will work if the process has other children which you do not want to wait for.
    – kasperd
    May 6, 2017 at 20:37
  • 1
    @kasperd Better with a array in that case: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}" or something similar.
    – Kusalananda
    May 6, 2017 at 21:29
  • @kasperd By "better" I mean "uses only one variable". Nothing inherently wrong with using many, and is probably totally ok for small cases like this.
    – Kusalananda
    May 6, 2017 at 21:49
0

I like the wait answer, but just as an academic exercise, I think this would also work:

bash -c 'command1 & command2 & command3 &' && command4

Please correct me if I am wrong.

2
  • 2
    Did you test this? It absolutely does not work. Example: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo If it doesn't say the bash command took five seconds, it didn't do what you want. May 6, 2017 at 22:55
  • I tested it with sleep and echos and it seemed to work. Your example proves otherwise.
    – burger
    May 6, 2017 at 23:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .