1

My question is partially answered here: gitlab ci scripts during which $? is allowed to be non-zero

In principle, I want to achieve the following in bash:

// assume both functions return truthy values and the 2nd doesn't run if 1st fails

$success = test1() && test2();

someOtherStuff();

exit($success);

GitLab CI scripts terminate immediately when any simple command fails (possibly due to set -e, IDK for sure).

The nearest (and taking that link into consideration):

CODE=0
if test1 && test2; then
    CODE=1
fi

someOtherStuff

exit $CODE

Is there any better way? In particular, I'd like to get the real $CODE not a fake one.

5
  • BTW, set -e is not particularly good practice -- see BashFAQ #105. Commented Jan 20, 2018 at 23:54
  • @CharlesDuffy yes, but what I mean is that it is enabled by default in GitLab CI (or something similar with that same behaviour) - it's not my decision. Commented Jan 20, 2018 at 23:56
  • 1
    Also, all-caps names are used for variables with meaning to the OS or system, whereas names with at least one lower-case character are reserved for application use. You should use such lowercase names in your own code, to avoid conflicting with system-meaningful variables which may be added in the future. See pubs.opengroup.org/onlinepubs/9699919799/basedefs/…, fourth paragraph. Commented Jan 20, 2018 at 23:56
  • Yeah, bad habit mixing between uppercase vars required by applications (eg; behat's BEHAT_PARAMS etc) and vars for local use. Commented Jan 21, 2018 at 0:07
  • BTW, if you choose to, you can turn set -e off by putting set +e in your script. Commented Jan 21, 2018 at 3:17

1 Answer 1

1

As I understand it, you're asking how to run a series of commands until one fails, and store the exit status of the failing command for future reference, in a manner which is robust against side effects of set -e.

Using test1, test2 and test3 as our commands:

#!/usr/bin/env bash

test1() { return 0; }
test2() { return 2; }
test3() { echo "THIS SHOULD NOT BE RUN"; }
someOtherStuff() { echo "This should be run; current value of retval is $retval"; }

retval=0
test1 && test2 && test3 || retval=$?
someOtherStuff ||: "ignoring a failure here"
exit "$retval"

|| retval=$? makes test1 && test2 && test3 a checked expression, thus immune to set -e.

: is a synonym for true, with a history of conventional use as a placeholder.


Running the above, we have the following output:

This should be run; current value of retval is 2

...and the exit status of the script is indeed 2.

Sign up to request clarification or add additional context in comments.

1 Comment

Cool, wouldn't have thought about that last ||... I'd have expected immediate termination.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.