Search code examples
bashprocessbackgroundwait

How can I wait for background processes to finish in Bash script - wait not working


The aim is to run two workloads concurrently, so each workload needs to be started in the background. Each of those workloads will have n workload processes running in the background (in the example below the 'workload' is a script that sleeps for n seconds). I want to wait for all background processes to complete before additional processing, whereas script returns immediately. As soon as I add the & to the {}, it stops waiting for the workload processes to complete

for wl_num in 1 2 ; do
  echo "... Workload $wl_num"
  {
    for i in `seq 1 3` ; do
      echo ...... workload process $i
      . run_sleep.sh 300 &
    done 
  } &
done
wait
echo ... done waiting for both workloads

I have also tried saving the pids and then waiting for them, but this also does not work, in that the script returns immediately, while the processes continue in the background.

for wl_num in 1 2 ; do
  echo "... Workload $wl_num"
  {
    for i in `seq 1 3` ; do
      echo ...... workload process $i
      . run_sleep.sh 5 &
      pids[${i}=$!  
    done 
  } & 
  wlpids[${db_num}]=$!
done
for pid in ${pids[*]} ; do
  wait $pid
done
for pid in ${wlpids[*]} ; do
  wait $pid
done
echo ... done waiting for both workloads

How can I wait for all backgrounds to be complete?


Solution

  • When you run the workload in the background, it forks a subshell. The main shell process can only wait for its own children, not the grandchildren.

    Use another wait inside each workload process to have that subshell wait for its children, while the main shell waits for the workloads.

    for wl_num in 1 2 ; do
      echo "... Workload $wl_num"
      {
        for i in `seq 1 3` ; do
          echo ...... workload $wl_num process $i
          . run_sleep.sh 300 &
        done 
        wait 
        echo "... Workload $wl_num done"
      } &
    done
    wait
    echo ... done waiting for both workloads