I’ve spent the past couple days working on this, and at this point I am super stuck. I have a Java program that must be run not as a service. This program must also be capable of updating itself when a new file is given for updating.
As a result, I have a script that is started with Linux that starts the Java application and then checks every 5 seconds if the application has been terminated. If the application has been terminated, it should check if there is an update and then start appropriately.
This is the code for that script:
#!/bin/bash JAVA_HOME=/usr/lib/jvm/java-16-openjdk-amd64 WORKING_DIR=~/Data LOG=$WORKING_DIR/logs/Bash.log rm $LOG echo "Script started" > $LOG while true; do source $WORKING_DIR/Server.pid if ! kill -0 $AppPID; then echo "App must be started" >> $LOG source $WORKING_DIR/UpdateStatus if [ "$UpdateReady" -eq "1" ]; then echo "Moving files for update" >> $LOG mv $WORKING_DIR/Server.jar $WORKING_DIR/old.jar mv $WORKING_DIR/new.jar $WORKING_DIR/Server.jar fi nohup ${JAVA_HOME}/bin/java -jar ${WORKING_DIR}/Server.jar & echo AppPID="$!" > $WORKING_DIR/Server.pid echo "Server started" >> $LOG if [ "$UpdateReady" -eq "1" ]; then echo "Checking for safe update" >> $LOG source $WORKING_DIR/Server.pid echo UpdateReady="0" > $WORKING_DIR/UpdateStatus sleep 5; if kill -0 $AppPID; then echo "Update successful" >> $LOG rm $WORKING_DIR/old.jar else echo "Update failed, restarting old jar" >> $LOG rm $WORKING_DIR/Server.jar mv $WORKING_DIR/old.jar $WORKING_DIR/Server.jar nohup ${JAVA_HOME}/bin/java -jar ${WORKING_DIR}/Server.jar & echo AppPID="$!" > $WORKING_DIR/Server.pid fi fi echo "Server start process finished, going into idle state" >> $LOG fi sleep 5 echo "5 seconds idle passed" >> $LOG done
To initialize the update, I have tried a couple of different things, both with the same result. First I had set UpdateReady="1"
through Java, then used exit(0);
. I have also tried having Java call a Bash script which also sets UpdateReady="1"
but uses kill $AppPID
to shutdown the java application.
The result is that both the Java application and the Bash script stop executing causing the update and restart to fail! I have looked through a significant amount of Stack Overflow questions and answers finding things such as nohup
, all to no avail.
I will once again state that the Java application cannot be run as a service. No packages other than what is included in Java or made by Apache can be used, and no programs can be installed to Linux. I would prefer to solve the problem with Bash.
Upon testing some things mentioned in comments, I may have missed something that turns out to be important. While all other runs of the startup script will be run by the startup applications manager, the initial run is not.
The install is taken care of remotely with an SSH connection sending the following command string:
cd /home/UserName; unzip -u -o Server.zip; chmod 777 install.sh; bash install.sh &; exit
install.sh is as follows:
#!/bin/bash INSTALL_DIR=~/Data mkdir ${INSTALL_DIR} mkdir ${INSTALL_DIR}/logs mkdir ${INSTALL_DIR}/data cp Server.jar ${INSTALL_DIR}/Server.jar cp service-start.sh ${INSTALL_DIR}/service-start.sh chmod 777 ${INSTALL_DIR}/service-start.sh rm Server.jar rm service-start.sh rm Server.zip nohup bash $INSTALL_DIR/service-start.sh &
Upon rebooting my machine, I noticed that this problem goes away! This means that there must be a problem with the initial setup script. When the shell command is run, it does seem to be sticky and not actually let go after the bash install.sh &
. I have tried putting nohup
at the beginning of this, however the entire line will not run in that case for reasons I am not able to determine.
I would prefer to not have the user be forced to restart after install and can’t seem to find any way to force the Startup Application manager to start an application at any time other than startup.
Advertisement
Answer
Well, after a lot of searching and some prompting from the comments, I found that the issue lied with how the program was initially being started.
As mentioned in the update, the first run is always started by an ssh connection. I knew there was a slight problem with this ssh connection, as it seemed to hold onto the connection no matter what I did. It turns out that this was causing the problem that resulted in the Bash instance and the Java instance remaining attached.
The solution for this problem was found here: jsch ChannelExec run a .sh script with nohup “lose” some commands
After managing to get the initial setup to start with nohup properly, the issue has gone away.