Bash script to start spring-boot app and finish script - bash

I have a bash script to deploy my spring-boot app (using bamboo).
script gets hung on this as the spring-boot app launches and is running
java -jar myApp.jar
I tried running it in the background with
java -jar myApp.jar &
as well as
java -jar myApp.jar &
disown
just "&" seems to do nothing while the "&" followed by "disown" made the script fail.
How do I let the script finish while the spring-boot app keeps running?

There is multiple options, one as mentioned is 'nohup' command. Another way to run is using 'screen' virtual terminal. But I would suggest you take a considerably better approach and run it as any other background service on *nix machines (like apache, mysql, etc.)
Here my very simple code that I have inside of /etc/init.d/great-spring-boot-app script, you can edit few lines to suite your conventions and save this file with
any name inside of /etc/init.d/ directory, for example /etc/init.d/my-cool-spring-boot-app
Then make it executable:
chmod +x /etc/init.d/my-cool-spring-boot-app
Afterwards can simply start process by doing something like
sudo service my-cool-spring-boot-app start
Other options are:
stop|restart|status
#!/bin/bash -
#=-= START OF CUSTOM SERVICE CONFIGURATION =-#
# Where micro service war/jar file sits?
MS_HOME=/opt/MY_MICRO_SERVICE_ROOT_DIRECTORY # <--- EDIT THIS LINE
# Actual file name of Micro Service (jar or war),
# ms-service.war or something-0.0.1-SNAPSHOT.jar, etc.
MS_JAR=MY_SPRING_BOOT_APPLICATION-0.0.1-SNAPSHOT.war # <--- EDIT THIS LINE
# ^^^ that should relative to MS_HOME directory.
# Which username we should run as.
RUNASUSER=USER_TO_RUN_AS; # <-- EDIT THIS LINE,
# if port number for spring boot is < 1024 it needs root perm.
JAVA_HOME=/usr/local/jdk1.8.0_60; # <-- EDIT THIS, Where is your JDK/JRE?
PATH=${JAVA_HOME}/bin:${PATH};
SHUTDOWN_WAIT=20; # before issuing kill -9 on process.
export PATH JAVA_HOME
# These options are used when micro service is starting
# Add whatever you want/need here... overrides application*.yml.
OPTIONS="
-Dserver.port=8080
-Dspring.profiles.active=dev
";
#=-= END OF CUSTOM CONFIGURATION =-=#
# Try to get PID of spring jar/war
MS_PID=`ps fax|grep java|grep "${MS_JAR}"|awk '{print $1}'`
export MS_PID;
# Function: run_as
run_as() {
local iam iwant;
iam=$(id -nu);
iwant="$1";
shift;
if [ "${iam}" = "${iwant}" ]; then {
eval $*;
}
else {
/bin/su -p -s /bin/sh ${iwant} $*;
} fi;
}
# Function: start
start() {
pid=${MS_PID}
if [ -n "${pid}" ]; then {
echo "Micro service is already running (pid: ${pid})";
}
else {
# Start screener ms
echo "Starting micro service";
cd $MS_HOME
run_as ${RUNASUSER} java -jar ${OPTIONS} ./${MS_JAR};
# java -jar ${OPTIONS} ./${MS_JAR}
} fi;
# return 0;
}
# Function: stop
stop() {
pid=${MS_PID}
if [ -n "${pid}" ]; then {
run_as ${RUNASUSER} kill -TERM $pid
echo -ne "Stopping micro service module";
kwait=${SHUTDOWN_WAIT};
count=0;
while kill -0 ${pid} 2>/dev/null && [ ${count} -le ${kwait} ]; do {
printf ".";
sleep 1;
(( count++ ));
} done;
echo;
if [ ${count} -gt ${kwait} ]; then {
printf "process is still running after %d seconds, killing process" \
${SHUTDOWN_WAIT};
kill ${pid};
sleep 3;
# if it's still running use kill -9
#
if kill -0 ${pid} 2>/dev/null; then {
echo "process is still running, using kill -9";
kill -9 ${pid}
sleep 3;
} fi;
} fi;
if kill -0 ${pid} 2>/dev/null; then {
echo "process is still running, I give up";
}
else {
# success, delete PID file, if you have used it with spring boot
# rm -f ${SPRING_BOOT_APP_PID};
} fi;
}
else {
echo "Micro service is not running";
} fi;
#return 0;
}
# Main Code
case $1 in
start)
start;
;;
stop)
stop;
;;
restart)
stop;
sleep 1;
start;
;;
status)
pid=$MS_PID
if [ "${pid}" ]; then {
echo "Micro service module is running with pid: ${pid}";
}
else {
echo "Micro service module is not running";
} fi;
;;
esac
exit 0;
This is the appropriate way to start background service(s) on Linux.

