Service tomcat
| Fiche express | |
|---|---|
| Domaine | Script d'init SysV pour Apache Tomcat |
| Emplacement | /etc/init.d/tomcat
|
| Motif de base | Service generique3 |
| Alternative moderne | unit systemd — voir Systemctl |
| Voir aussi | Service complet · Chkconfig · Java |
Trois versions d'un script d'init SysV pour Apache Tomcat, de la plus simple à la plus robuste. Les trois partagent le même motif de base — lancement via su - utilisateur -c script (voir Service generique3), sans passer par la bibliothèque /etc/init.d/functions — mais divergent sur la fiabilité de la détection d'état et la gestion des erreurs.
Version 1 : basique
Application directe du motif Service generique3 à Tomcat : détection par ps/grep, pas de gestion fine des codes retour.
#!/bin/bash
#
# chkconfig: 345 85 15
# description: service tomcat
## Variables
CATALINA_HOME=/opt/tomcat/apache-tomcat-6.0.20
JAVA_HOME=/usr/local/java
TOMCAT_OWNER=tomcat
export CATALINA_HOME JAVA_HOME TOMCAT_OWNER
## Fonctions
start() {
echo -n "Starting Tomcat: "
su - "$TOMCAT_OWNER" -c "$CATALINA_HOME/bin/startup.sh"
sleep 2
}
stop() {
echo -n "Stopping Tomcat: "
su - "$TOMCAT_OWNER" -c "$CATALINA_HOME/bin/shutdown.sh"
}
status() {
numproc=$(ps -ef | grep catalina | grep -v grep | wc -l)
if [ "$numproc" -gt 0 ]; then
echo "Tomcat is running..."
else
echo "Tomcat is stopped..."
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; start ;;
status) status ;;
*)
echo "Usage: tomcat {start|stop|restart|status}"
exit 1
;;
esac
Correction : les liens wiki [[grep]] insérés directement dans les commandes de l'original cassaient le script une fois copié tel quel — remplacés par grep.
Version 2 : suivi par PID, journalisation
Ajoute une détection par PID (plus fiable que compter les lignes de ps), un réglage d'ulimit, et une trace via logger.
#!/bin/bash
#
# tomcat7 Démarre/arrête Tomcat
#
# chkconfig: 345 85 15
### BEGIN INIT INFO
# Provides: tomcat7
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Description: Release implementation for Servlet 2.5 and JSP 2.1
# Short-Description: start and stop tomcat
### END INIT INFO
. /etc/rc.d/init.d/functions
USER=tomcat
APP_NAME=tomcat
JAVA_HOME=/usr/bin/java
LOG_HOME=/var/log/$APP_NAME
PATH=$JAVA_HOME/bin:$PATH
TOMCAT_HOME=/opt/tomcat/$APP_NAME
SHUTDOWN_WAIT=20
RETVAL=0
umask 077
# JAVA_OPTS="-Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -Xms512m -Xmx512m"
tomcat_pid() {
ps aux | grep "$USER" | grep -v grep | awk '{ print $2 }'
}
start() {
pid=$(tomcat_pid)
if [ -n "$pid" ]; then
echo "Tomcat is already running (pid: $pid)"
return 0
fi
echo "Starting tomcat"
ulimit -n 100000
umask 007
logger -s "Start $APP_NAME"
su - "$USER" -c "$TOMCAT_HOME/bin/startup.sh"
return $RETVAL
}
stop() {
pid=$(tomcat_pid)
if [ -z "$pid" ]; then
echo "Tomcat is not running"
return 0
fi
echo "Stopping Tomcat"
logger -s "Stop $APP_NAME"
su - "$USER" -c "$TOMCAT_HOME/bin/shutdown.sh"
count=0
while ps -p "$pid" > /dev/null 2>&1 && [ "$count" -le "$SHUTDOWN_WAIT" ]; do
echo -n -e "\nwaiting for process $pid to exit"
sleep 1
count=$((count + 1))
done
if [ "$count" -gt "$SHUTDOWN_WAIT" ]; then
echo -n -e "\nkilling process $pid after ${SHUTDOWN_WAIT}s"
kill -9 "$pid"
fi
return $RETVAL
}
version() {
if [ -f "$TOMCAT_HOME/bin/version.sh" ]; then
logger -s "Display $APP_NAME Version"
su -l "$USER" -c "$TOMCAT_HOME/bin/version.sh"
return $RETVAL
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart|reload) stop; start ;;
status)
pid=$(tomcat_pid)
if [ -n "$pid" ]; then
echo "Tomcat is running with pid: $pid"
else
echo "Tomcat is not running"
fi
;;
version) version ;;
*)
echo "Usage: $0 {start|stop|restart|reload|status|version}"
exit 1
;;
esac
exit 0
Bug corrigé : dans le script d'origine, stop() contenait return $RETVAL avant la boucle d'attente d'arrêt (until ... done) — cette boucle et le kill -9 de secours qui la suit n'étaient donc jamais exécutés, code mort après un return prématuré. Le script « fonctionnait » quand même car shutdown.sh suffit en général, mais le filet de sécurité (kill forcé après timeout) ne se déclenchait jamais. Corrigé ici en déplaçant return $RETVAL à la fin de la fonction.
Version 3 : version distribution (paquet RPM tomcat)
Version la plus robuste, proche de celle fournie par les paquets RPM Tomcat historiques (auteurs d'origine cités dans les commentaires du script : Henri Gomez, Keith Irwin, Nicolas Mailhot, réécriture Deepak Bhole et Jason Corley) : bibliothèque LSB, fichier de configuration externe, PID file, gestion de SELinux via runuser, distinction fine des états (arrêté / en cours / fichier PID orphelin).
#!/bin/bash
#
# tomcat6 Démarre/arrête Tomcat
#
# chkconfig: - 80 20
### BEGIN INIT INFO
# Provides: tomcat6
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Description: Release implementation for Servlet 2.5 and JSP 2.1
# Short-Description: start and stop tomcat
### END INIT INFO
#
# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
# - heavily rewritten by Deepak Bhole and Jason Corley
if [ -r /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
else
exit 1
fi
DISTRIB_ID=$(lsb_release -i -s 2>/dev/null)
NAME="$(basename "$0")"
# Sous SELinux, utiliser 'runuser' plutôt que 'su'
if [ -x /sbin/runuser ]; then
SU="/sbin/runuser -s /bin/sh"
else
SU="/bin/su -s /bin/sh"
fi
TOMCAT_CFG="/etc/tomcat6/tomcat6.conf"
[ -r "$TOMCAT_CFG" ] && . "$TOMCAT_CFG"
[ -r "/etc/sysconfig/${NAME}" ] && . "/etc/sysconfig/${NAME}"
CONNECTOR_PORT="${CONNECTOR_PORT:-8080}"
TOMCAT_SCRIPT="/usr/sbin/tomcat6"
TOMCAT_PROG="${NAME}"
TOMCAT_USER="${TOMCAT_USER:-tomcat}"
TOMCAT_LOG="${TOMCAT_LOG:-/var/log/${NAME}-initd.log}"
export CATALINA_PID="${CATALINA_PID:-/var/run/${NAME}.pid}"
RETVAL="0"
start() {
echo -n "Starting ${TOMCAT_PROG}: "
if [ -f "${CATALINA_PID}" ]; then
read -r kpid < "${CATALINA_PID}"
if [ -d "/proc/${kpid}" ]; then
log_success_msg
return
fi
fi
touch "$CATALINA_PID" 2>&1 || RETVAL="4"
[ "$RETVAL" = "0" ] && chown "${TOMCAT_USER}:${TOMCAT_USER}" "$CATALINA_PID"
[ "$RETVAL" = "0" ] && $SU - "$TOMCAT_USER" -c "${TOMCAT_SCRIPT} start" >> "$TOMCAT_LOG" 2>&1 || RETVAL="4"
if [ "$RETVAL" = "0" ]; then
log_success_msg
touch "/var/lock/subsys/${NAME}"
else
log_failure_msg "Error code ${RETVAL}"
fi
}
stop() {
echo -n "Stopping ${TOMCAT_PROG}: "
if [ -f "/var/lock/subsys/${NAME}" ]; then
$SU - "$TOMCAT_USER" -c "${TOMCAT_SCRIPT} stop" >> "$TOMCAT_LOG" 2>&1 || RETVAL="4"
if [ "$RETVAL" = "0" ] && [ -f "${CATALINA_PID}" ]; then
read -r kpid < "${CATALINA_PID}"
count=0
while [ -d "/proc/${kpid}" ] && [ "$count" -le "$SHUTDOWN_WAIT" ]; do
sleep 1
count=$((count + 1))
done
[ "$count" -gt "$SHUTDOWN_WAIT" ] && kill -9 "$kpid"
log_success_msg
fi
rm -f "/var/lock/subsys/${NAME}" "$CATALINA_PID"
else
log_success_msg
fi
}
status() {
if [ -f "${CATALINA_PID}" ]; then
read -r kpid < "${CATALINA_PID}"
if [ -d "/proc/${kpid}" ]; then
log_success_msg "${NAME} (pid ${kpid}) is running..."
return
fi
fi
pid="$(pgrep -u "${TOMCAT_USER}" -f "${NAME}")"
if [ -z "$pid" ]; then
log_success_msg "${NAME} is stopped"
RETVAL="3"
else
log_success_msg "${NAME} (pid $pid) is running..."
fi
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; start ;;
condrestart|try-restart)
[ -f "/var/run/${NAME}.pid" ] && { stop; start; }
;;
status) status ;;
*)
echo "Usage: $0 {start|stop|restart|condrestart|try-restart|status}"
RETVAL="2"
;;
esac
exit "$RETVAL"
Cette version 3 est nettement plus longue à maintenir mais gère des cas que les deux précédentes ignorent : fichier PID orphelin (process disparu sans nettoyer son verrou), redémarrage sous SELinux, configuration externalisée par instance.
Quelle version choisir
- Aujourd'hui, sur un système avec systemd (RHEL7+/Debian9+), aucune de ces trois versions n'est le premier choix : une unit systemd dédiée est plus simple à écrire et à maintenir — voir Systemctl pour la syntaxe, et s'appuyer sur l'unit fournie par le paquet Tomcat de la distribution quand elle existe.
- Sur un système SysV encore en place, la version 2 offre un bon compromis (suivi par PID, sans la complexité de la version 3).
- La version 3 reste la référence si le script doit gérer plusieurs instances Tomcat sur la même machine ou tourner sous SELinux en mode enforcing.
Voir aussi
- Service generique3 — motif générique dont ce script est une application concrète
- Service complet — motif alternatif basé sur la bibliothèque système (
daemon/killproc) - Chkconfig — enregistrement/activation du service
- Systemctl — remplacement moderne (unit systemd)
- Java — environnement d'exécution requis par Tomcat