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 `.gz` unique 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`).
```bash
- !/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 | ( $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.lock` pour éviter les exécutions simultanées.
- Test à blanc possible avec `DRY_RUN=1`.
- Purge automatique après `RETENTION_MONTHS` mois.
- 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` |