[sf-lug] +trap, etc.: Re: bash strict mode (set -e)? - not so fast unless you know these quirks

Michael Paoli michael.paoli at berkeley.edu
Thu Aug 14 23:24:40 PDT 2025


On Thu, Aug 14, 2025 at 11:31#AM Ron <ron at bclug.ca> wrote:
> * how regularly do you put `set` in your bash scripts?

Pretty commonly, though not necessarily in the same ways one might think
of from the examples you show.  E.g.  I'll not uncommonly use

set --
With or without additional arguments.  Often in a subshell.
That sets positional parameters.

set -e I use very commonly, however, in many places I'll often add more
explicit handling, e.g. if I want more information about what
returned/exited non-zero.  Sometimes additional handling isn't needed,
as the thing that failed will give sufficient info, e.g.:
cat /does_not_exist
cat: /does_not_exist: No such file or directory
In other cases:
FILE=/does_not_exist
[ -f "$FILE" ] || {
  printf '%s\n' "$0: can't find file: $FILE" 1>&2
  exit 1
}
bash: can't find file: /does_not_exist

set -u I generally avoid, as that mostly tends to break backwards
compatibility and general default expectations on behavior.
If I need/want to know if a shell named parameter / variable is set,
there are ample ways to check that, and handle accordingly.
And pipefail I use sparingly.  Sometimes it's exactly what one
want/needs, other times it's more likely to get in the way or be a
problem where it's not wanted.

> * how often do you trap signals in your bash scripts?

Not super regularly, yet fairly common.
Most commonly to clean up temporary file(s).
And by also trapping on 0, I can make the cleanup pretty generic, well
covering all the (ab)normal cases with a common chunk of code.

An example bit:
trap "trap - 0; rm -rf $tmpd; exit "'"$rc"' 0
for sig in 1 2 3 15
do
  trap '
    trap - 0
    rm -rf '"$tmpd"' || exit
    trap - '"$sig"'
    kill -'"$sig"' "$$"
  ' "$sig"
done
In those traps, first I clear the trap on 0 (exit), so I don't possibly
reenter the trap with another exit, since I'm already trapping 0 (exit).
Then get rid of the temporary directory - and for my non-zero traps if
that rm returns non-zero I exit with that.  Then for the non-zero traps,
I clear the trap on the signal I'm handling, so I resume getting default
behavior for that signal.  Then for my non-zero (signal) traps, I signal
my PID with the signal that I'd trapped - that will cause the PID
to then exit with the relevant value, indicating it exited from signal
(and the same one I'd trapped).  And 1 2 3 15 are respectively HUP INTR
QUIT TERM signals - fairly normal/common ways a program may get signaled
to exit.

> On to the video:
>  > The Problem with Bash 'Strict Mode'
>  > - Why I Don't Use `set -euo pipefail`
> https://www.youtube.com/watch?v=4Jo3Ml53kvc

>   i.e. how to handle exit values > 128.

Yeah, exit/return value >128 is exit from signal,
subtract 128 to get the signal number,
or high bit set, exit from signal, clear the high bit to get the signal
number.  And useful beyond just shell, as that's part of the status
information exiting PID returns to PPID.



More information about the sf-lug mailing list