Home > OS >  How do I assert something in bash, print a useful error message, and then still fail?
How do I assert something in bash, print a useful error message, and then still fail?

Time:01-27

Without installing anything on a barebones bash, is there a simple and clear way to:

  • test a value
  • print out a message if it's not what you want
  • still fail (without exiting the window/shell)

Currently, I've got:

[[ -n "$some_val" && -n "$other_val"]] || {echo "Unable to retrieve xxx from yyy"; false}

that's kind of a wtf to read, but then this is more verbose than I'd like for such a simple assertion:

if test -n "$some_val" && test -n "$other_val"; then
  echo "Unable to retrieve xxx from yyy"
  false
fi

What I'd really love would be to have something like:

test -n "$some_val" -m "some_val missing" && test -n "$other_val" "other_val missing"

or:

[[ -n "$some_val" && -n "$other_val" ]] || fail "Unable to retrieve xxx from yyy"

CodePudding user response:

die() { rc=$?; (( $# )) && printf '%s\n' "$*" >&2; exit $(( rc == 0 ? 1 : rc )); }

do_something || die "explanation of how it failed"

Let's break this down:

  • Capturing $? at the top of the function lets us get the exit status that caused the function to be invoked.
  • Checking $# lets us log an error message only if there actually was an error to log.
  • If we do log a message, we send it to stderr so our message doesn't get mixed in with output (and potentially directed to a file or pipeline where the user will never see it).
  • $(( rc == 0 ? 1 : rc )) causes us to exit with status 1 if die was called when $? didn't reflect a failure, or the prior exit status otherwise.

If you don't want to exit the shell interpreter but just want to pass the exit status along, change the exit to return.

CodePudding user response:

The function you want is trivial to define:

fail () {
    printf '%s\n' "$1" >&2
    return "${2:-1}"
}

test -n "$some_val" || fail "Value is empty"

(The definition is overly general, so that you can provide an explicit exit status for the function if 1 isn't desired, for example, complicated_test || fail "Failed, preserving exit status" $?. The $? will contain the exit status of the command that allowed the second half of the || list to execute.)

  •  Tags:  
  • bash
  • Related