2
votes

The short version: My bash script has a function.

This function then launches several instances (a maximum of 10) of another function in the background (with &).

I keep a count of how many are still active with jobs -p | wc -w in a do loop. When I'm done with the loop, I break.

I then use wait to ensure that all those processes terminate before continuing.

However, when I check the count (with jobs -p) I sometimes find this:

[10]   9311 Done                    my_background_function_name $param

How can I get wait to only proceed when all the launched child-processes have completely terminated and the jobs list is empty?

Why are jobs sometimes shown with "Done" and sometimes not?

Clearly, my knowledge of how jobs works is deficient. :)

Thanks.

1
If you're going to wait, why check with jobs -p why not just jump to the wait since it'll wait for all the children?Eric Renouf
Though not the same, I had been confused (here) by the relationship between jobs and processes. They are definitely different, so it's not necessarily safe to intermingle your ideas about them too much, jobs can continue even when the process is gone, although that's not the problem you have here, I just highlight that they are not interchangableEric Renouf
jobs -p forms part of an on-screen progress display to let user know how many copies of that background function are still active. After wait it runs again to ensure progress now reads "0". But sometimes it doesn't. I don't know why. Maybe I should parse jobs output and count the number of jobs listed as 'Running' only?teracow
@EricRenouf - yes, I'm definitely confused. I usually use PIDs but looked like jobs -p might be a better solution here. Now I'm not sure. :)teracow
Could you post more of your code? It'll likely make it easier to disentangleEric Renouf

1 Answers

1
votes

Inside a bash script, it seems that when all jobs has ended, jobs -p still returns the last one finished. This works for me in bash:

while true; do
  sleep 5
  jobs_running=($(jobs -l | grep Running | awk '{print $2}'))
  if [ ${#jobs_running[@]} -eq 0 ]; then
    break
  fi
  echo "Jobs running: ${jobs_running[@]}"
done

Using the "wait" command you cannot tell when each process ends. With the previous algorithm you can.