Reputation: 6392
I'm running several background processes in my script
run_gui()
{
exec ... # the real commands here
}
The functions run_ai1(), run_ai2
are analogous.
Then I run the functions and do the needed piping
run_gui &
run_ai1 &
run_ai2 &
while true; do
while true; do
read -u $ai1_outfd line || echo "Nothing read"
if [[ $line ]]; then
: # processing
fi
done
sleep $turndelay
while true; do
read -u $ai2_outfd line || echo "nothing read"
if [[ $line ]]; then
: # processing
fi
done
sleep $turndelay
done
If any of those three processes exits, I want to check their exit codes and terminate the rest of the processes. For example, if run_ai2
exits with exit code 3, then I want to stop the processes run_ai1
and run_gui
and exit the main script with exit code 1. The correct exitcodes for the different backgrounds processes may differ.
The problem is: how can I detect it? There's the command wait
but I don't know in advance which script will finish first. I could run wait
as a background process - but it's becoming even more clumsy.
Can you help me please?
Upvotes: 4
Views: 4426
Reputation: 7302
A simple idea is to kill the parent process:
( sleep 2; echo hola; kill $$) &
Beware that if the set -e
option is enabled, and the first command fails, the kill
will not be executed. In this case, either disable it via set +e
or ensure the commands before kill
always succeed, e.g. append || true
.
Upvotes: 0
Reputation: 3529
The following script monitors test child processes (in the example, sleep+false and sleep+true) and reports their PID and exit code:
#!/bin/bash
set -m
trap myhandler CHLD
myhandler() {
echo sigchld received
cat /tmp/foo
}
( sleep 5; false; echo "exit p1=$?" ) > /tmp/foo &
p1=$!
echo "p1=$p1"
( sleep 3; true; echo "exit p2=$?" ) > /tmp/foo &
p2=$!
echo "p2=$p2"
pstree -p $$
wait
The result is:
p1=3197
p2=3198
prueba(3196)─┬─prueba(3197)───sleep(3199)
├─prueba(3198)───sleep(3201)
└─pstree(3200)
sigchld received
sigchld received
exit p2=0
sigchld received
exit p1=1
It could be interesting to use SIGUSR1
instead of SIGCHLD
; see here for an example: https://stackoverflow.com/a/12751700/4886927.
Also, inside the trap handler, it is posible to verify which child is still alive. Something like:
myhandler() {
if kill -0 $p1; then
echo "child1 is alive"
fi
if kill -0 $p2; then
echo "child2 is alive"
fi
}
or kill both childs when one of them dies:
myhandler() {
if kill -0 $p1 && kill -0 $p2; then
echo "all childs alive"
else
kill -9 $p1 $p2
fi
}
Upvotes: 3