Hacker News new | comments | show | ask | jobs | submit login
Two simple tricks for better shell script error handling (turnkeylinux.org)
35 points by liraz on Apr 5, 2010 | hide | past | web | favorite | 11 comments

(posted to blog comments as well)

If you decide to trap INT or TERM, it would be wise to properly kill your process with INT or TERM:

    # if you're using bash, you can use $BASHPID in place of $$
    for sig in INT TERM EXIT; do
        trap "rm -f \"\$TMPFILE\"; [[ $sig == EXIT ]] || kill -$sig $$" $sig
Not propagating signals in this manner is being a bad Unix citizen. Bash would have re-raised the SIGNAL, so you should too.

For more information: http://www.cons.org/cracauer/sigint.html

I haven't run into any problems (yet) obstructing signal propagation in my scripts but as you point out it's not The Correct Thing To Do. For the sake of correctness I'll be updating my error handling code. I find doing the correct thing often saves me from debugging strange edge cases.

(replied to on blog comments as well)

Personally, I think shell scripts should start with "#! /bin/sh", not going for some specific shell. If I need more than the standard Bourne shell, I should probably be using something else.

More or less sane systems have something like this (Ubuntu 9.10):

    $ ls -l /bin/*sh
    -rwxr-xr-x 1 root root 917960 2009-09-14 06:08 /bin/bash
    -rwxr-xr-x 1 root root 101608 2009-09-21 00:49 /bin/dash
    lrwxrwxrwx 1 root root      4 2009-10-29 19:25 /bin/rbash -> bash
    lrwxrwxrwx 1 root root      4 2009-05-17 19:57 /bin/sh -> dash

I find using specific shebangs is a good habit if you don't know exactly which generic POSIX shell features/syntax you can rely on. In years past I would all too often use #!/bin/sh for the shebang only to find out later I had accidentally used a BASH specific shell feature, which is fine if /bin/sh happens to point to /bin/bash but can break if it points to something else.

OTOH, I believe the error handling tricks discussed should work with any POSIX shell so I've updated the shebang line in the code snippets to use the more generic #!/bin/sh.

I agree with using /bin/bash if that's what you're actually using and aren't sure the script will work more generally.

Something that can help pin down usage of bash extensions is checkbashisms (in the devscripts package on Debian systems). Also running the script through a shell that claims POSIX compliance like /bin/dash.

When invoked as sh, Bash enters POSIX mode after reading the startup files.

When invoked that way it still supports more than /bin/dash on my system:

  % ln -s /bin/bash sh
  % ./sh
  sh-3.2$ echo {1..10}
  1 2 3 4 5 6 7 8 9 10
  sh-3.2$ exit
  % dash
  $ echo {1..10}
where dash is supposed to be POSIX compliant.

I used to have quite an amount of Korn shell scripts, but of course that was on commercial Unices (with some ksh-retro-fitted Linux boxes in the mix).

Having ksh93 available on all systems was pretty nice, and there definitely was a place for some of the features without going for something else (which in this case mostly was Perl).

Usually when when the Ubuntu `sh -> dash' link is pointed out, it is meant as a warning to use the proper sha-bang, instead of just using `#!/bin/sh'.

If you're arguing that classic shell scripting doesn't carry you all that far, I would agree, but I don't see the harm in using #!/bin/bash or #!/bin/ksh in lieu of sh the few times you are writing a shell script; they are both extremely common and feature many conveniences.

If your script is a daemon, a runlevel or service script, an at or cron job, or just needs to spawn or control processes then trap will make you hate unix and your life.

Another invaluable mention would be "set -u" which triggers an error on undeclared variables.

Applications are open for YC Summer 2018

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact