Target

The next 2 programs target is to demonstrate that bash can manipulate background jobs. In those examples, 2 programs will launch few sleep in background, the aim is to wait that all child process has exited, thus allowing to verify the correct execution. The second script can handle process time-out.

Exemple 3 - the patient

The script in example 3 is available here:

Look at following code:

set -o monitor
trap "childexit" CHLD

This permits to execute the function childexit() whenever a child process ends. In fact, the trap command is used to intercept signals and also child exit (man bash).
Every child process are run the same way and the variable $pid contains all child PID.
The wait starts thanks to the function waitall() which :

  • wait for a child to exit
  • show return code of it
Cinematic

List of actions:

  • the script initializes the trap on signal CHILD.
  • the script launches few commands in background and then wait they finish.
  • the function waitall() checks that a child has already exited (kill -0) and then wait indefinitely (waitsignal()).
  • a child process exits, the trap childexit() is executed
  • the waitsignal() function is terminated by a kill on the sleep command from the childexit() trap.
  • the function waitall() continues and recheck if a child process has exited and show its return code. Its PID is deleted from the variable $pid.
  • If $pid is empty (no more child process), the function waitall() give up to the main program.
Pro
  • simple
  • efficient
  • handle correctly return codes
Cons
  • no timeout handling
  • works only with bash (set -o monitor)

Example 4 - the patient, but not much

The script in example 4 is available here:

The script look alike example 3, but it can handle process timeout. The parameter MAXTIMEOUT specifies the maximum number of seconds to wait before killing all child process.

The infinite wait is remplaced by a limited wait (7 seconds in this example). If after 7 seconds, there still child process, a SIGTERM is sent.

Look at following code, right after the function timedwait():

timedwait
if [ $? -eq 0 ]; then
[..]
fi

This checks the return code of timedwait(). If the function timedwait() is killed by the trap CHILD (=end of child), then the return code will be diffrent of 0 and the function waitall() all check again for terminated child. However, if the function timedwait() correctly ends (=timeout), then its return code will be 0 and a kill signal will be sent to all remaining child process through the function killallchilds().

Pro
  • Simple
  • Efficient
  • Little possibility of infinite wait
Cons
  • Works only with bash

Conclusion

Bash is not only capable of running few commands in a sequential way, it can manage background processes. Bash n'est pas seulement capable de lancer quelques commandes de manière séquentielle, il est tout à fait possible de gérer les processus multitâches. Of course, we are far from performance offered by other languages but it can handle simultaneous jobs rather easily.