Reputation: 567
I am trying to write a shell script that records the exit status of a Java program. The script should simple launch a Java app, and if the Java app doesn't run for some reason, the shell script should detect this and take mitigating measures.
#!/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
I have written a simple Swing GUI that runs fine. However, I packaged it as a jar without specifying an entry point. Hence, I should get the error:
Exception in thread "main" java.lang.NoClassDefFoundError: Demo$1
and the script should detect that the application failed to start.
All of this works FINE until I try to launch the Java app in the background using &. Whenever I do this:
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log" &
the script always returns a 0 for $?, indicating it passed.
What am I doing wrong? Is there a better way to go about detecting if the app failed to launch?
Thanks!
Upvotes: 3
Views: 1725
Reputation: 2865
Wait! you are recording the exit status of wait
!
This is why you see unexpected result with your script. Look at the man page for bash (wait
is a bash built-in so you need to read the bash manual):
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.
Since you have not specified the n
(child pid to wait for) the return status is zero as per spec.
Another question is: do you really need a wait
.
If you don't need to run your app in the background then just do this:
echo "Starting new app"
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log"
STATUS=$?
the only difference is that i removed unnecessary wait
.
If for some reason you need to run your app in the background and read exit status later, then you need wait for that pid. To find out the pid of the last background process use special variable $!
:
echo "Starting new app"
java -jar $APPFOLDER/$APPNAME*.jar > $LOGFOLDER/$APPNAME"_$(date+%Y.%m.%d.%s).log" &
CHILDPID=$!
wait "${CHILDPID}"
STATUS=$?
Here's short example of how it works:
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?
I don't think there is an easy way to distinguish between JRE non-zero exit code and you java application non-zero exit-code.
I can imagine lots of other reasons to unroll deployment many of which do not lead to non-zero exit code.
Upvotes: 3