nohup java -jar myApp.jar &
nohup will intercept the HUP (hangup) signal when the TTY closes. This prevents the process from being terminated when the user logs out / your remote session ends. The ampersand is for starting the process in the background.

Easy stop / start spring boot application uber jar
https://github.com/tyrion9/spring-boot-startup-script
Copy uber jar file in the same folder
./bootstrap.sh start
./bootstrap.sh stop
./bootstrap.sh restart

Using start and shutdown scripts
I have answered similar question here.
You could use a set of scripts to achieve this. For example a startup.sh may look like this. It will start the application and write the process id to /path/to/app/pid.file .And the nohup disowns the process so the process doesn't hold on to current TTY session.
#!/bin/bash
nohup java -jar /path/to/app/hello-world.jar > /path/to/log.txt 2>&1 &
echo $! > /path/to/app/pid.file
And a shutdown.sh may look like this.
#!/bin/bash
kill $(cat /path/to/app/pid.file)
You can find more detail in my post. https://springhow.com/start-stop-scripts-for-spring-boot-applications/

Related

restarting delayed_job script via monit breaks /usr/lib/ruby/2.3.0/rubygems/core_ext/kern

So i am trying to use monit to monitor my delayed_job processes. And to do that, i have written this
/home/deploy/sites/app.project.com.my/shared/delayed_job.monitrc
check process delayed_job_0
with pidfile /home/deploy/sites/app.project.com.my/shared/pids/delayed_job.0.pid
start program = "/home/deploy/sites/app.project.com.my/shared/delayed_job.sh start staging 0"
as uid deploy and gid deploy
stop program = "/bin/su - deploy -c '/home/deploy/sites/app.project.com.my/current/bin/delayed_job stop staging 0'"
group delayed_job
I have also written this script
/home/deploy/sites/app.project.com.my/shared/delayed_job.sh
#!/bin/bash
APP_NAME=app.project.com.my
APP_DIR=/home/deploy/sites
RAILS_ROOT=$APP_DIR/$APP_NAME/current
LOG_FILE=$APP_DIR/$APP_NAME/shared/delayed_job_monit.log
exec 2>&1
if [ "$3" ]; then
RUNNER="$3"
else
RUNNER=0
fi
echo "Runner: $RUNNER"
ENVIRONMENT=$2
echo "Env: $ENVIRONMENT"
PID_FILE=$RAILS_ROOT/tmp/pids/delayed_job.$RUNNER.pid
echo "Pid: $PID_FILE"
cd $RAILS_ROOT
echo "Received $1"
function stop {
cd $RAILS_ROOT
RAILS_ENV=$ENVIRONMENT /usr/bin/env bin/delayed_job stop -i $RUNNER
}
function start {
if [ -f $PID_FILE ]; then
echo "Pid Found. Deleting PID FILE: $PID_FILE"
rm -f $PID_FILE
fi
CMD=" /usr/bin/env RAILS_ENV=$ENVIRONMENT bin/delayed_job start -i $RUNNER"
cd $RAILS_ROOT
exec $CMD
}
case $1 in
start)
stop
start
;;
stop)
stop
;;
*)
echo "WTF"
;;
esac
Now when in this folder /home/deploy/sites/app.project.com.my/shared/, if i run the delayed_job.sh script like this ./delayed_job start staging 0. it works properly and the delayed_job is restarted.
But when i run the monit script sudo monit start delayed_job_0, i get an error /usr/lib/ruby/2.3.0/rubygems/core_ext/kern
Currently not sure how to get rid of this error.

how to run and stop a bash script in a init.d process?

