tags:

views:

54

answers:

2

When I use the "trap" command in bash, the previous trap for the given signal is replaced.

Is there a way of making more than one trap fire for the same signal?

+1  A: 

No

About the best you could do is:

$ trap "rm -f /tmp/xyz; exit 1" 2
$ trap
trap -- 'rm -f /tmp/xyz; exit 1' INT
$ trap 2
$ trap
$

The first line sets a trap on signal 2 (SIGINT). The second line prints the current traps - you would have to capture the standard output from this and parse it for the signal you want. Then, you can add your code to what was already there - noting that the prior code will most probably include an 'exit' operation. The third invocation of trap clears the trap on 2/INT. The last one shows that there are no traps outstanding.

You can also use trap -p INT or trap -p 2 to print the trap for a specific signal.

Jonathan Leffler
+1  A: 

Edit:

It appears that I misread the question. The answer is simple:

handler1 () { do_something; }
handler2 () { do_something_else; }
handler3 () { handler1; handler2; }

trap handler3 SIGNAL1 SIGNAL2 ...

Original:

Just list multiple signals at the end of the command:

trap function-name SIGNAL1 SIGNAL2 SIGNAL3 ...

You can find the function associated with a particular signal using trap -p:

trap -p SIGINT

Note that it lists each signal separately even if they're handled by the same function.

You can add an additional signal given a known one by doing this:

eval "$(trap -p SIGUSR1) SIGUSR2"

This works even if there are other additional signals being processed by the same function. In other words, let's say a function was already handling three signals - you could add two more just by referring to one existing one and appending two more (where only one is shown above just inside the closing quotes).

If you're using Bash >= 3.2, you can do something like this to extract the function given a signal. Note that it's not completely robust because other single quotes could appear.

[[ $(trap -p SIGUSR1) =~ trap\ --\ \'([^\047])\'.* ]]
function_name=${BASH_REMATCH[1]}

Then you could rebuild your trap command from scratch if you needed to using the function name, etc.

Dennis Williamson
He asked for multiple traps for the same signal, not the same trap for multiple signals.
Darron
@Darron: Sorry, I misread the question. The answer to the **actual** question is much simpler and I've added it at the top.
Dennis Williamson
@Dennis: you are still only firing one trap - that the trap in question invokes multiple functions and achieves the effect is more or less indisputable. The only reason to think there might be any grounds for dispute is that if handler1 is installed first, and it is designed to exit, then handler2 won't be fired. But there is still just one action fired off. (You've always been able to have an arbitrarily complex sequence of operations in the triggered action.)
Jonathan Leffler
@Jonathan: handler3 can run handler1 and 2 in subshells so that it can be sure that both handlers are run and do its own exit (or run all but the last in subshells and let the last do it). Also, handler3 can set a trap on EXIT and make sure that both sub-handlers have been run.
Dennis Williamson
OK - we're concluding that the question is asking for two different things. You're assuming that the question is asking "can you do arbitrarily complex operations in a trap handler", to which the answer is, of course, Yes - you can write any shell script commands in the trap handler. I'm assuming the question is "can I have two separate traps both active: '`trap "xyz" 2`' and '`trap "pqr" 2`' simultaneously, to which the answer is (as I stated) No. Given the difference in interpretation of the question, there can be no surprise at the difference in the answer.
Jonathan Leffler