Shell 脚本不记录 Java 失败时退出状态

Shell script not recording Java exit status on failure

我正在尝试编写一个 shell 脚本来记录 Java 程序的退出状态。该脚本应该简单地启动一个 Java 应用程序,如果 Java 应用程序由于某种原因没有 运行,shell 脚本应该检测到这一点并采取缓解措施。

以下是我的脚本:

#!/bin/bash 

APPNAME="app"
APPFOLDER=$APPNAME
BACKUP=$APPFOLDER"-backup"
LOGFOLDER=$APPNAME"-log"

echo "Starting new app"
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log"
wait 
STATUS=$?
if [ $STATUS -eq 0 ]
   then
      echo "Deployment successful" $?
   else
      echo "Deployment failed: ... derp" $?
fi

我写了一个简单的 Swing GUI,运行没问题。但是,我将它打包为一个 jar,但没有指定入口点。因此,我应该得到错误:

 Exception in thread "main" java.lang.NoClassDefFoundError: Demo

并且脚本应该检测到应用程序启动失败。

在我尝试使用 & 在后台启动 Java 应用程序之前,所有这些工作正常。每当我这样做时:

java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log" & 

脚本总是 returns $? 的 0,表明它通过了。
我究竟做错了什么?有没有更好的方法来检测应用程序是否启动失败?

谢谢!

等等!您正在记录 wait!

的退出状态

这就是您的脚本出现意外结果的原因。查看 bash 的手册页(wait 是内置的 bash,因此您需要阅读 bash 手册):

wait [-n] [n ...]

Wait for each specified child process and return its termination status. Each n may be a process ID... If n is not given, all currently active child processes are waited for, and the return status is zero(!). If n specifies a non-existent process or job, the return status is 127. Otherwise, the return status is the exit status of the last process ... waited for.

由于您没有指定 n(要等待的子 pid),根据规范 return 状态为

另一个问题是:你真的需要wait.

如果您不需要 运行 您的应用程序在后台运行,那么只需执行以下操作:

echo "Starting new app"
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log"
STATUS=$?

唯一的区别是我删除了不必要的 wait

如果出于某种原因您需要 运行 您的应用程序在后台运行并稍后读取退出状态,那么您需要等待该 pid。要找出最后一个后台进程的 pid,请使用特殊变量 $!:

echo "Starting new app"
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log" &
CHILDPID=$!
wait "${CHILDPID}"
STATUS=$?

这是它如何工作的简短示例:

user@s:~$ (sleep 10 && exit 42)&
[1] 27792
user@s:~$ wait "$!"
[1]+  Exit 42                 ( sleep 10 && exit 42 )
user@s:~$ echo $?
42

What I want to know is if the app fails on startup or not. In the case of the former, my script would bag up the app and role out the previous version. This purpose is too vague. Are you only interested in missing dependencies?

我认为没有一种简单的方法可以区分 JRE 非零退出代码和您 java 应用程序非零退出代码。

我可以想象展开部署的许多其他原因,其中许多不会导致非零退出代码。