i have a process script and i want it to run and stop (if already running) a bash script.
I've tried pkill -x test but it doesn't seem to work. in any case i believe i need a if statement, to see if test.sh is running..
EDIT: in the stop i added for i inps ax | grep 'test' | awk '{print $1}'; do kill -9 $i; done
that seems to fix it.. need to do some more testing
here is the code:
#!/bin/bash
# chkconfig: 2345 20 80
# description: Description comes here....
# Source function library.
. /etc/init.d/functions
prog="test"
NEWLINE=$'\n'
start() {
STR=$"Starting $prog ${NEWLINE}"
echo "$STR"
/var/www/html/test.sh
# code to start app comes here
# example: daemon program_name &
}
stop() {
STR=$"Stopping $prog ${NEWLINE}"
echo "$STR"
pkill -x test
# code to stop app comes here
# example: killproc program_name
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
${0} stop
sleep 1
${0} start
;;
status)
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
esac
exit 0
any ideas?
Maybe if the script test.sh puts a file in /var/run with it's pid. You can use the variable $$ for that.
Then you could look for for the process with the pid with ps and grep in the init script and killing it easy.

Launch Java application at startup on Centos

I need to launch a Java application on Centos (5.9) startup.
I am trying to start a simple script (named "lanzar.sh") on Centos at boot time:
#!/bin/sh
cd /home/someuser/Desktop/Dist
java -jar SomeApp.jar
I append the line "/bin/sh /home/someuser/Desktop/Dist/lanzar.sh" to /etc/rc.d/rc.local. But the java application does not start. I have:
Granted 755 rights to the /etc/rc.d/rc.local file
Write the content of the "lanzar.sh" into /etc/rc.d/rc.local. Separated with semicolon, and in different lines.
Changing "lanzar.sh" of location.
Other things, taken from other threads that did not work for me.
My rc.loca looks like:
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
#
#Some comment
#Some comment
#Some comment
touch /var/lock/subsys/local
/bin/sh /home/fernando/Desktop/Dist/lanzar.sh
Note: I know similar questions have been asked before, but after testing many of the answers that I have found by googling with no success, I had to ask this myself.
I highly recommend that you explore the /etc/init.d directory of your server and the /etc/rc3.d directory. See how the names of the files in /etc/rc3.d are symbolically linked to the names in the /etc/init.d directory. Notice how the files in /etc/rc3.d all start with Sxx or Kxxwherexx is a number between 00 to 99.
What I am about to tell you is officially all wrong. These startup scripts are way more complicated today that what I describe, but it's a basic outline of what's going on.
In standard Unix and Linux, startup scripts were normally stored in /etc/init.d and then linked to the /etc/rcX.d directory where X stood for what was called the Init States of the server. (Yes, I'm linking to an SCO Unix page, but they were all pretty similar).
Note that Init State 3 is running in multi-user mode and that all the daemons are started. This is why I am telling you to look in /etc/rc3.d.
When the server enters that init state, it runs all of the script starting with S in alphabetical order. It runs each script with the parameter start after it. So, S01xxxx starts before S03xxx which starts before S99xxxxx.
When the server exits that init state, it runs all of the scripts that start with K in alphabetical order, and passes the stop parameter to them.
Now, Centos, Redhat, and Fedora setup handles a lot of this for you. You specify which service you depend upon, and it figures out startup and shutdown order. However, nothing is preventing you from munging a startup script and creating your own links.
By the way, speaking about Java programs that startup and shutdown... Jenkins is a Java program that's started in a very similar way as your program. Here's the /etc/init.d script I got off of Jenkins website:
#!/bin/bash
#
# Startup script for Jenkins
#
# chkconfig: - 84 16
# description: Jenkins CI server
# Source function library.
. /etc/rc.d/init.d/functions
[ -z "$JAVA_HOME" -a -x /etc/profile.d/java.sh ] && . /etc/profile.d/java.sh
JENKINS_HOME=/var/jenkins
WAR="$JENKINS_HOME/jenkins.war"
LOG="/var/log/jenkins.log"
LOCK="/var/lock/subsys/jenkins"
export JENKINS_HOME
RETVAL=0
pid_of_jenkins() {
pgrep -f "java.*jenkins"
}
start() {
[ -e "$LOG" ] && cnt=`wc -l "$LOG" | awk '{ print $1 }'` || cnt=1
echo -n $"Starting jenkins: "
cd "$JENKINS_HOME"
nohup java -jar "$WAR" --httpPort=-1 --ajp13Port=8010 --prefix=/jenkins >> "$LOG" 2>&1 &
while { pid_of_jenkins > /dev/null ; } &&
! { tail +$cnt "$LOG" | grep -q 'Winstone Servlet Engine .* running' ; } ; do
sleep 1
done
pid_of_jenkins > /dev/null
RETVAL=$?
[ $RETVAL = 0 ] && success $"$STRING" || failure $"$STRING"
echo
[ $RETVAL = 0 ] && touch "$LOCK"
}
stop() {
echo -n "Stopping jenkins: "
pid=`pid_of_jenkins`
[ -n "$pid" ] && kill $pid
RETVAL=$?
cnt=10
while [ $RETVAL = 0 -a $cnt -gt 0 ] &&
{ pid_of_jenkins > /dev/null ; } ; do
sleep 1
((cnt--))
done
[ $RETVAL = 0 ] && rm -f "$LOCK"
[ $RETVAL = 0 ] && success $"$STRING" || failure $"$STRING"
echo
}
status() {
pid=`pid_of_jenkins`
if [ -n "$pid" ]; then
echo "jenkins (pid $pid) is running..."
return 0
fi
if [ -f "$LOCK" ]; then
echo $"${base} dead but subsys locked"
return 2
fi
echo "jenkins is stopped"
return 3
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit $RETVAL
It'll give you something to work with.

JBoss Init Script - Trapping issue

I have a script that I'm making to use to start/stop/etc a JBoss AS (v7.1.1). I'm running on SUSE Enterprise 11, so the provided initscript doesn't work. The problem I'm running into with my script is that the cleanup function is never called.
#!/bin/sh
HOME="/var/rulesserver"
CURRENT=$HOME/logs/current
LOGFILE=$HOME/logs/`date -u +%Y-%m-%d-%H-%M-%S`.log
COMMAND=/usr/local/jboss/bin/standalone.sh
SELF=/usr/sbin/jboss-as-standalone
function cleanup() {
rm $CURRENT
}
function run() {
trap cleanup 1 2 3 6 15
nohup $COMMAND &> $CURRENT
}
case $1 in
"start" )
echo "Starting the server..."
if [ -e $CURRENT ]
then
echo "ERROR: The server is already running"
else
ln -s $LOGFILE $CURRENT
run &
echo "Server started"
fi
;;
"stop" )
echo "Stopping the server..."
killall java
echo "Server stopped"
;;
"status" )
if [ -e $CURRENT ]
then
echo "The server is currently running"
else
echo "The server is currently stopped"
fi
;;
"cleanup" )
cleanup
;;
"restart" )
$SELF stop
$SELF start
;;
* )
$SELF start
;;
esac
There is a method provided in the standalone.sh startup script that you can use to control it's behavior. Just set the value of environment variable LAUNCH_JBOSS_IN_BACKGROUND to some value, ie.
LAUNCH_JBOSS_IN_BACKGROUND=true
before calling the script and then you will no longer need nohup to do the job for you, and no cleanup will be necessary.
Also, there is an option to tell JBoss AS to write the "console output" to a file, so you can still have the messages that it will be generating.
One more thing: I personally do not think that killall java is 100% clever thing to do in all the possible circumstances.
I may be confused, but can you not just do
function run() {
( nohup $COMMAND ; rm $CURRENT )
}
?
$COMMAND would block till i dies and then there would be an rm and then the subshell would exit? There would be no need for trap.

