Here are two simple tricks that are easy to use and will make your scripts much more robust.
Turn on -e mode (do you feel lucky - punk?)
In this mode any command your script runs which returns a non-zero exitcode - an error in the world of shell - will cause your script to itself terminate immediately with an error.You can do that in your shebang line:#!/bin/sh -e
Or using set:set -e
Yes, this is what you want. A neat predictable failure is infinitely better than a noisy unreliable failure.If you REALLY want to ignore an error, be explicit about it:# I don't care if evil-broken-command fails evil-broken-command || true
Oh and as long as you're messing with shell modes, -e goes well with -x (which I like to think of as shell X-ray).Like this:#!/bin/sh -ex
Or like this:# turn -x on if DEBUG is set to a non-empty string [ -n "$DEBUG" ] && set -x
That way you can actually see what your script was doing right before it failed.Use trap for robust clean-ups
A trap is a snippet of code that the shell executes when it exits or receives a signal. For example, pressing CTRL-C in the terminal where the script is running generates the INT signal. killing the process by default generates a TERM (I.e., terminate) signal.I find traps most useful for making sure my scripts clean-up after themselves whatever happens (e.g., a non-zero error code in -e mode).For example:#!/bin/sh -e TMPFILE=$(tempfile) trap 'echo "removing $TMPFILE"; rm -f $TMPFILE' INT TERM EXIT echo TMPFILE=$TMPFILE echo hello world > $TMPFILE cat $TMPFILE # gives user a chance to press CTRL-C sleep 3 # false always returns an error false echo "NEVER REACHED"
Note that you can only set one trap per signal. If you set a new trap you're implicitly disabling the old one. You can also disable a trap by specifying - as the argument, like this:trap - INT TERM EXIT
0 blogger-disqus:
Post a Comment