Search code examples
bashif-statementposixbackground-process

Sequence of bash commands fails when enclosed in if ... fi - Why? And how to write it in POSIX style?


The following sequence of commands works fine

EHRbase_VERSION=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec)
echo ${EHRbase_VERSION}
java -jar application/target/application-${EHRbase_VERSION}.jar --cache.enabled=false > log &
grep -m 1 "Started EhrBase in" <(tail -f log)

But when I try to run them conditionally they don't work as I want

if [ "${MY_ENV}" != "FOO" ]; then
  EHRbase_VERSION=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec)
  echo ${EHRbase_VERSION}
  java -jar application/target/application-${EHRbase_VERSION}.jar --cache.enabled=false > log &
  grep -m 1 "Started EhrBase in" <(tail -f log)
fi

The result is

0.13.0
[1] 17584

# from here it seems to hang and I have to exit w/ CTRL+C

What is going wrong? How to write it correctly in BASH? How to write it in POSIX?


Solution

  • Simply put: If file is a regular file (and not a named pipe), tail -f file never finishes. If there isn't any message that matches Started EhrBase in in your file, then, it's normal and expected for this code to hang forever.

    It'll never finish even without the surrounding if either -- the surrounding code is surely a red herring.


    Maybe you want to just wait for up to a certain amount of time to see the log message? timeout (from GNU coreutils) is your friend:

    java -jar "application/target/application-${EHRbase_VERSION}.jar" \
        --cache.enabled=false >log & app_pid=$!
    if ! tail -f log | timeout 30s grep -m 1 "Started EhrBase in"; then
      echo "WARNING: Did not see a startup message even after waiting 30s" >&2
      if kill -0 "$app_pid"; then
        echo "...although EHRbase is still running" >&2
      else
        echo "...and EHRbase did not successfully start" >&2
      fi
    fi