All of my Java applications are deployed onto a Unix (Linux or Solaris) environment and so I need to have a unix wrapper shell script in order to start and stop them. I looked at Java Service Wrapper but I wanted something simpler. So I wrote my own little wrapper, based on JSW.
The wrapper allows you to invoke the following set of commands on your application:
start
: Starts up the application and writes its pid to a pid file. it also writes the hostname to the pid file. This is important, in case you try to run commands on the application on a different server. After starting, it waits a number of seconds and then checks to see if the application is still running.
stop
: Stops the application using the kill
command. If it has not died within 10 seconds, it executes the harder kill -9
command.
restart
: Restarts the application by calling stop
and then start
.
status
:Reads the pid file and invokes kill -0
on the pid to see if the process is alive. If the process is not alive, an email alert is generated, if the $EMAIL
variable has been set.
dump
: Generates a full Java thread dump by invoking kill -3
on the pid
purge
: Purges log files
Here is the wrapper script (bin/console.ksh
):
#! /bin/ksh
# A generic wrapper script to stop and start components.
# Usage: console.ksh { start | stop | restart | status | purge | dump }
#
APP_NAME="APP"
APP_LONG_NAME="MyApplication"
#the location of the pid files.
PIDDIR="../pid"
PIDFILE="$PIDDIR/$APP_NAME.pid"
TIMESTAMP=$( date +%Y%m%d_%H%M%S )
#number of seconds to wait after starting up.
WAIT_AFTER_STARTUP=2
#the location of the log files
LOG_DIR="../log"
STDOUT="$LOG_DIR/${APP_NAME}.stdout.log"
PURGE_EXPRESSION="-mtime +2"
VMARGS="-Xms250M -Xmx3000M -verbose:gc"
MAINCLASS="com.blogspot.fahdshariff.MyApplication"
ARGS="arg1 arg2"
if [ -z ${JAVA_HOME} ]
then
echo JAVA_HOME has not been set.
exit 1
fi
START_COMMAND="${JAVA_HOME}/bin/java $VMARGS $MAINCLASS $ARGS"
#-----------------------------------------------------------------------------
# Do not modify anything beyond this point
#-----------------------------------------------------------------------------
getpid() {
pid=""
if [ -f "$PIDFILE" ]
then
if [ -r "$PIDFILE" ]
then
pid=`cat "$PIDFILE"|cut -d: -f1`
host=`cat "$PIDFILE"|cut -d: -f2`
currhost=`hostname`
if [ "$host" != "$currhost" ]
then
echo "You are on the wrong host. $APP_LONG_NAME runs on $host."
exit 1
fi
if [ "X$pid" != "X" ]
then
kill -0 $pid > /dev/null 2>&1
if [ $? -ne 0 ]
then
# Process doesn't exist, so remove pidfile
rm -f "$PIDFILE"
echo "Removed stale pid file: $PIDFILE"
pid=""
fi
fi
else
echo "Cannot read $PIDFILE."
exit 1
fi
fi
}
#tests if the pid is alive
testpid() {
kill -0 $pid > /dev/null 2>&1
if [ $? -ne 0 ]
then
# Process is gone so remove the pid file.
rm -f "$PIDFILE"
pid=""
fi
}
start() {
echo "Starting $APP_LONG_NAME..."
getpid
if [ "X$pid" = "X" ]
then
if [ -s $STDOUT ]
then
#backup current file
mv $STDOUT $STDOUT.sav.${TIMESTAMP}
fi
echo CLASSPATH is $CLASSPATH > $STDOUT
echo ${START_COMMAND} >> $STDOUT
nohup ${START_COMMAND} >> $STDOUT 2>&1 &
echo $!:`hostname` > $PIDFILE
else
echo "$APP_LONG_NAME is already running."
exit 1
fi
# Sleep for a few seconds to allow for intialization if required
# then test to make sure we're still running.
i=0
while [ $i -lt $WAIT_AFTER_STARTUP ]
do
sleep 1
i=`expr $i + 1`
done
if [ $WAIT_AFTER_STARTUP -gt 0 ]
then
getpid
if [ "X$pid" = "X" ]
then
echo "WARNING: $APP_LONG_NAME may have failed to start."
exit 1
else
echo "running ($pid)."
fi
else
echo ""
fi
}
stopit() {
echo "Stopping $APP_LONG_NAME..."
getpid
if [ "X$pid" = "X" ]
then
echo "$APP_LONG_NAME was not running."
else
# Running so try to stop it.
kill $pid
if [ $? -ne 0 ]
then
echo "Unable to stop $APP_LONG_NAME."
exit 1
fi
# If it has not stopped in 10 tries, forcibly kill it
savepid=$pid
CNT=0
TOTCNT=0
while [ "X$pid" != "X" ]
do
# Show a waiting message every 5 seconds.
if [ "$CNT" -lt "5" ]
then
CNT=`expr $CNT + 1`
else
echo "Waiting for $APP_LONG_NAME to exit..."
CNT=0
fi
if [ $TOTCNT -gt 11 ]
then
echo "Killing by force (kill -9)"
kill -9 $pid
fi
TOTCNT=`expr $TOTCNT + 1`
sleep 1
testpid
done
pid=$savepid
testpid
if [ "X$pid" != "X" ]
then
echo "Failed to stop $APP_LONG_NAME."
exit 1
else
echo "Stopped $APP_LONG_NAME."
fi
fi
}
purge() {
pcmd="find $LOG_DIR -follow -type f $PURGE_EXPRESSION -print -exec rm -f {} +"
echo "Running purge: $pcmd"
$pcmd
}
alert() {
if [ "X$EMAIL" != "X" ]
then
echo "$APP_LONG_NAME is not running on `hostname`. Please check and restart." \
| mailx -s "`hostname`: $APP_LONG_NAME is not running" "$EMAIL"
echo "Sent alert to $EMAIL"
fi
}
status() {
getpid
if [ "X$pid" = "X" ]
then
echo "$APP_LONG_NAME is not running."
alert
exit 1
else
echo "$APP_LONG_NAME is running (PID:$pid)."
exit 0
fi
}
dump() {
echo "Dumping $APP_LONG_NAME..."
getpid
if [ "X$pid" = "X" ]
then
echo "$APP_LONG_NAME is not running."
else
kill -3 $pid
if [ $? -ne 0 ]
then
echo "Failed to dump $APP_LONG_NAME."
exit 1
else
echo "Dumped $APP_LONG_NAME."
fi
fi
}
####################
case "$1" in
'start')
start
;;
'stop')
stopit
;;
'restart')
stopit
start
;;
'status')
status
;;
'dump')
dump
;;
'purge')
purge
;;
*)
echo "Usage: $0 { start | stop | restart | status | dump | purge }"
exit 1
;;
esac
exit 0
you have nice site. thanks for sharing this site. various kinds of ebooks are available here
ReplyDeletehttp://feboook.blogspot.com
Great example. thanks for sharing it.
ReplyDelete