I have this failing line in my bash script
cp $a $b || (echo "error in line $LINENO (${FUNCNAME[0]})" && exit -1)
and I know it is failing because I get the msg, but the script continues to run. Why?
You are exiting from a subshell created by (...), not your current shell. Use {...} instead.
cp "$a" "$b" || { echo "..."; exit 1; }
Note the exit status should be an integer between 0 and 255.
I prefer setting a trap to run a clean-up function which can print the information as you need and perform proper exit from the script. Define your condition for trapping on ERR (i.e. on command failure). See The trap builtin command for other signals you can act on
trap cleanup ERR
and define a simple function as
cleanup() {
exitcode=$?
printf 'exit code returned: %s\n' "$exitcode"
printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
printf 'command present on line: %d\n' "${BASH_LINENO[0]}"
# Some more clean up code can be added here before exiting
exit $exitcode
}
Try running the failing cp command again with these actions defined which would exactly point you to the line-number and the command that caused the failure. Its also mandated to define your trap definitions inside the function where you suspect a possible failure instead of defining it globally.
There is an option provided by the shell for the trap to be inherited by all the functions in the script. See The set builtin
-EIf set, any
traponERRis inherited by shell functions, command substitutions, and commands executed in a subshell environment. TheERRtrap is normally not inherited in such cases.
Just define the option before your definition of the trap and use any level of nested functions as you like
set -E
trap cleanup ERR
cleanup() {
# clean-up actions
}
foo() {
# some incorrect commands
}
bar() {
# more incorrect commands
}
main() {
foo
bar
}