#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$(dirname "$0")/lib/ulib/ulib" || exit 1 urequire DEFAULTS xmlsupport function display_help() { uecho "$scriptname: Déployer une ou plusieurs webapps vers Tomcat USAGE $scriptname [options] ... OPTIONS -c, --config CONFIG Spécifier un fichier de configuration qui contient les informations spécifiées par les options ci-dessous: TOMCAT_PROFILE, CATALINA_BASE, TOMCAT_USER, TOMCAT_GROUP, TOMCAT_VERSION, MANAGER_URL, MANAGER_USER, MANAGER_PASSWORD, WAMAP, BACKUP, RESTART -C, --config-profile TOMCAT_PROFILE Spécifier le profil de configuration à utiliser. Cette valeur détermine la façon dont sont calculés CATALINA_BASE, TOMCAT_USER, TOMCAT_GROUP et TOMCAT_VERSION. Les valeurs valides sont: * debian:tomcatV Tomcat installé par 'apt-get install tomcatV'. L'alias 'd:V' est aussi supporté, e.g 'debian:tomcat7' ou 'd:8' * runs:NAME Tomcat installé par 'runs tomcat/V name=NAME'. Le suffixe NAME est le nom de base des fichiers de tomcat. Pour spécifier le cas échéant la version de Tomcat, il faut utiliser l'option -V ci-dessous. L'alias NAME sans le préfixe runs: est supporté aussi. Le profil par défaut est calculé comme suit: * Si un répertoire de la forme /var/lib/tomcatV existe alors il s'agit de debian:tomcatV. * Si le lien /opt/tomcat --> /opt/apache-tomcat-V existe, vérifier l'existence du script /etc/init.d/tomcatV. Si le script existe, alors utiliser runs:tomcatV comme profil. Sinon, utiliser runs:tomcat. * Sinon, aucun profil n'est sélectionné, et il faut spécifier manuellement les options -d, -U, -G, -V -d, --catalina-base CATALINA_BASE Spécifier le répertoire de base des configurations de Tomcat. La valeur par défaut est celle de CATALINA_HOME. Cette option n'a normalement pas besoin d'être spécifiée. -U, --tomcat-user TOMCAT_USER -G, --tomcat-group TOMCAT_GROUP Spécifier l'utilisateur et le groupe propriétaires des fichiers de Tomcat. Ces options n'ont normalement pas besoin d'être spécifiées. -V, --tomcat-version TOMCAT_VERSION Spécifier la version de tomcat installée, e.g 8.0.37 pour une version complète ou simplement 8 si on ne donne que la version majeure. Cette option peut s'avérer nécessaire avec le profil runs:tomcat bien que les meilleurs efforts soient faits pour détecter la valeur effective. -g, --manager-url MANAGER_URL Spécifier l'url du manager, e.g http://localhost:8080/manager/text Par défaut, le fichier server.xml est consulté pour connaitre sur quel port écoute le serveur. -u, --user MANAGER_USER -p, --password MANAGER_PASSWORD Spécifier le compte et le mot de passe à utiliser pour piloter le manager Tomcat, notamment pour redémarrer l'application venant d'être déployée. Ce compte doit avoir le rôle manager-script à partir de Tomcat 6.0.30, et le rôle manager-gui dans les version antérieurs. Par défaut, le fichier tomcat-users.xml est consulté pour avoir cette information. -m, --wamap WAMAPS Ajouter un ou plusieurs mappings de la forme src:dest. Avec ce mapping, la webapp src est déployée avec le nom dest. Plusieurs mappings peuvent être spécifiés en les séparant par des virgules. Si src est mentionné plusieurs fois, e.g src:dest1,src:dest2 alors la webapp src est déployée plusieurs fois avec des noms distincts. --protect PROTECTS --exclude EXCLUDES --replace-excludes EXCLUDES --rsync-option RSYNC_OPTIONS --replace-rsync-options RSYNC_OPTIONS XXX Options non documentées à implémenter -b, --backup --no-backup Avant le déploiement du service numérique, faire (resp. ne pas faire) une sauvegarde des fichiers actuellement déployés. -B, --backup-only Ne pas faire le déploiement. Faire uniquement la sauvegarde. -n, --no-restart Après le déploiement de la webapp, ne pas redémarrer l'application. -r, --restart-only Ne pas faire le déploiement. Redémarrer uniquement l'application. --fake Afficher simplement ce qui serait fait. Ne pas le faire réellement. --config-template Créer un modèle de configuration dans le répertoire des webapp spécifiées. Si aucune webapp n'est spécifiée, créer le fichier dans le répertoire courant." } VARS=( TOMCAT_PROFILE CATALINA_BASE TOMCAT_USER TOMCAT_GROUP TOMCAT_VERSION MANAGER_URL MANAGER_USER MANAGER_PASSWORD BACKUP RESTART ) ARRAYS=( WAMAPS PROTECTS EXCLUDES RSYNC_OPTIONS REPLACE_RSYNC_OPTIONS ) function __reset_vars() { local var for var in "${VARS[@]}"; do eval "$var=" done for var in "${ARRAYS[@]}"; do eval "$var=()" done } function __dump_vars() { local var for var in "${VARS[@]}"; do echo_setv2 "$var" done for var in "${ARRAYS[@]}"; do echo_seta2 "$var" done } function use_manager_script() { local v="$TOMCAT_VERSION" if [ -z "$v" ]; then return 0 elif [[ "$v" == 6.0.* ]]; then if [ "${v#6.0.}" -ge 30 ]; then return 0 else return 1 fi elif [ "${v%%.*}" -gt 6 ]; then return 0 else return 1 fi } function parse_server() { local -a lines local serverxml port serverxml="$CATALINA_BASE/conf/server.xml" array_from_lines lines "$(xpathtool -g "/Server/Service[@name='Catalina']/Connector/@port" "$serverxml")" port="${lines[0]}" if [ -n "$port" ]; then if use_manager_script; then MANAGER_URL="http://localhost:$port/manager/text" else MANAGER_URL="http://localhost:$port/manager/html" fi fi } function parse_tomcat_users() { local -a lines local usersxml role usersxml="$CATALINA_BASE/conf/tomcat-users.xml" if use_manager_script; then role=manager-script else role=manager-gui fi array_from_lines lines "$(xpathtool -g "/tomcat-users/user[contains(@roles,'$role')]/@username" "$usersxml")" MANAGER_USER="${lines[0]}" if [ -n "$MANAGER_USER" ]; then array_from_lines lines "$(xpathtool -g "/tomcat-users/user[@username='$MANAGER_USER']/@password" "$usersxml")" MANAGER_PASSWORD="${lines[0]}" fi } action=deploy parse_tomcat_users= parse_server= istmpdir= tmpdir= config= tomcat_profile= catalina_base= tomcat_user= tomcat_group= tomcat_version= manager_url= manager_user= manager_password= wamaps=() protects=() excludes=() rsync_options=(-rptL --delete --exclude /.git/) replace_rsync_options=() backup= restart= fake= args=( --help '$exit_with display_help' --private-parse-server '$action=parse; parse_server=1' --private-parse-tomcat-users '$action=parse; parse_tomcat_users=1' --is-tmpdir '$istmpdir=1; tmpdir=.' -c:,--config: config= -C:,--config-profile: tomcat_profile= -d:,--catalina-base:,--catalina-home: catalina_base= -U:,--tomcat-user: tomcat_user= -G:,--tomcat-group: tomcat_group= -V:,--tomcat-version: tomcat_version= -g:,--manager-url: manager_url= -u:,--user: manager_user= -p:,--password: manager_password= -m:,--wamap: wamaps -b,--backup backup=1 --no-backup backup=0 -B,--backup-only action=backup --restart restart=1 -n,--no-restart restart=0 -r,--restart-only action=restart --fake fake=1 --config-template action=config-template ) parse_args "$@"; set -- "${args[@]}" if [ "$action" == parse ]; then CATALINA_BASE="$1" TOMCAT_VERSION="$2" if [ -n "$parse_server" ]; then parse_server echo_setv2 MANAGER_URL fi if [ -n "$parse_tomcat_users" ]; then parse_tomcat_users echo_setv2 MANAGER_USER echo_setv2 MANAGER_PASSWORD fi exit 0 fi # Charger la configuration __reset_vars if [ -n "$config" ]; then eval "$( __reset_vars CATALINA_HOME= source "$config" 2>/dev/null || exit 1 [ -n "$CATALINA_BASE" ] || CATALINA_BASE="$CATALINA_HOME" __dump_vars )" fi # Traiter la ligne de commande for var in "${VARS[@]}"; do lvar="${var,,}" if [ -n "${!lvar}" ]; then setv "$var" "${!lvar}" fi done [ -n "$RESTART" ] || RESTART=1 # valeur par défaut normyesvals BACKUP RESTART for var in "${ARRAYS[@]}"; do lvar="${var,,}" if ! array_isempty "$lvar"; then array_copy "$var" "$lvar" fi done array_fix_paths WAMAPS , # Calculer le profil de connexion if [ -z "$TOMCAT_PROFILE" ]; then for v in 8 7; do if [ -d /var/lib/tomcat$v ]; then TOMCAT_PROFILE=debian:tomcat$v break fi done fi if [ -z "$TOMCAT_PROFILE" ]; then v= if [ -L /opt/tomcat ]; then setx v=readlink /opt/tomcat setx v=basename -- "$v" else array_lsdirs ts /opt "apache-tomcat-*" if [ ${#ts[*]} -gt 0 ]; then [ -n "$CATALINA_BASE" ] || CATALINA_BASE="${ts[0]}" v="$CATALINA_BASE" [ -L "$v" ] && setx v=readlink "$v" setx v=basename -- "$v" fi fi if [ -n "$v" ] && [[ "$v" == apache-tomcat-* ]]; then v=${v#apache-tomcat-} mv=${v%%.*} if [ -f /etc/init.d/tomcat$mv ]; then TOMCAT_PROFILE=runs:tomcat$mv else TOMCAT_PROFILE=runs:tomcat fi [ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v" fi fi if [ -n "$TOMCAT_PROFILE" ]; then case "$TOMCAT_PROFILE" in debian:*|runs:*) ;; d:*) TOMCAT_PROFILE="debian:tomcat${TOMCAT_PROFILE#d:}";; *) TOMCAT_PROFILE="runs:$TOMCAT_PROFILE";; esac fi # Calculer les valeurs dérivées du profil de connexion case "$TOMCAT_PROFILE" in debian:*) t="${TOMCAT_PROFILE#debian:}" v="${t#tomcat}" [ -z "$CATALINA_BASE" ] && CATALINA_BASE="/var/lib/$t" eval "$( setv "${t^^}_USER" setv "${t^^}_GROUP" source "/etc/default/$t" 2>/dev/null eval "echo tomcat_user=\"\$${t^^}_USER\"" eval "echo tomcat_group=\"\$${t^^}_GROUP\"" )" [ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user" [ -z "$TOMCAT_GROUP" ] && TOMCAT_GROUP="$tomcat_group" [ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v" ;; runs:*) v="${TOMCAT_PROFILE#runs:tomcat}" if [ -z "$CATALINA_BASE" -a "$v" != "$TOMCAT_PROFILE" ]; then array_lsdirs ts /opt "apache-tomcat-$v*" CATALINA_BASE="${ts[0]}" fi if [ -z "$CATALINA_BASE" ]; then if [ -L /opt/tomcat ]; then setx CATALINA_BASE=readlink /opt/tomcat else array_lsdirs ts /opt "apache-tomcat-*" CATALINA_BASE="${ts[0]}" fi fi name="${TOMCAT_PROFILE#runs:}" eval "$( TOMCAT_USER= source "/etc/default/$name" 2>/dev/null echo tomcat_user="$TOMCAT_USER" )" [ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user" if [ -z "$TOMCAT_VERSION" ]; then v="$CATALINA_BASE" [ -L "$v" ] && setx v=readlink "$v" setx v=basename -- "$v" if [[ "$v" == apache-tomcat-* ]]; then TOMCAT_VERSION="${v#apache-tomcat-}" fi fi ;; esac # Calculer les valeurs dérivées des fichiers de $CATALINA_BASE if [ -n "$CATALINA_BASE" -a -n "$TOMCAT_VERSION" ]; then if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then # lire les fichiers de configuratione et déterminer MANAGER_URL, # MANAGER_USER et MANAGER_PASSWORD if is_root; then [ -z "$MANAGER_URL" ] && parse_server [ -z "$MANAGER_USER" ] && parse_tomcat_users else args=() [ -z "$MANAGER_URL" ] && array_add args --private-parse-server [ -z "$MANAGER_USER" ] && array_add args --private-parse-tomcat-users array_add args "$CATALINA_BASE" "$TOMCAT_VERSION" eval "$(run_as root --noexec "${args[@]}")" fi fi fi # A partir de la liste des webapps et de WAMAPS, construire une liste de couples # waname:src pour la sauvegarde et/ou le déploiement [ -n "$fake" -o "$action" == config-template ] && require_webapps= || require_webapps=1 if [ $# -eq 0 -a -n "$require_webapps" ]; then [ -d WEB-INF ] && src=. || src= read_value "Veuillez entrer la webapp à déployer" src "$src" O set -- "$src" fi srcs=() [ -n "$istmpdir" ] || ac_set_tmpdir tmpdir for src in "$@"; do if [ -f "$src" ] && is_archive "$src"; then setx waname=get_archive_appname "$src" wadir="$tmpdir/$waname" mkdir "$wadir" if extract_archive "$src" "$wadir"; then array_add srcs "$wadir" else eerror "$src: erreur lors de l'extraction de l'archive" fi elif [ -d "$src" ]; then array_add srcs "$(abspath "$src")" elif [ -e "$src" ]; then eerror "$src: fichier invalide" else eerror "$src: fichier ou répertoire introuvable" fi done [ ${#srcs[*]} -gt 0 -o -z "$require_webapps" ] || die deploymaps=() for src in "${srcs[@]}"; do setx waname=basename -- "$src" found= for wamap in "${WAMAPS[@]}"; do splitpair "$wamap" from to if [ "$waname" == "$from" ]; then found=1 array_add deploymaps "$to:$src" fi done if [ -z "$found" ]; then array_add deploymaps "$waname:$src" fi done ################################################################################ # Maintenant, nous pouvons faire les actions if [ "$action" == config-template ]; then if [ ${#deploymaps[*]} -gt 0 ]; then toinstconfname=.toinst.conf else toinstconfname=toinst.conf deploymaps=(:.) fi for deploymap in "${deploymaps[@]}"; do splitpair "$deploymap" waname src toinstconf="$src/$toinstconfname" if [ -f "$toinstconf" ]; then estepi "$(ppath "$toinstconf"): configuration déjà existante" else estep "$(ppath "$toinstconf")" echo >"$toinstconf" "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # Fichiers à exclure de la source lors du déploiement #$(echo_seta2 EXCLUDES) # Fichiers à protéger dans la destination lors du déploiement #$(echo_seta2 PROTECTS)" fi done exit 0 fi ## Sauvegarde if [ -n "$BACKUP" -o "$action" == backup ]; then if [ -n "$fake" ]; then : else : fi fi ## Déploiement if [ "$action" == deploy ]; then [ -n "$CATALINA_BASE" -o -n "$fake" ] || die "Vous devez spécifier l'option --catalina-base" if [ -n "$fake" ]; then # Afficher ce qu'il faut faire etitle "Variables définies" __dump_vars etitle "Déploiements des webapps" for deploymap in "${deploymaps[@]}"; do splitpair "$deploymap" waname src setx srcname=basename -- "$src" dest="${CATALINA_BASE:-CATALINA_BASE}/webapps/$waname" etitle "$waname" evalx qvals rsync "${RSYNC_OPTIONS[@]}" "$src/" "$dest" // eecho evalx qvals chmod -R u=rwX,g=rX,o=rX "$dest" // eecho if [ -n "$TOMCAT_USER" ]; then evalx qvals chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" // eecho fi eend done eend elif ! is_root; then # le déploiement doit être fait en root args=( -C "$TOMCAT_PROFILE" -d "$CATALINA_BASE" -U "$TOMCAT_USER" -G "$TOMCAT_GROUP" -V "$TOMCAT_VERSION" -g "$MANAGER_URL" -u "$MANAGER_USER" -p "$MANAGER_PASSWORD" -m "$(array_join WAMAPS ,)" --no-backup --no-restart ) run_as root --noexec "${args[@]}" "${srcs[@]}" || die else # faire le déploiement etitle "Déploiements des webapps" for deploymap in "${deploymaps[@]}"; do splitpair "$deploymap" waname src setx srcname=basename -- "$src" dest="$CATALINA_BASE/webapps/$waname" etitle "$srcname" estepi "Déploiement vers $dest" estep "Copie des fichiers" if ! rsync "${RSYNC_OPTIONS[@]}" "$src/" "$dest"; then eerror "Une erreur s'est produite pendant la copie des fichiers" else error= estep "Correction des permissions et du propriétaire" chmod -R u=rwX,g=rX,o=rX "$dest" || error=1 if [ -n "$TOMCAT_USER" ]; then chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" || error=1 fi if [ -n "$error" ]; then eeror "Une erreur s'est produite pendant la mise à jour" fi fi eend done eend fi fi ## Redémarrage if [ -n "$RESTART" -o "$action" == restart ]; then etitle "Redémarrage des webapps" if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then ewarn "Impossible de recharger la webapp parce que l'url du manager et/ou le compte admin n'ont pas pu être déterminés." [ -z "$fake" ] && enote "\ Par défaut, les webapps ne sont rechargées automatiquement que si le fichier web.xml est modifié. Utilisez les options -g, -u, -p pour spécifier les informations manquantes nécessaires au pilotage du manager." elif [ -n "$fake" ]; then estepi "Utilisation du manager à l'adresse $MANAGER_URL" for deploymap in "${deploymaps[@]}"; do splitpair "$deploymap" waname src etitle "$waname" evalx qvals curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" // eecho eend done else estepi "Utilisation du manager à l'adresse $MANAGER_URL" for deploymap in "${deploymaps[@]}"; do splitpair "$deploymap" waname src ebegin "$waname" curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" >/dev/null eend $? done fi eend fi