我正在尝试编写一个记录Java程序退出状态的shell脚本。该脚本应该简单地启动一个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$1
并且脚本应该检测到应用程序无法启动。
所有这些都很有效,直到我尝试使用&在后台启动Java应用程序。每当我这样做时:
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log" &
脚本总是为$?返回0,表示它已通过。
我究竟做错了什么?有没有更好的方法来检测应用程序是否无法启动?
谢谢!
答案 0 :(得分:2)
等待!您正在记录wait
的退出状态!
这就是您在脚本中看到意外结果的原因。查看bash的手册页(wait
是一个内置的bash,所以你需要阅读bash手册):
等[-n] [n ...]
等待每个指定的子进程并返回其终止状态。每个n可以是进程ID ...如果未给出 ,则等待所有当前活动的子进程,并且返回状态为零(!)。如果n指定不存在的进程或作业,则返回状态为127.否则,返回状态是最后一个进程的退出状态...等待。
由于您尚未指定n
(要等待的子pid),因此规格的返回状态为零。
另一个问题是:你真的需要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
我想知道的是应用程序是否在启动时失败。对于前者,我的脚本会将应用程序和角色打包到以前的版本中。 这个目的太模糊了。您是否只对缺少依赖项感兴趣?
我认为没有一种简单的方法可以区分JRE非零退出代码和java应用程序非零退出代码。
我可以想象很多其他原因可以展开部署,其中很多都不会导致非零退出代码。