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

时间:2016-05-18 01:00:11

标签: java shell exit-code

我正在尝试编写一个记录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,表示它已通过。
我究竟做错了什么?有没有更好的方法来检测应用程序是否无法启动?

谢谢!

1 个答案:

答案 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应用程序非零退出代码。

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