Need an init script for a Java service? Like tomcat, liferay, or jboss?
Regular Linux init scripts often don’t work so well. e.g. Java apps typically want to be run by a particular user (e.g. tomcat or liferay). e.g. They may require a ’special’ shutdown mechanism (e.g. with Tomcat sending a signal to a particular port).
So over the years I have had a handy-dandy script that can control most of my most commonly used Java apps (liferay, tomcat, jboss).
It does things like start up the app as a particular user. Checks to ensure the app is responding on a URL before saying it is stared. Waits for the app to shutdown gracefully, else forces it to quit. And provides kill and killstart commands when you’re developing and just want the thing restarted!
This morning I updated it to use the lsb logging methods. So the output is a bit prettier than the ‘old’ echo’s we used to use.
The current version of the file will live at http://proj.ri.mu/javainitscript
To use it wget that to the /etc/init.d directory on your server. Then rename (or symlink) it to the service you want to control. Currently the tomcat, liferay and jboss names are supported.
Some excerpts (if you’re using the script, alway use the one at http://proj.ri.mu/javainitscript) :
#!/bin/bash # Startup script for Jakarta Tomcat, Lferay, JBoss, or potentially other java apps if [ -e /etc/debian_version ]; then . /lib/lsb/init-functions elif [ -e /etc/init.d/functions ] ; then . /etc/init.d/functions fi # else we include the crucial log_* methods for lsb-deprived distros # how long to wait for the app to startup before saying 'its probably up' STARTWAITTIMES=45 # figure out what to do based on the name of this script if echo $0 | grep -qai tomcat; then HOMEDIR=/usr/local/tomcat TOMCAT_USER=tomcat APPNAME=Tomcat elif echo $0 | grep -qai jboss; then .... else log_failure_msg "Unknown startup script name $0" exit 1 fi # something so we can test if the app is fully started TESTURL=http://127.0.0.1:8080/ if [ -e $HOMEDIR/initscript/testurl ]; then TESTURL=$(cat $HOMEDIR/initscript/testurl) fi # makes it a bit easier to find if the process is running. e.g. put a -Dsomeval=Y # into the JAVA_OPTS for the program. e.g. in catalina.sh or setenv.sh or run.conf if [ -e $HOMEDIR/initscript/grepstring ]; then GREPSTRING=$(cat $HOMEDIR/initscript/grepstring) fi #Necessary environment variables export JAVA_HOME=/usr/java/jdk #export LD_KERNEL_ASSUME="2.2.5" if [ "$APPNAME" = "Tomcat" -o "$APPNAME" = "Liferay" -o "$APPNAME" = "Alfresco" ]; then export CATALINA_HOME=$HOMEDIR INITSCRIPT=$HOMEDIR/bin/catalina.sh RUNCOMMAND="export CATALINA_HOME=$CATALINA_HOME; $INITSCRIPT start" STOPCOMMAND="$INITSCRIPT stop" STARTGREPTEXT="[o]rg.apache.catalina.startup.Bootstrap start" LOGFILE=$HOMEDIR/logs/catalina.out elif [ "$APPNAME" = "JBoss" ]; then .... else log_failure_msg "Only JBoss and Tomcat are recognised. Not $APPNAME" exit 1 fi setpslist() { PSLIST=$(ps a --width=1000 --User "$TOMCAT_USER" -o pid,user,command | grep "$GREPSTRING" | grep -v PID | awk '{printf $1 " "}') } start() { setpslist log_daemon_msg "Starting" "$APPNAME" if [ ! -z "$PSLIST" ]; then log_warning_msg "$APPNAME already running, can't start it" log_end_msg 1 return 1 fi chown -R $TOMCAT_USER $HOMEDIR exec su - -p --shell=/bin/sh $TOMCAT_USER -c "cd $(dirname $INITSCRIPT); $RUNCOMMAND >\"$LOGFILE\"" 2>&1 & local starttime=$(date +"%s") # wait a bit for the app to start up while true; do sleep 3 local now=$(date +"%s") if wget --tries=1 --timeout=1 --server-response -O - $TESTURL 2>&1 | grep -qai " HTTP/1.1 "; then log_end_msg 0 break fi # process not starting (cf. http response not happening) if [ $(($now - 15 )) -gt $starttime ]; then setpslist if [ -z "$PSLIST" ]; then log_failure_msg "Java process not starting. Last few lines from the startup log follow:" log_failure_msg "$(tail -n 4 $LOGFILE)" log_end_msg 1 return 1 fi fi if [ $(($now - $STARTWAITTIMES)) -gt $starttime ]; then log_warning_msg "$APPNAME startup taking too long, not getting a response on $TESTURL, giving up" log_end_msg 0 return 0 fi log_progress_msg . done } killprocesses() { log_daemon_msg "Killing" "$APPNAME" setpslist if [ -z "$PSLIST" ]; then log_progress_msg "$APPNAME not running, no need to kill it" log_end_msg 0 fi kill -9 $PSLIST log_end_msg 0 } stop() { log_daemon_msg "Stopping" "$APPNAME" setpslist if [ -z "$PSLIST" ]; then log_progress_msg "$APPNAME not running, no need to stop it" log_end_msg 0 fi waslistening=N needtokill=N if wget --tries=1 --timeout=1 --server-response -O - $TESTURL 2>&1 | grep -qai " HTTP/1.1 "; then waslistening=Y fi suoutput=$(su - --shell=/bin/bash -p $TOMCAT_USER -c "$STOPCOMMAND" 2>&1) local starttime=$(date +"%s") # wait a while for the app to shutdown gracefully, else kill it while true; do sleep 3 local now=$(date +"%s") setpslist if [ -z "$PSLIST" ]; then log_end_msg 0 return 0 fi if echo $suoutput | egrep -qai "(Refused|Address already in use)" ; then log_warning_msg "'stop' signal refused, killing $APPNAME." kill -SIGTERM $PSLIST elif [ $(($now - 50)) -gt $starttime ]; then log_warning_msg "Graceful shutdown taking too long, terminating it."; kill -SIGTERM $PSLIST elif [ $(($now - 50)) -gt $starttime ]; then log_warning_msg "Graceful shutdown taking too long, killing it."; kill -SIGKILL $PSLIST elif [ "$needtokill" = "Y" ]; then log_progress_msg "Killing. " kill -SIGKILL $PSLIST elif [ "$waslistening" = "Y" -a "$needtokill" = "N" ]; then if ! wget --tries=1 --timeout=1 --server-response -O - $TESTURL 2>&1 | grep -qai " HTTP/1.1 " ; then log_progress_msg "Stopped listening on http, but not shutting down fully. " needtokill=Y sleep 10 fi fi # echo -n $(echo $PSLIST | wc -w) " " done } status() { setpslist if [ ! -z "$PSLIST" ]; then local MSG="$APPNAME ( PIDs $PSLIST ) is running." if wget --tries=1 --timeout=1 --server-response -O - $TESTURL 2>&1 | grep -qai " HTTP/1.1 "; then log_success_msg "$MSG And listening on $TESTURL." else log_warning_msg "$MSG But not responding on $TESTURL." fi else log_failure_msg "$APPNAME is not running" fi } case "$1" in start) start ;; stop) stop ;; restart) stop sleep 3 start ;; kill) killprocesses ;; killstart) killprocesses start ;; status) status ;; *) echo "Usage: $0 {start|stop|restart|status|kill|killstart}" exit 1 esac exit $?







