0

I have some simple smoke test scripts that generally look like:

set -e

run-command
run-other-command

echo ok

This works great when I expect commands to succeed; if any fails, the set -e will exit the script early with a non-zero exit code.

However sometimes I expect a command to fail, and I want the script to exit otherwise (that is, if the command exits with code 0). I would have thought I could just write:

set -e
run-command-that-succeeds
! run-command-that-fails

But this ignores the exit code. The bash man page says this about set -e:

The shell does not exit [...] if the command's return value is being inverted with !

Alternatives that work are:

set -e
! run-command-that-fails
[[ $? -eq 0 ]]

and

set -e
if run-command-that-fails; then
  exit 1
fi

Are these the best options, or is there a more idiomatic alternative to exit if a command succeeds?

0

2 Answers 2

1

My tests indicate that (! run-command-that-fails) is a solution. This runs run-command-that-fails in a subshell.

If you need to run run-command-that-fails in the main shell for whatever reason, then you need another solution. I notice that { ! run-command-that-fails; } is not a solution.

1

It would be easier if you dropped the set -e completely and instead used something like

should-fail    && exit 1
should-succeed || exit 1

In the above code, the should-fail is expected to fail, and if it fails to do that, the script exits with a non-zero exit code.

The second one is expected to succeed, and the script exits if it doesn't.

Or, if you want consistency in the use of AND-OR-lists,

! should-fail  || exit 1
should-succeed || exit 1 

or

should-fail      && exit 1
! should-succeed && exit 1

For anything that requires more than a simple exit if it fails, I would use

if should-fail; then
    # handle failure in test
    exit 1
fi

if ! should-succeed; then
    # handle failure in test
    exit 1
fi

As you already noticed, with set -e active, the shell does not exit if a command's exit-status is inverted by !. This is a requirement by POSIX. The following is from the POSIX specification for the special built-in utility set, with my emphasis:

The -e setting shall be ignored when executing the compound list following the while, until, if, or elif reserved word, a pipeline beginning with the ! reserved word, or any command of an AND-OR list other than the last.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .