1
0
Fork 0
scripts-admin-quickndirty-p.../oldies/script_multi-instance-tomcat.sh

453 lines
16 KiB
Bash
Executable file

#!/bin/sh
# Ce script sert à créer ou détruire une instance Tomcat
# en créant un CATALINA_BASE indépendant.
# L'usage habituel se fait sur une Debian 7 "Wheezy" avec
# tomcat, libapache2-mod-jk et apache2 installé.
# Prérequis :
# - Debian Wheezy (Squeeze non testée)
# - tomcat7 (6 non testée)
# - libapache2-mod-jk avec le workers.properties du module
# Trucs à nettoyer (si quelque chose part en vrille, ou simplement
# pour désinstaller ):
# - supprimer tout le répertoire REP_TOMCAT_MULTIINSTANCE
# - supprimer /etc/default/tomcatN_XXX
# - supprimer /etc/init.d/tomcatN_XXX
# - supprimer les utilisateurs tomcatN_YYYY
# - nettoyer les clusters PostgreSQL
# Version de Tomcat : 6 ou 7
# TODO : voir si on peut le passer en paramètre pour gérer
# Tomcat 6 & 7 sur la même machine
VERSION_TOMCAT="7"
# Quelques constantes internes
MAX_INSTANCES=999
START_RANGE_TOMCATUID=8000
START_RANGE_TOMCAT_PORT_SYS=15000
START_RANGE_TOMCAT_PORT_HTTP=18000
START_RANGE_TOMCAT_PORT_AJP=19000
# Initialisation des variables globales
MODE_CREATION=0
MODE_DESTRUCTION=0
TOMCAT_ENABLE_SHUTDOWN_PORT=""
OPTION_WORKERS_PROPERTIES=""
OPTION_VHOST_APACHE_SERVERNAME=""
NB_CHIFFRES_DANS_NUM_INSTANCE=$( printf "%d" "$MAX_INSTANCES" | wc -c )
REP_TOMCAT_MULTIINSTANCE="/var/lib/tomcat$VERSION_TOMCAT-multiinstances"
# On récupère également le nom de l'utilisateur et du groupe de Tomcat
if [ ! -f /etc/default/tomcat$VERSION_TOMCAT ]; then
echo "ERREUR: /etc/default/tomcat$VERSION_TOMCAT inaccessible." >&2
exit 1
fi
. /etc/default/tomcat$VERSION_TOMCAT
# Par défaut, on arrête le script à la première erreur non "catchée"
set -e
# Fonctions
# Arguments
# $1 : Version de Tomcat
# $2 : nom du worker
# $3 : port AJP du worker
ajout_worker_properties() {
test -n "$1" && test -n "$2" && test -n "$3" || exit 1
# On se fiche un peu de la version de Tomcat, en fait :)
case "$1" in
6|7)
cat <<EOF
# Script MI Tomcat : ajout du worker $2
worker.$2.port = $3
worker.$2.host = localhost
worker.$2.type = ajp13
EOF
;;
*)
echo "ERREUR: version de Tomcat non-gérée." >&2
exit 1
;;
esac
}
# Arguments
# $1 : Version de Tomcat
# $2 : port système (d'habitude 8005)
# $3 : port connecteur HTTP (8080, d'habitude)
# $4 : port connecteur AJP (8009, d'habitude)
generate_patch_tomcat_server_xml() {
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" && test -n "$5" || exit 1
case "$1" in
6|7)
generate_patch_tomcat_server_xml_6 "$2" "$3" "$4" "$5"
;;
*)
echo "ERREUR: version de Tomcat non-gérée." >&2
exit 1
;;
esac
}
# Arguments
# $1 : port système (d'habitude 8005)
# $2 : port connecteur HTTP (8080, d'habitude)
# $3 : port connecteur AJP (8009, d'habitude)
generate_patch_tomcat_server_xml_6() {
local NOM_WORKER TOMCAT_PORT_SYS TOMCAT_PORT_HTTP TOMCAT_PORT_AJP
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" || exit 1
NOM_WORKER="$1"
TOMCAT_PORT_SYS="$2"
TOMCAT_PORT_HTTP="$3"
TOMCAT_PORT_AJP="$4"
cat <<EOF
--- server.xml
+++ server.xml
@@ -19,7 +19,7 @@
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
-<Server port="8005" shutdown="SHUTDOWN">
+<Server port="$TOMCAT_PORT_SYS" shutdown="SHUTDOWN">
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
@@ -69,10 +69,12 @@
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL HTTP/1.1 Connector on port 8080
-->
- <Connector port="8080" protocol="HTTP/1.1"
+ <!--
+ <Connector port="$TOMCAT_PORT_HTTP" protocol="HTTP/1.1"
connectionTimeout="20000"
URIEncoding="UTF-8"
redirectPort="8443" />
+ -->
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
@@ -91,9 +93,7 @@
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
- <!--
- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
- -->
+ <Connector port="$TOMCAT_PORT_AJP" protocol="AJP/1.3" redirectPort="8443" address="127.0.0.1" />
<!-- An Engine represents the entry point (within Catalina) that processes
@@ -105,7 +105,7 @@
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
- <Engine name="Catalina" defaultHost="localhost">
+ <Engine name="Catalina" defaultHost="localhost" jvmRoute="$NOM_WORKER">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
EOF
}
# Petites fonctions pour éviter de faire des concatenations
# hasardeuses un peu partout
get_tomcat_user() {
case $VERSION_TOMCAT in
'6')
printf "%s" "$TOMCAT6_USER"
;;
'7')
printf "%s" "$TOMCAT7_USER"
;;
esac
}
get_tomcat_group() {
# TODO : une idée à creuser serait de créer un groupe tomcat incluant tomcat6 et tomcat7
case $VERSION_TOMCAT in
'6')
printf "%s" "$TOMCAT6_GROUP"
;;
'7')
printf "%s" "$TOMCAT7_GROUP"
;;
esac
}
# affiche le message d'aide
usage() {
cat <<EOF
$0 -c suffixe
$0 -d numero_instance
$0 -h
-c xxxx : création d'une instance avec le suffixe 'xxxx' (15 caract. max)
-d NNN : destruction de l'instance numéro NNN
-S : activation du port d'extinction de Tomcat
(déconseillé en production, ne gêne pas le gestionnaire de démon de Debian :
http://tomcat.apache.org/tomcat-7.0-doc/config/server.html#Common_Attributes
http://wiki.apache.org/tomcat/FAQ/Security#Q2 )
Ce script peut également modifier le fichier workers.properties
pour y ajouter les infos du worker créé.
-w /etc/.../workers.properties : Modification du workers.properties
-h : ce message d'aide
EOF
}
# Début du code
# gestion des options de lancement
while getopts c:d:Sw:h f; do
case $f in
'c')
MODE_CREATION=1
SUFFIX="$OPTARG"
OLD_LC_ALL="$LC_ALL"
export LC_ALL=C
export LANG=C
if [ $( printf "$SUFFIX" | egrep -c "^[a-z][a-z0-9_]{0,14}$" ) -ne 1 ]; then
echo "ERREUR: suffixe vide ou contenant des caractères interdits : regexp : [a-z][a-z0-9_]{0,14}" >&2
exit 1
fi
export LC_ALL="$OLD_LC_ALL"
export LANG="$OLD_LC_ALL"
;;
'd')
MODE_DESTRUCTION=1
NUM_INSTANCE=$( printf "%d" "$OPTARG" )
;;
'h')
usage
exit 0
;;
'S')
TOMCAT_ENABLE_SHUTDOWN_PORT="1"
;;
'w')
OPTION_WORKERS_PROPERTIES="$OPTARG"
if [ ! -f "$OPTION_WORKERS_PROPERTIES" ]; then
echo "ERREUR: fichier workers.properties inexistant : $OPTION_WORKERS_PROPERTIES" >&2
exit 1
fi
;;
\?)
usage >&2
exit 1
;;
esac
done
#(code inutile pour ce script, mais que je garde parce qu'on ne sait jamais)
#shift $( expr $OPTIND - 1 )
#DATA="$1"
# Petite vérif.
case $(( $MODE_CREATION + $MODE_DESTRUCTION )) in
'0')
echo "ERREUR: veuillez choisir entre création et destruction." >&2
usage >&2
exit 1
;;
'2')
echo "ERREUR: tu veux créer et détruire en même temps, petit malin ?" >&2
exit 1
;;
esac
# - est-ce qu'on est bien sur une Debian 6 ou 7
# (c'est surtout pour éviter les mauvaises surprises, ce script n'ayant pas été testé ailleurs)
if [ ! -f "/etc/debian_version" ] || [ $( egrep -c "^(6.|7.)" /etc/debian_version ) -ne 1 ]; then
echo "ERREUR: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
exit 1
fi
# - est-ce que Tomcat est bien installé ?
if ! dpkg -l tomcat$VERSION_TOMCAT >/dev/null 2>&1; then
echo "ERREUR: tomcat$VERSION_TOMCAT ne semble pas avoir été installé." >&2
exit 1
fi
# - on vérifie que le /etc/default/tomcatN contient bien les infos qui nous intéresse
if [ ! -n $( get_tomcat_user ) ] || [ ! -n $( get_tomcat_group) ]; then
echo "ERREUR: TOMCAT_USER ou TOMCAT_GROUP indeterminé." >&2
exit 1
fi
# Fin des vérifications
if [ "$MODE_CREATION" -eq 1 ]; then
# Détermination du numéro d'instance :
# On cherche un numéro inutilisé ni par une instance Tomcat, ni par une instance Postgres
for NUM_INSTANCE in $( seq 1 $MAX_INSTANCES ); do
# Finalement, on base tout sur le nom de l'instance : ça
# nous permet de retrouver facilement le répertoire de l'instance
# lors de la suppression (le HOME de tomcat7 est sur CATALINA_HOME,
# pas sur CATALINA_BASE :'(
NOM_INSTANCE=$( printf "%s_%0$NB_CHIFFRES_DANS_NUM_INSTANCE""d_%s" "$( get_tomcat_user )" "$NUM_INSTANCE" "$SUFFIX" )
USERID_TOMCAT=$(( $START_RANGE_TOMCATUID + $NUM_INSTANCE ))
USERNAME_TOMCAT="$NOM_INSTANCE"
SCRIPTNAME_TOMCAT="$NOM_INSTANCE"
WORKERNAME_TOMCAT="worker_$NOM_INSTANCE"
if [ ! -d "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE" ] && ! getent passwd "$USERID_TOMCAT" >/dev/null 2>&1 && ! getent passwd "$USERNAME_TOMCAT" >/dev/null 2>&1; then
echo "INFO: Numéro d'instance libre trouvé : $NUM_INSTANCE"
break
fi
done
if [ "$NUM_INSTANCE" -eq "$MAX_INSTANCES" ]; then
echo "ERREUR: plus de numéro d'instance disponible." >&2
exit 1
fi
# Vérifier que le REP_TOMCAT_MULTIINSTANCE pré-existe.
# TODO review : finalement pas une bonne idée de le faire créer par le script ?
if [ ! -d "$REP_TOMCAT_MULTIINSTANCE" ]; then
# (finalement, on le crée nous même...)
echo "WARNING: le répertoire '$REP_TOMCAT_MULTIINSTANCE' n'existe pas (normal si première exécution). Création..."
mkdir -p "$REP_TOMCAT_MULTIINSTANCE"
chown -R "root:$( get_tomcat_group )" "$REP_TOMCAT_MULTIINSTANCE"
chmod 750 "$REP_TOMCAT_MULTIINSTANCE"
fi
# Copie du script d'init et du /etc/default de Tomcat
# Note : pour les scripts d'init, j'aurais aimé faire de simples liens symboliques vers
# un script générique. Malheureusement, ça pose de gros soucis pour LSB (insserv
# semble avoir les liens symboliques en horreur) et on aurait dû tout faire à la
# main, d'où plus d'inconvénients que d'avantages.
echo "INFO: création de l'utilisateur système dédié..."
useradd -u "$USERID_TOMCAT" -s /bin/false -g $( get_tomcat_group ) -d $( getent passwd $( get_tomcat_user ) | cut -d : -f 6 ) "$USERNAME_TOMCAT"
echo "INFO: création du script de lancement..."
cat /etc/init.d/tomcat$VERSION_TOMCAT | \
sed "s/^\(#[[:space:]]*Provides[[:space:]]*:[[:space:]]*\)tomcat[0-9]\+[[:space:]]*$/\1$SCRIPTNAME_TOMCAT/" | \
sed 's/^NAME=tomcat[0-9]\+$/NAME=$( basename "$0" | sed "s\/^[SK][0-9]\+\/\/" )/' \
>/etc/init.d/$SCRIPTNAME_TOMCAT
chmod +x /etc/init.d/$SCRIPTNAME_TOMCAT
echo "INFO: création du fichier de paramétrage dans /etc/default..."
cat /etc/default/tomcat$VERSION_TOMCAT | sed "s/^\(TOMCAT[0-9]\+_USER\)=tomcat[0-9]\+$/\1=$USERNAME_TOMCAT/" >/etc/default/$SCRIPTNAME_TOMCAT
echo "# Script MI Tomcat : Spécification des CATALINA_HOME et CATALINA_BASE" >>/etc/default/$SCRIPTNAME_TOMCAT
echo "CATALINA_HOME=/usr/share/tomcat$VERSION_TOMCAT" >>/etc/default/$SCRIPTNAME_TOMCAT
echo "CATALINA_BASE=$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE" >>/etc/default/$SCRIPTNAME_TOMCAT
# Activation du script d'init
echo "INFO: activation du script d'init..."
update-rc.d $SCRIPTNAME_TOMCAT defaults
# Instanciation du CATALINA_BASE
# Copie du /var/lib/tomcatN (notre template, en gros)
echo "INFO: génération du CATALINA_BASE ( $REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE )..."
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
cp -a /var/lib/tomcat$VERSION_TOMCAT/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/"
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf"
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs"
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work"
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf"
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs"
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work"
cp -r /var/lib/tomcat$VERSION_TOMCAT/conf/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf/"
# Parfois, le work est vide. Solution temporaire : on émet un warning
if [ "$( ls /var/lib/tomcat$VERSION_TOMCAT/work/* 2>/dev/null | wc -l )" -gt 0 ]; then
cp -r /var/lib/tomcat$VERSION_TOMCAT/work/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work/"
else
echo "INFO: le répertoire /work/ du template est vide. A priori, c'est normal."
fi
chown -R $USERNAME_TOMCAT:$( get_tomcat_group ) "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
# Réglage des ports TCP/IP
generate_patch_tomcat_server_xml "$VERSION_TOMCAT" \
"$WORKERNAME_TOMCAT" \
$( test -n "$TOMCAT_ENABLE_SHUTDOWN_PORT" && echo $(( $START_RANGE_TOMCAT_PORT_SYS + $NUM_INSTANCE )) || echo "-1" ) \
$(( $START_RANGE_TOMCAT_PORT_HTTP + $NUM_INSTANCE )) \
$(( $START_RANGE_TOMCAT_PORT_AJP + $NUM_INSTANCE )) | \
patch $REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf/server.xml
# Génération du fichier de config de logrotate
echo "INFO: génération du logrotate..."
cat /etc/logrotate.d/tomcat$VERSION_TOMCAT | \
sed "s#^/var/log/tomcat[0-9]\+/catalina.out #$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs/catalina.out #" | \
sed "s/create 640 tomcat[0-9]\+ adm/create 640 $USERNAME_TOMCAT adm/" \
>/etc/logrotate.d/$SCRIPTNAME_TOMCAT
# partie annexe n°1 : workers.properties
if [ -f "$OPTION_WORKERS_PROPERTIES" ]; then
echo "INFO: Modification du workers.properties..."
# Ajout du worker à la worker.list
TMP_SUFFIX=$( date +%Y%m%d-%H%M%S )
sed -i.$TMP_SUFFIX -e "s/^worker.list=\(.\+\)$/worker.list=\1,$WORKERNAME_TOMCAT/g" -e "s/^worker.list=$/worker.list=$WORKERNAME_TOMCAT/g" "$OPTION_WORKERS_PROPERTIES"
echo "NOTICE: une sauvegarde $OPTION_WORKERS_PROPERTIES.$TMP_SUFFIX a été créée, n'hésitez pas à la supprimer."
# Ajouts de la définition du worker
ajout_worker_properties "$VERSION_TOMCAT" "$WORKERNAME_TOMCAT" $(( $START_RANGE_TOMCAT_PORT_AJP + $NUM_INSTANCE )) >> "$OPTION_WORKERS_PROPERTIES"
fi
# Fin
echo "INFO: Création terminée. Serveur Tomcat éteint."
echo "INFO: Pour connecter mod-jk au worker, voici la ligne à ajouter au vhost : JkMount /* $WORKERNAME_TOMCAT"
echo "INFO: Pour allumer l'instance Tomcat : service $SCRIPTNAME_TOMCAT start"
fi
if [ "$MODE_DESTRUCTION" -eq 1 ]; then
USERID_TOMCAT=$(( $START_RANGE_TOMCATUID + $NUM_INSTANCE ))
#echo "NOTICE: le script est en mode -e. Il s'arrête donc à la première erreur. Le cas échéant, il faudra terminer le nettoyage à la main."
# On recherche le nom de l'instance
USERNAME_TOMCAT=$( getent passwd $USERID_TOMCAT | cut -d : -f 1 )
NOM_INSTANCE="$USERNAME_TOMCAT"
SCRIPTNAME_TOMCAT="$NOM_INSTANCE"
WORKERNAME_TOMCAT="worker_$NOM_INSTANCE"
if [ ! -n "$USERNAME_TOMCAT" ]; then
echo "ERREUR: l'utilisateur correspondant à l'uid $USERID_TOMCAT est introuvable." >&2
exit 1
fi
if service "$SCRIPTNAME_TOMCAT" status >/dev/null 2>&1; then
echo "ERREUR: l'instance tomcat tourne toujours. Ne pas oublier le service $SCRIPTNAME_TOMCAT stop" >&2
exit 1
fi
# Suppression utilisateur et répertoire dédié
echo "INFO: suppression de l'utilisateur..."
userdel $USERNAME_TOMCAT
echo "INFO: suppression du répertoire dédié..."
rm -rf "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
echo "INFO: suppresion fichier default..."
rm -f "/etc/default/$SCRIPTNAME_TOMCAT"
# Suppression du script d'init
echo "INFO: désactivation et suppression du script d'init..."
rm -f /etc/init.d/$SCRIPTNAME_TOMCAT
update-rc.d "$SCRIPTNAME_TOMCAT" remove
# Suppression logrotate
echo "INFO: suppression logrotate..."
rm -f /etc/logrotate.d/$SCRIPTNAME_TOMCAT
# partie annexe n°1 : workers.properties
if [ -f "$OPTION_WORKERS_PROPERTIES" ]; then
echo "INFO: Modification du workers.properties..."
# Soustraction de la définition du worker
TMP_SUFFIX=$( date +%Y%m%d-%H%M%S )
sed -i.$TMP_SUFFIX -e "/^worker.list=/s/$WORKERNAME_TOMCAT[,]\?//g" \
-e '/^worker.list=.*,$/s/,$//' \
-e "/^# Script MI Tomcat : ajout du worker $WORKERNAME_TOMCAT$/d" \
-e "/^worker.$WORKERNAME_TOMCAT/d" \
"$OPTION_WORKERS_PROPERTIES"
echo "NOTICE: une sauvegarde $OPTION_WORKERS_PROPERTIES.$TMP_SUFFIX a été créée, n'hésitez pas à la supprimer."
fi
# Fin
echo "INFO: suppression terminée."
fi