bash 命令序列在包含在 if ... fi 中时失败 - 为什么?以及如何以 POSIX 风格编写它?

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

以下命令序列可以正常工作

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)

但是当我有条件地尝试 运行 它们时,它们并没有像我想要的那样工作

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

结果是

0.13.0
[1] 17584

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

出了什么问题? BASH中如何正确书写? POSIX怎么写?

简单地说:如果 file 是一个常规文件(而不是命名管道),tail -f file 永远不会完成。如果您的文件中 没有 任何与 Started EhrBase in 匹配的消息,那么此代码将永远挂起是正常的。

即使没有周围的 if 也永远不会完成 -- 周围的代码肯定是转移注意力的。


也许您只想等待一定的时间才能看到日志消息? timeout(来自 GNU coreutils)是你的朋友:

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