Il y a 389 articles et 19 utilisateurs inscrits (ce bandeau est défini dans MediaWiki:Sitenotice)
Rotation des logs tomcat et Pleade
🧩 Archivage mensuel et nettoyage automatique des logs Tomcat / Java
🎯 Objectif
Ce document présente un script Bash permettant :
- D’archiver automatiquement les fichiers journaliers et mensuels produits par des applications Java/Tomcat ;
- De créer une archive compressée
.gzunique par mois et par type de log ; - De supprimer les fichiers quotidiens une fois archivés correctement ;
- De purger les archives plus anciennes qu’une période définie ;
- De gérer plusieurs formats de nommage de fichiers :
manager.2025-11-07.log(format point)
sdx-20251107.log(format tiret)
pleade-stats-202511.log(format tiret mensuel).
Paramètres à modifier selon l’installation
#---------- PARAMÈTRES À ADAPTER ---------- DIRS=( "/home/ajlsm/tomcats/preprod/logs" "/home/ajlsm/tomcats/slecture/logs" "/home/ajlsm/tomcats/internet-consultation/logs" "/home/ajlsm/tomcats/internet-consultation/webapps/pleade/WEB-INF/logs" "/home/ajlsm/tomcats/slecture/webapps/pleade/WEB-INF/logs" "/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs" ) RETENTION_MONTHS=6 BATCH_SIZE=0 # 0 = désactivé ; 20 = regrouper dès qu'il y a 20 fichiers DRY_RUN=0 # 1 = ne rien écrire/supprimer, juste logguer NORMALIZE_SUFFIX=1 # 1 = corriger *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage ARCHIVE_CURRENT_MONTH=0 # 1 = inclure le mois courant (ré-agrège au fil du mois) # Familles par style + extensions declare -A FAMILIES_DOT FAMILIES_DOT["manager"]="log" FAMILIES_DOT["localhost_access_log"]="txt" FAMILIES_DOT["catalina"]="log" FAMILIES_DOT["localhost"]="log" FAMILIES_DOT["host-manager"]="log" declare -A FAMILIES_HYPH FAMILIES_HYPH["auto-publication"]="log" FAMILIES_HYPH["cocoon"]="log" FAMILIES_HYPH["oai"]="log" FAMILIES_HYPH["publication"]="log" FAMILIES_HYPH["sdx"]="log" declare -A FAMILIES_HMTH FAMILIES_HMTH["pleade-stats"]="log"
⚙️ 1. Script d’archivage (archive-logs.sh)
Créer le fichier :
/usr/local/sbin/archive-logs.sh
et lui donner les droits d’exécution (chmod +x /usr/local/sbin/archive-logs.sh).
#!/usr/bin/env bash
# archive-logs.sh — regroupe les logs existants en archives mensuelles uniques (.gz)
# - Supporte trois styles de naming :
# 1) DOT : base.YYYY-MM-DD.ext (ex: manager.2025-11-07.log)
# 2) HYPH : base-YYYYMMDD.ext (ex: sdx-20251107.log)
# 3) HMTH : base-YYYYMM.ext (ex: pleade-stats-202511.log)
# - Ne modifie pas les fichiers lors de la lecture ; supprime uniquement si l’archive est OK
# - Purge les archives plus vieilles que RETENTION_MONTHS
# - (Optionnel) Normalise *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage
set -euo pipefail
IFS=$'\n\t'
umask 022
# ---------- PARAMÈTRES À ADAPTER ----------
DIRS=(
"/home/ajlsm/tomcats/preprod/logs"
"/home/ajlsm/tomcats/slecture/logs"
"/home/ajlsm/tomcats/internet-consultation/logs"
"/home/ajlsm/tomcats/internet-consultation/webapps/pleade/WEB-INF/logs"
"/home/ajlsm/tomcats/slecture/webapps/pleade/WEB-INF/logs"
"/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs"
)
RETENTION_MONTHS=6
BATCH_SIZE=0 # 0 = désactivé ; 20 = regrouper dès qu'il y a 20 fichiers
DRY_RUN=0 # 1 = ne rien écrire/supprimer, juste logguer
NORMALIZE_SUFFIX=1 # 1 = corriger *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage
ARCHIVE_CURRENT_MONTH=0 # 1 = inclure le mois courant (ré-agrège au fil du mois)
# Familles par style + extensions
declare -A FAMILIES_DOT
FAMILIES_DOT["manager"]="log"
FAMILIES_DOT["localhost_access_log"]="txt"
FAMILIES_DOT["catalina"]="log"
FAMILIES_DOT["localhost"]="log"
FAMILIES_DOT["host-manager"]="log"
declare -A FAMILIES_HYPH
FAMILIES_HYPH["auto-publication"]="log"
FAMILIES_HYPH["cocoon"]="log"
FAMILIES_HYPH["oai"]="log"
FAMILIES_HYPH["publication"]="log"
FAMILIES_HYPH["sdx"]="log"
declare -A FAMILIES_HMTH
FAMILIES_HMTH["pleade-stats"]="log"
# -------------------------------------------
log() { printf "[%s] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
current_month() { date +%Y-%m; }
month_from_dot_name() { sed -nE 's/.*([0-9]{4})-([0-9]{2})-[0-9]{2}\.[^.]+$/\1-\2/p'; }
month_from_hyph_name() { awk 'match($0, /-[0-9]{8}\.[^.]+$/){y=substr($0,RSTART+1,4);m=substr($0,RSTART+5,2);print y"-"m}'; }
month_from_hmth_name() { awk 'match($0, /-[0-9]{6}\.[^.]+$/){y=substr($0,RSTART+1,4);m=substr($0,RSTART+5,2);print y"-"m}'; }
do_mv() { (( DRY_RUN )) && log "[DRY] mv '$1' '$2'" || mv -- "$1" "$2"; }
do_rm() { (( DRY_RUN )) && log "[DRY] rm -f $*" || rm -f -- "$@"; }
do_gzip_f() { (( DRY_RUN )) && log "[DRY] gzip -f '$1'" || gzip -f "$1"; }
normalize_suffixes() {
for d in "${DIRS[@]}"; do
[[ -d "$d" ]] || continue
shopt -s nullglob
for f in "$d"/*.txt-????????; do
[[ "$f" =~ ^(.*\.txt)-[0-9]{8}$ ]] || continue
new="${BASH_REMATCH[1]}"
[[ -e "$new" ]] && { log "Skip (existe déjà) : $new"; continue; }
do_mv "$f" "$new" && log "$f → $new"
done
for f in "$d"/*.log-????????; do
[[ "$f" =~ ^(.*\.log)-[0-9]{8}$ ]] || continue
new="${BASH_REMATCH[1]}"
[[ -e "$new" ]] && { log "Skip (existe déjà) : $new"; continue; }
do_mv "$f" "$new" && log "$f → $new"
done
shopt -u nullglob
done
}
build_outname() {
local style="$1" dir="$2" base="$3" month="$4" ext="$5"
if [[ "$style" == "hyph" ]]; then
printf "%s/%s-%s.%s.gz" "$dir" "$base" "$month" "$ext"
else
printf "%s/%s.%s.%s.gz" "$dir" "$base" "$month" "$ext"
fi
}
make_monthly_archive() {
local style="$1"; shift
local dir="$1"; shift
local base="$1"; shift
local ext="$1"; shift
local -a list=( "$@" )
[[ ${#list[@]} -eq 0 ]] && return 0
local month out tmp
case "$style" in
dot) month="$(basename -- "${list[0]}" | month_from_dot_name)";;
hyph) month="$(basename -- "${list[0]}" | month_from_hyph_name)";;
hmth) month="$(basename -- "${list[0]}" | month_from_hmth_name)";;
esac
[[ -z "$month" ]] && { log "⚠️ Impossible d’extraire le mois pour ${list[0]}"; return 0; }
out="$(build_outname "$style" "$dir" "$base" "$month" "$ext")"
tmp="${out}.tmp"
if [[ -s "$out" ]]; then
log "Archive déjà présente: $out"
return 0
fi
log "Création archive mensuelle: $out"
: > "$tmp"
for f in "${list[@]}"; do
(( DRY_RUN )) && log "[DRY] cat '$f' >> '$tmp'" || cat -- "$f" >> "$tmp"
done
(( DRY_RUN )) && log "[DRY] gzip -f '$tmp' && mv '${tmp}.gz' '$out'" || { do_gzip_f "$tmp"; do_mv "${tmp}.gz" "$out"; }
if [[ -s "$out" || ( $DRY_RUN -eq 1 ) ]]; then
log "Archive OK ⇒ suppression des fichiers (${#list[@]})"
do_rm "${list[@]}"
else
log "⚠️ Échec création archive: $out (aucune suppression faite)"
fi
}
process_style() {
local style="$1"; shift
declare -n families="$1"
local nowm; nowm="$(current_month)"
for d in "${DIRS[@]}"; do
[[ -d "$d" ]] || continue
for base in "${!families[@]}"; do
read -r -a exts <<< "${families[$base]}"
for ext in "${exts[@]}"; do
shopt -s nullglob
local -a files=()
case "$style" in
dot) files=( "$d"/${base}.[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9].${ext} );;
hyph) files=( "$d"/${base}-[0-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9].${ext} );;
hmth) files=( "$d"/${base}-[0-9][0-9][0-9][0-9][0-1][0-9].${ext} );;
esac
shopt -u nullglob
[[ ${#files[@]} -eq 0 ]] && continue
declare -A months=()
local f m
for f in "${files[@]}"; do
case "$style" in
dot) m="$(basename -- "$f" | month_from_dot_name)";;
hyph) m="$(basename -- "$f" | month_from_hyph_name)";;
hmth) m="$(basename -- "$f" | month_from_hmth_name)";;
esac
[[ -z "$m" ]] && continue
if (( ! ARCHIVE_CURRENT_MONTH )) && [[ "$m" == "$nowm" ]]; then
continue
fi
months["$m"]=1
done
[[ ${#months[@]} -eq 0 ]] && continue
for m in "${!months[@]}"; do
local -a month_files=()
y="${m%%-*}"; mm="${m##*-}"
while IFS= read -r line; do month_files+=( "$line" ); done < <(
printf "%s\n" "${files[@]}" |
grep -E "/${base}[-\.](${y}${mm}|${m})" |
LC_ALL=C sort
)
[[ ${#month_files[@]} -eq 0 ]] && continue
make_monthly_archive "$style" "$d" "$base" "$ext" "${month_files[@]}"
done
done
done
done
}
purge_old_archives() {
local days=$(( RETENTION_MONTHS * 31 ))
for d in "${DIRS[@]}"; do
[[ -d "$d" ]] || continue
find "$d" -maxdepth 1 -type f \
\( -regex '.*/[^/]+\.[0-9]{4}-[0-9]{2}\.(log|txt)\.gz' \
-o -regex '.*/[^/]+-[0-9]{4}-[0-9]{2}\.(log|txt)\.gz' \) \
-mtime +$days -print -delete
done
}
LOCK="/var/lock/archive-logs.lock"
mkdir -p /var/lock
exec 9>"$LOCK" || exit 1
flock -n 9 || { echo "Déjà en cours, abandon."; exit 0; }
trap 'flock -u 9' EXIT
log "=== Début archivage logs ==="
if (( NORMALIZE_SUFFIX )); then
log "Normalisation des suffixes *.txt-YYYYMMDD / *.log-YYYYMMDD"
normalize_suffixes
fi
process_style dot FAMILIES_DOT
process_style hyph FAMILIES_HYPH
process_style hmth FAMILIES_HMTH
purge_old_archives
log "=== Fin archivage logs ==="
🕐 2. Cron automatique
➤ Exécution mensuelle (chaque 1er du mois à 06:10)
10 6 1 * * /usr/local/sbin/archive-logs.sh >> /var/log/archive-logs.log 2>&1
➤ Option quotidienne (si BATCH_SIZE > 0))
5 6 * * * /usr/local/sbin/archive-logs.sh >> /var/log/archive-logs.log 2>&1
🧹 3. Renommage automatique
Si certains fichiers sont mal nommés (suffixes dupliqués comme .txt-YYYYMMDD ou .log-YYYYMMDD), le script les corrige automatiquement grâce à NORMALIZE_SUFFIX=1.
Tu peux aussi lancer cette normalisation seule :
bash /usr/local/sbin/archive-logs.sh
✅ 4. Résumé des familles gérées
| Style | Familles | Exemple fichier | Archive produite |
|---|---|---|---|
| DOT | manager, localhost_access_log, catalina, localhost, host-manager
|
manager.2025-11-07.log
|
manager.2025-11.log.gz
|
| HYPH | auto-publication, cocoon, oai, publication, sdx
|
sdx-20251107.log
|
sdx-2025-11.log.gz
|
| HMTH | pleade-stats
|
pleade-stats-202511.log
|
pleade-stats-2025-11.log.gz
|
🔒 5. Sécurité & cohérence
- Verrou via
/var/lock/archive-logs.lockpour éviter les exécutions simultanées. - Test à blanc possible avec
DRY_RUN=1. - Purge automatique après
RETENTION_MONTHSmois. - Aucune altération des fichiers pendant la lecture : suppression uniquement après création réussie de l’archive.
🧭 Exemple avant/après
Avant
sdx-20251101.log sdx-20251102.log sdx-20251103.log ... pleade-stats-202510.log
Après exécution
sdx-2025-11.log.gz pleade-stats-2025-10.log.gz
📦 Résumé technique
| Élément | Valeur |
|---|---|
| Fichier script | /usr/local/sbin/archive-logs.sh
|
| Logs d’exécution | /var/log/archive-logs.log
|
| Cron mensuel | 10 6 1 * *
|
| Rétention | 6 mois (RETENTION_MONTHS=6)
|
| Mode test | DRY_RUN=1
|
| Verrouillage | /var/lock/archive-logs.lock
|