fedora 13 init.d script, can't stop

I wrote init.d script that suppose to run java CLI proccess.
The problem is that when i stop it, i get [failed] and the proccess is still running.
thanks
#!/usr/bin/env bash
#
# chkconfig: 345 97 03
#
# processname: quotes-srv
#
#
# source function library
. /etc/rc.d/init.d/functions
NAME=quotes-srv
start() {
echo -n $"Starting $NAME: "
daemon +19 java -Dlog4j.configuration="file:/opt/quotes/properties/log4j/log4j.properties" -Dproperties_folder="/opt/quotes/properties/app/" -jar /opt/quotes/trade-0.0.1-SNAPSHOT-jar-with-dependencies.jar &
touch /var/lock/subsys/$NAME
}
stop() {
echo -n $"Stopping $NAME: "
killproc $NAME
echo
rm -f /var/lock/subsys/$NAME
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|force-reload|reload)
restart
;;
condrestart|try-restart)
[ -f /var/lock/subsys/$NAME ] && restart
;;
status)
status $NAME
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
exit 1
esac
exit 0
killproc will terminate programs in the process list which match the name $NAME
Strictly speaking this is in your case java .
If it is the only java process you can go and put java in $NAME
If you run other java services you have to find another way to stop your java process, e.g. putting the PID in the /var/lock/subsys/$NAME file and then killing the process using the pid.
On at least debian there is a nice tool which helps with this, but I am not sure it exists for
redhat.

Resources