My problem is gonna be a little difficult to explain, so please bear with me.
I'm trying to write a shell script that will start a Java HTTPServer
as a background process. The relevant line in the script is seemingly very simple:
java -jar "$jar.jar" &
However, I need to somehow check that there aren't problems when Java tries to run the jar. For example, if I were to touch Server.jar
, I want to catch java's failure to run that empty jar. So, I was trying to just wrap it in an if statement:
if ! java -jar "$jar.jar" &
then
echo "Couldn't start server" >&2
fi
This doesn't work. The returned status is the same regardless of whether java was actually able to run the jar
or not. I noticed that if I omit the ampersand at the end, it does what I want in cases where the jar
is bad. However, this obviously causes the script to wait on that line until the server is stopped when the jar is good, so there's no way to send the process to the background.
Is there any easy way to accomplish this?
A common way of doing this is to ignore the exit status entirely, and instead check that the server starts successfully within a timeout (here that it opens port 8080
as probed by nc
):
# Start server
java -jar "$jar.jar" &
# Wait for up to 30s
printf "%s" "Waiting for server to respond"
timeout=30
until nc -z localhost 8080 || (( --timeout == 0 ))
do
sleep 1
printf "."
done
# Check result
if (( timeout > 0 ))
then
echo "Server started successfully"
else
echo "Server still not responding"
fi
This is better than ensuring that the process runs for 30 seconds without dying, because in the happy case it'll continue very quickly.
You can additionally make it immediately abort if the process dies (as checked with kill -0 $!
). This probably works for your java
command, but other servers like Apache have startup commands that exit immediately while the server keeps running.