Bash scripts are brittle – simple error handling in bash

2 days ago (notifox.com)

I believe that Bash scripts should be trivially short and simple. As soon as any complexity is introduced they should be written in another language.

  • Perl was written to write more complicated bash scripts. It's so seamless to call and handle shell commands and the first class regexes make it terse in a way that's appropriate for this use case.

I declare a `my_die() { echo "$" 1>&2; exit 1; }` on top of each file. Makes life easier by knowing why the script failed instead of having only exit code or having to turn `set -x` on and rerun.

Only if I could somehow mix `if` & `set -e`in a readable way... I wanted it to only capture errors of explicit `return 1` from bash functions, not from commands within those bash functions. But I guess I'm doing too much* of the job in bash now and it's getting messy.

ok so some people call it "brittle" it's 2026, what would impress were if people raised the issues and helped fixing them!

writing in another language, how much more complexity do you want to introducing :)

I believe bash scripts can be anything you want them to be, if they are useful to you then happy day's.

if you hit performance issues or want to experiment else where cool.

error handling in ruby is almost impossible

error handling in python is wildly hit and miss

error handling in golang is rather annoying

error handling in powershell, good luck you will need it

error handling in perl ok i'll stop now you probably get the picture.

bash is glue. write long sequences of command in it. maybe one or two if statements for testing if a file exists. but the minute you start putting branching logic into it.. it's time to reach for another tool.

    #!/usr/bin/env bash
    set -eEuo pipefail # pipefail bash 4.2+, which is basically everything. There's a longer version for backwards compatibility, but it's rare.

    die() {
      echo >&2 "ERROR: $*"
      exit 1
    } 

    # e= & exit preserves the original exit code
    # trap - ... prevents multiple cleanup() calls
    # To only run on error instead of always, replace both EXITs with ERR
    trap 'e=$?; trap - EXIT; cleanup; exit $e' EXIT
    cleanup() {
      : # Delete this line and place cleanup code here.
    }

    # Minimal script here.
    # Use semantic-named functions.
    # DRY.
    # Don't use many levels of indentation.
    # All ordinary variables must be defined before use, so use checks like [[ -n "${X-}" ]]
    # All pipeline and bare command non-zero exit codes are errors.