40

Possible Duplicate:
Identifying received signal name in bash shell script

When using something like trap func_trap INT TERM EXIT with:

func_trap () {
    ...some commands...
}

Is there a way in the function block to detect which trap has called it?

Something like:

func_trap () {
    if signal = INT; then
        # do this
    else
        # do that
    fi
}

Or do I need to write a separate function for each trap type that does something different? Is there a bash variable that holds the latest received signal?

Thanks in advance!

Community
  • 1
  • 1
Wolf
  • 513
  • 1
  • 4
  • 7

2 Answers2

109

You can implement your own trap function that automatically passes the signal to the function:

trap_with_arg() {
    func="$1" ; shift
    for sig ; do
        trap "$func $sig" "$sig"
    done
}

$ trap_with_arg func_trap INT TERM EXIT

The first argument to func_trap will be the name of the signal.

camh
  • 40,988
  • 13
  • 62
  • 70
  • 16
    +9000: You are using [currying](http://en.wikipedia.org/wiki/Currying) in Bash. Brilliant. – kevinarpe Nov 09 '13 at 10:26
  • 4
    It may be clearer to write: `for sig "$@"; do` – kevinarpe Nov 09 '13 at 10:33
  • 7
    @kevinarpe: That would have to be `for sig in "$@"; do` - possibly clearer, but `for var ; do` is a common enough idiom (to me), that it is just as clear. It also avoids the trap of using `$@` or `$*` instead of `"$@"` that many people fall into. – camh Nov 09 '13 at 22:21
  • 3
    @camh, this idiom is completely new to me. Is this feature documented somewhere? I can't find anything relevant in `man bash`, and I don't know what to call it to search for it. – markrian Feb 13 '17 at 15:12
  • @markrian It is explicity documented as far as I know, but have a look at "help trap" or the man page anyway. It is just a consequence of how "arg" is evaluated when it is executed. Bash does not document exactly how "arg" is executed, but if you look at the posix shell docs: http://pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html it tells you is equivalent to `eval arg`. – camh Feb 14 '17 at 04:04
  • 3
    @camh, thanks, but I was referring to the `for var ; do` idiom you mentioned. Traps aren't relevant to that, AFAICT. Okay, I think I've just found *some* documentation for this: _"Omitting the in \[list] part of a for loop causes the loop to operate on $@"_, from Example 11-6 in http://www.tldp.org/LDP/abs/html/loops1.html. – markrian Feb 14 '17 at 12:12
  • 2
    @markrian, this is documented in the bash man page under "Compound Commands", where the `for` command is documented, or you can run `help for` at a bash command line where it is also described. Also, in my previous comment (now un-editable), I meant to say "*not* explicitly documented". – camh Feb 14 '17 at 23:44
  • When you only want to trap INT TERM EXIT, you can change `$func` in hardcoded funtion name, avoiding the shift. Not better, but maybe easier to understand, – Walter A Jul 16 '19 at 13:11
  • That's a new one for me @kevinarpe, very neat idiom! The complexity vs readability though ... – conny Nov 10 '20 at 08:58
  • @kevinarpe Pedantically, no currying is involved here. `trap` commands invoke `func_trap` with its sole argument, `func_trap` is used as a plain [callback function](https://en.wikipedia.org/wiki/Callback_(computer_programming)). – Maxim Egorushkin Sep 07 '22 at 23:12
15

No documentation hints of any argument or variable holding the signal that was trapped, so you'll have to write a function/trap statement for each trap you want to behave differently.

nos
  • 223,662
  • 58
  • 417
  • 506