1

I intend to use trap to execute some clean up code in case of a failure. I have the following code, but it seems to be have some syntactical issues.

#!/bin/bash

set -e

function handle_error {
    umount /mnt/chroot
    losetup -d $LOOP_DEV1 $LOOP_DEV2
}

trap "{ echo \"$BASH_COMMAND failed with status code $?\"; handle_error; }" ERR

Does any one see an issue with the way the trap has been written. In case of an error the trap does get executed fine but it also throws another unwanted error message below.

/root/myscript.sh: line 60: } ERR with status code 0: command not found
##line 60 is that line of code that exited with a non zero status

How do I write it correctly to avoid the error message? Also what if I had to send arguments $LOOP_DEV1 and $LOOP_DEV2 from the main script to the trap and then to the handle_error function? Right now they are exported as environment variables in the main script. I did some search for trap examples but I couldn't get something similar.

EDIT

I changed the shebang from /bin/sh to /bin/bash. As /bin/sh was already symlinked to bash I did not expect unicorns nor did I see any.

Jolta
  • 2,620
  • 1
  • 29
  • 42
The Governor
  • 1,152
  • 1
  • 12
  • 28
  • If you script is actually executed with `sh` and not `bash`, you need to define the function with `handle_error () {`. The `function` keyword is a `bash` extension. – chepner Jul 13 '13 at 15:49
  • @chepner Isn't /bin/sh a sym link to bash in most cases? At least that seems to be the case in my system. – The Governor Jul 13 '13 at 16:33
  • 2
    If you're using Bash syntax, then you should specify `#!/bin/bash` in the shbang line, even if it happens that `/bin/sh` is a symlink to `/bin/bash`. That way, if your script is ever run on a system where `/bin/sh` is *not* a symlink to `/bin/bash`, it will still work correctly. – Adam Rosenfield Jul 13 '13 at 16:33
  • Also, some features may be disabled if `bash` is run under the name `/bin/sh`, although that doesn't seem to be the case here. – chepner Jul 13 '13 at 20:19

1 Answers1

2

That trap call is creating an interesting recursion, because $BASH_COMMAND (and $?) are being expanded when the trap command executes. However, $BASH_COMMAND at that point is the trap command itself, textually including $BASH_COMMAND (and some quotes and semicolons). Actually figuring out what the command to be executed when the trap fires is an interesting study, but it's not necessary to fix the problem, which you can do like this:

trap '{ echo "$BASH_COMMAND failed with status code $?"; handle_error; }' ERR

Note that replacing " with ' not only avoids immediate parameter expansion, it also avoids have to escape the inner "s.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Appears to be working. Thanks a lot. Will post if I figure out the command that tries to get executed as a result of the recursion. – The Governor Jul 15 '13 at 09:13
  • @braindead: You can cheat by just typing `trap` and looking at what the command associated with ERR is, although you have to look carefully at the quotes. You'll see that it calls handle_error twice, but in between the two calls it tries to execute `"} ERR failed with status code 0"`, which leads to the error message you see. Remember that `{` and `}` are not self-delimiting characters; I moved the `"` above to make it more obvious what is going on, although it makes no difference whether the `"` is before or after the `}`. – rici Jul 15 '13 at 13:25