01 Jan 2022 - nicolas
Our bash scripts can exit in multiple ways, each one having its own status.
We can define a function to be executed on specific exit status, for instance if your script exit as planned or if an error occured:
trap myCommandToExecute myExitStatusHere
trap myCommandToExecute oneExitStatusHere anotherExitStatusHere yetAnotherExitStatusHere
Be aware that a failed command inside a function will cause our script to exit with an exit status and not an err status, so either we specify in our function how to handle your errors:
#! /bin/bash
functionCallingCommandWithError() {
trap _handleExit err # we need to specify again how to handle errors
ls unknownFile # will break this method and be trapped by 'exit' instead of 'err'
echo "hello world!"
}
_handleExit() {
echo "an error occured"
}
trap _handleExit err
functionCallingCommandWithError
Or we use both err and exit like so:
#! /bin/bash
functionCallingCommandWithError() {
ls unknownFile # will break this method and be trapped by 'exit' instead of 'err'
echo "hello world!"
}
_handleExit() {
echo "an error occured"
}
trap _handleExit err exit # this time _handleExit can be called twice in case of an error
functionCallingCommandWithError
And here is what I like to do:
#! /bin/bash
hasHandleExitBeenCalled=0
functionCallingCommandWithError() {
ls unknownFile # will break this method and be trapped by 'exit' instead of 'err'
echo "hello world!"
}
brokenFunction() {
echo ${FUNCNAME[0]}
return 3 # will be trapped by 'err'
}
_handleExit() {
# remember last exit code has the next 'if' statement will override it
lastExitCode=$?
# avoid _handleExit to be called more than once in case of brokenFunction
if [ 1 -eq $hasHandleExitBeenCalled ]
then
return
fi
if [ $lastExitCode -eq 3 ]; then
echo "brokenFunction has been called."
fi
echo "an error occured"
hasHandleExitBeenCalled=1
}
trap _handleExit err exit # 'exit' is mandatory to avoid calling _handleExit twice in case of a direct error like in brokenFunction
"$@" # I like to use this when using my scripts, so I can call 'myScriptName myFunctionName'. You can replace this line by a function name if you prefer.