Dash: How to capture output of trap (invoked w/o arguments)

dashtrap:

The section on trap in the dash manpage states the following:

trap without any arguments cause it to write a list of signals and their associated action to the standard output in a format that is suitable as an input to the shell that achieves the same trapping results.

Awesome! I thought I'd found an easy way to reinstate previous signal handlers that I've overridden, by feeding trap's output back to the shell as a command:

trap "echo 'good'" EXIT

# save signal handlers to $traps
traps="$(trap)"

# override EXIT handler
trap "echo 'bad'" EXIT

# reinstate original handlers
eval "$traps"

Desired output: good

Actual output: bad

And that's completely logical because $traps is empty, which is in turn consistent with the manpage:

When the shell forks off a subshell, it resets trapped (but not ignored) signals to the default action.

(The command substitution $(trap) forks off a subshell, so trap doesn't know about any signal handlers.)


Everything seems to behave as it should. But how do I take advantage of trap's list functionality?

Best Answer

You can redirect to a temp file:

file=$(mktemp) || exit
{
  rm -f -- "$file"
  trap
  traps=$(cat)
} > "$file" < "$file"

Note that in that regard dash's trap is not POSIX as POSIX does require that:

var=$(trap)

be treated as a special case where the traps are not reset in the subshell.

zsh and mksh also have the issue. In zsh however, you can do:

trap | IFS= read -rd '' traps
Related Question