Home > database >  Stop bash if any of the functions fail in parallel
Stop bash if any of the functions fail in parallel

Time:04-09

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 an exit command in the main script context) will terminate the script and all its sub-processes with kill 0.

  • The listener for SIGABRT (sent by a sub-processes) will not only generate an EXIT signal but also set the exit status to 1.

  • Related