Strange bash behavior in checkPhase (exiting on failure in if statement)

I have a checkPhase that is attempting to validate that a server has been successfully started. It looks like this:

  checkPhase = ''
    set -euo pipefail

    shopt -o
    shopt -p

    node server/index.js &
    pid="$!"

    set +e
    for i in {0..30}; do
      if curl http://localhost:3000; then
        break
      else
        if [[ "$i" == 30 ]]; then
          echo "Could not reach server"
          kill "$pid"
          exit 1
        else
          sleep 1
        fi
      fi
    done
    set -e

    kill "$pid"
  '';

Pretty standard stuff! The set +e should not be necessary, since exit on error doesn’t apply to if statements anyway, but I added it in there when trying to debug.

However, what I’m seeing is that the checkPhase immediately exits on the first curl failure, without looping. Bash doesn’t behave like this in a normal script, and I can’t find any options in the docs that would seem to cause this behavior.

The check phase output is as follows:

server> Running phase: checkPhase
server> allexport          off
server> braceexpand        on
server> errexit            on
server> errtrace           off
server> functrace          off
server> hashall            on
server> histexpand         off
server> history            off
server> ignoreeof          off
server> interactive-comments       on
server> keyword            off
server> monitor            off
server> noclobber          off
server> noexec             off
server> noglob             off
server> nolog              off
server> notify             off
server> nounset            on
server> onecmd             off
server> physical           off
server> pipefail           on
server> posix              off
server> privileged         off
server> verbose            off
server> xtrace             off
server> shopt -u autocd
server> shopt -u assoc_expand_once
server> shopt -u cdable_vars
server> shopt -u cdspell
server> shopt -u checkhash
server> shopt -u checkjobs
server> shopt -s checkwinsize
server> shopt -s cmdhist
server> shopt -u compat31
server> shopt -u compat32
server> shopt -u compat40
server> shopt -u compat41
server> shopt -u compat42
server> shopt -u compat43
server> shopt -u compat44
server> shopt -u dotglob
server> shopt -u execfail
server> shopt -u expand_aliases
server> shopt -u extdebug
server> shopt -u extglob
server> shopt -s extquote
server> shopt -u failglob
server> shopt -s globasciiranges
server> shopt -s globskipdots
server> shopt -u globstar
server> shopt -u gnu_errfmt
server> shopt -u histappend
server> shopt -u huponexit
server> shopt -s inherit_errexit
server> shopt -s interactive_comments
server> shopt -u lastpipe
server> shopt -u lithist
server> shopt -u localvar_inherit
server> shopt -u localvar_unset
server> shopt -u login_shell
server> shopt -u mailwarn
server> shopt -u nocaseglob
server> shopt -u nocasematch
server> shopt -u noexpand_translation
server> shopt -s nullglob
server> shopt -s patsub_replacement
server> shopt -s promptvars
server> shopt -u restricted_shell
server> shopt -u shift_verbose
server> shopt -s sourcepath
server> shopt -u varredir_close
server> shopt -u xpg_echo
server> curl: (7) Failed to connect to localhost port 3000 after 0 ms: Could not connect to server
server> Listening on http://0.0.0.0:3000

I can toss in a sleep 5 or whatever for now, but I’d prefer to understand what the heck is going on that’s causing this early error.

@mplanchard It looks like set -e is causing your script to exit early because curl fails before it reaches the if condition. You can try using curl || true, disabling set -e temporarily inside the loop, or restructuring the condition with if ! curl.

Thanks for the reply, but that’s not the case. You can see I’m setting set +e prior to the if statement, and even with set -e, failures in if statements don’t exit the script. Try running this as a local bash script and you’ll see it works fine:

set -eo pipefail

if false || false || false; then
  echo "not false"
else
  echo "false"
fi

echo $?

And just to be certain, the behavior persists regardless of whether or not I’ve got set -e in the checkPhase

Ha, it was a classic misinterpretation of output issue.

Turns out it was succeeding just fine, and I was misinterpreting the error return code from the install phase as being from the check phase :man_facepalming:

Thanks for the assistance!

1 Like