I have a BASH to run 3 functions in parallel in my BASH.
functionA () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionB () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionC () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionA &
functionB &
functionC &
wait
I have some commands in all functions for Error handling like this:
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
I noticed even though I have exit 1 for Error handling in all functions but the other functions still keep going. How do I stop bash and return exit code 1 if any of the functions fail?
I am very new to BASH, any help is appreciated!
CodePudding user response:
Something like this might work for your use-case:
update: Testing the code with a large number of sub-processes demonstrated that some kind of exclusive locking is needed. I implemented one (that should be atomic, I hope) with ln -s
and the widely available mktemp -d
#!/bin/bash
lockdir=$(mktemp -d) || exit "$?"
trap 'mv "$lockdir" "$lockdir~"; rm -rf "$lockdir~"; kill 0' EXIT
trap 'exit 1' ABRT
diex() { ln -s _ "$lockdir/.lock" 2> /dev/null && kill -ABRT "$$"; }
functionA () { sleep 5; echo "ERROR!!"; diex; }
functionB () { sleep 30; echo "GOOD!!"; }
functionA &
functionB &
wait
Explanations:
The idea is to make the sub-processes notify the main script with kill -ABRT "$$"
when they fail. I chose the SIGABRT
signal because it is appropriate for the purpose of aborting, but as a collateral effect, it will also prevent the automatic generation of a core-dump normally done when receiving SIGABRT
. If you're running an OS that supports SIGUSR1
or SIGUSR2
then you should use one of those instead.
At the start of the script, you define some signal listeners with trap
, associating a command to be run when catching a signal of the specified type:
The listener for the
EXIT
signal (triggered by anexit
command in the main script context) will terminate the script and all its sub-processes withkill 0
.The listener for
SIGABRT
(sent by a sub-processes) will not only generate anEXIT
signal but also set the exit status to1
.