3

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.

The following is my script:

#!/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!

6
  • 1
    You want to run the app in the background but also wait for it's status? Isn't that defeating the purpose of background tasks? Commented May 18, 2016 at 1:14
  • 1
    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. That's down the road though. I just need to see if the application starts up alright. Perhaps "exit status" is the wrong terminology. Commented May 18, 2016 at 1:17
  • 4
    At what point in time should the status be checked? You can either wait for the process to end (which imo means you don't need a background process) or you are left with checking at some more or less random point, since it takes a bit (but still undefined amount) of time for the app to fail. You can check whether the process is still alive perodically, I think that's roughly the approach that system deamons do that. Commented May 18, 2016 at 1:27
  • 1
    An app doesn't have an "exit code" until it exits and you can only see that exit code if you wait for the application to exit. So, as zapl says, if you don't want to wait then you get to check your app periodically to see if it is still alive. (If you know your app takes X long to start up correctly or die then you can just check once after that point instead. But, as is more likely, you don't know that then you just get to keep checking for as long as it might die or until you stop caring. Commented May 18, 2016 at 1:36
  • @Seanimus is anything left unclear to you? Commented May 21, 2016 at 0:17

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.