How to trap exit code in Bash script
There're many exit points in my bash code. I need to do some clean up work on exit, so I used trap to add a callback for exit like this:
trap "mycleanup" EXIT
The problem is there're different exit codes, I need to do corresponding cleanup works. Can I get exit code in mycleanup?
The accepted answer is basically correct, I just want to clarify things.
The following example works well:
#!/bin/bash
cleanup() {
rv=$?
rm -rf "$tmpdir"
exit $rv
}
tmpdir="$(mktemp)"
trap "cleanup" EXIT
# Do things...
But you have to be more careful if doing cleanup inline, without a function. For example this won't work:
trap "rv=$?; rm -rf $tmpdir; exit $rv" EXIT
Instead you have to escape the $rv
and $?
variables:
trap "rv=\$?; rm -rf $tmpdir; exit \$rv" EXIT
You might also want to escape $tmpdir
, as it will get evaluated when the trap line gets executed and if the tmpdir
value changes later that might not give the expected behaviour.
Edit: Use shellcheck to check your bash scripts and be aware of problems like this.
I think you can use $?
to get the exit code.
I've found it is better to separate EXIT trap from the trap for other signals
Example trap test script...
umask 77
tmpfile=`tmpfile.$$`
trap 'rm -f "$tmpfile"' EXIT
trap 'exit 2' HUP INT QUIT TERM
touch $tmpfile
read -r input
exit 10
The temporary file is cleaned up. The file exit value of 10 is preserved! Interrupts result in an exit value of 2
Basically as long as you don't use "exit" in a EXIT trap, it will exit with the original exit value preserved.
ASIDE: Note the quoting in the EXIT trap. That lets me change what file needs to be cleaned up during the scripts lifetime. I often also include a test for the existence of the $tmpfile before trying to remove it, so I don't even need to set it at the start of the script, only before creating it.