Why isn't Bash trap working if output is redirected to stdout?
The other answer advises exec &> /dev/tty
, so traps write to /dev/tty
regardless of previous redirections:
The traps are run, but the standard output redirect to
/dev/null
is still in place, so the output is not printed. […] addexec &> /dev/tty
to work around it by re-establishing the connection from standard output/error to the terminal.
Sometimes this may not be the best solution. Consider a general case when you want your script ("fixed" with exec &> /dev/tty
) to be silent. You invoke
./the_script >/dev/null 2>/dev/null
but then the trap is triggered and it writes to /dev/tty
anyway.
For me a better way is to store the original stdout and stderr in a form of "backup" file descriptors:
# at the very beginning of the script
exec 21>&1
exec 22>&2
Then, inside the trap function, you either redirect any single command:
echo "Some output" >&21
echo "Some error" >&22
or restore the original destinations and proceed as usual:
# at the beginning of the trap function
exec 1>&21
exec 2>&22
This way the redirections applied to the interrupted command won't affect the trap; still the redirections applied to the entire script will.
The traps are run, but the standard output redirect to /dev/null is still in place, so the output is not printed. Try replacing the trap
contents with touch "$FUNCNAME"
to verify, or add exec &> /dev/tty
to work around it by re-establishing the connection from standard output/error to the terminal. As to why, this may be part of a larger feature to keep a lot of the original environment when running traps in order to avoid surprises.