I've noticed that when Bash is called as sh
, you cannot unset a trap using e.g., trap -- EXIT
, but when it is called as bash
you can.
trap - EXIT
seems to work regardless of how the shell was called.
Example output:
[vagrant@localhost ~]$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 9 2016 /bin/sh -> bash
[vagrant@localhost ~]$ sh
sh-4.1$ trap 'echo something' EXIT
sh-4.1$ exit
exit
something
[vagrant@localhost ~]$ sh
sh-4.1$ trap 'echo something' EXIT
sh-4.1$ trap -- EXIT
trap: usage: trap [-lp] [[arg] signal_spec ...]
sh-4.1$ trap - EXIT
sh-4.1$ exit
exit
[vagrant@localhost ~]$ bash
[vagrant@localhost ~]$ trap 'echo something' EXIT
[vagrant@localhost ~]$ exit
exit
something
[vagrant@localhost ~]$ bash
[vagrant@localhost ~]$ trap 'echo something' EXIT
[vagrant@localhost ~]$ trap -- EXIT
[vagrant@localhost ~]$ exit
exit
[vagrant@localhost ~]$ bash
[vagrant@localhost ~]$ trap 'echo something' EXIT
[vagrant@localhost ~]$ trap - EXIT
[vagrant@localhost ~]$ exit
exit
[vagrant@localhost ~]$
I checked the documentation but I don't see the difference elucidated anywhere. I do see that the single hyphen form is specified by POSIX.
Is there any difference in behavior between the two methods of unsetting a trap, other than --
not working in sh
?
Best Answer
This is explained some in the trap(1P) man page and more in the Advanced Bash Scripting Guide, which explains that the
--
is a Bash built-in, used to denote the "end of options" for a command. Since scripts usingsh
are designed to be portable between other systems with it, bash behaves as if it were executed with--posix
, which changes some shell behavior to match the POSIX specification.When a signal is "trapped", (e.g.,
EXIT
), it binds the first argument after the command to the signal,eval
-ing it when the signal is issued, and ignoring its normal behavior (except forEXIT
). So whentrap 'echo something' EXIT
is run, thenexit
, the shell willeval 'echo something'
prior to exiting. This would also work with a different signal, such asTERM
, which could be bound to, for example, a graceful exit function in a script. Whentrap -- EXIT
is run, the--
is interpreted as an "end of arguments", indicating totrap
that the signal is to be bound to null (''
) (since there were no flags prior to or after--
), indicating to the shell to ignore the signal (however, this doesn't work with EXIT, but works with other signals). Runningtrap -- 'echo something' EXIT
, however, will stilleval 'echo something'
and exit uponexit
. As per the specification oftrap
, the command-
by itself indicates that the shell will reset any traps for the signals specified, which is why it works in bothsh
and Bash.