Il y a 389 articles et 19 utilisateurs inscrits (ce bandeau est défini dans MediaWiki:Sitenotice)
« Rotation des logs tomcat et Pleade » : différence entre les versions
| (8 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 5 : | Ligne 5 : | ||
|- | |- | ||
! Clients | ! Clients | ||
! | ! Mise en place de la rotation de logs | ||
|- | |- | ||
| ad53 | | ad53 | ||
| Ligne 20 : | Ligne 20 : | ||
|- | |- | ||
| Pandor | | Pandor | ||
|✅ | |||
|- | |||
| ens-lyon | |||
|✅ | |||
|- | |||
| cnd | |||
|✅ | |||
|- | |||
| ad64 | |||
| | |||
|- | |||
| bm-dijon | |||
| | |||
|- | |||
| am-angers | |||
| | | | ||
|- | |- | ||
| | | Drac-Alsace | ||
| | | | ||
|- | |||
| Mercure:/home/ajlsm/recette/... | |||
|✅ | |||
|} | |} | ||
| Ligne 101 : | Ligne 119 : | ||
<syntaxhighlight lang="bash">#!/usr/bin/env bash | <syntaxhighlight lang="bash">#!/usr/bin/env bash | ||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" | |||
export PATH | |||
# archive-logs.sh — regroupe les logs existants en archives mensuelles uniques (.gz) | # archive-logs.sh — regroupe les logs existants en archives mensuelles uniques (.gz) | ||
# - Supporte trois styles de naming : | # - Supporte trois styles de naming : | ||
| Ligne 109 : | Ligne 129 : | ||
# - Purge les archives plus vieilles que RETENTION_MONTHS | # - Purge les archives plus vieilles que RETENTION_MONTHS | ||
# - (Optionnel) Normalise *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage | # - (Optionnel) Normalise *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage | ||
# | |||
# Installer le script ici : /usr/local/sbin/archive-logs.sh | |||
# Lancer avec crontab -e, par exe : | |||
# Rotation des logs des 3 tomcats tous les 1er de chaque mois. | |||
# 10 6 1 * * /usr/local/sbin/archive-logs.sh >> /home/ajlsm/rotation-logs-pleade/archive-logs-$(date +\%Y-\%m-\%d).log 2>&1 | |||
set -euo pipefail | set -euo pipefail | ||
| Ligne 117 : | Ligne 142 : | ||
DIRS=( | DIRS=( | ||
"/home/ajlsm/tomcats/preprod/logs" | "/home/ajlsm/tomcats/preprod/logs" | ||
"/home/ajlsm/tomcats/slecture/logs" | |||
"/home/ajlsm/tomcats/internet/logs" | "/home/ajlsm/tomcats/internet/logs" | ||
"/home/ajlsm/tomcats/internet/webapps/pleade/WEB-INF/logs" | "/home/ajlsm/tomcats/internet/webapps/pleade/WEB-INF/logs" | ||
"/home/ajlsm/tomcats/slecture/webapps/pleade/WEB-INF/logs" | |||
"/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs" | "/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs" | ||
) | ) | ||
| Ligne 440 : | Ligne 465 : | ||
# ----- Verrou ----- | # ----- Verrou ----- | ||
LOCK_DIR="/home/ajlsm/.lock" | |||
mkdir -p | LOCK="$LOCK_DIR/archive-logs.lock" | ||
exec 9>"$LOCK" | mkdir -p "$LOCK_DIR" | ||
exec 9>"$LOCK" | |||
flock -n 9 || { echo "Déjà en cours, abandon."; exit 0; } | flock -n 9 || { echo "Déjà en cours, abandon."; exit 0; } | ||
trap 'flock -u 9' EXIT | trap 'flock -u 9' EXIT | ||
log "=== Début archivage logs ===" | log "=== Début archivage logs ===" | ||
if (( NORMALIZE_SUFFIX )); then | if (( NORMALIZE_SUFFIX )); then | ||
| Ligne 455 : | Ligne 480 : | ||
process_style hmth FAMILIES_HMTH | process_style hmth FAMILIES_HMTH | ||
purge_old_archives | purge_old_archives | ||
log "=== Fin archivage logs ==="</syntaxhighlight> | log "=== Fin archivage logs ===" | ||
</syntaxhighlight> | |||
<span id="cron-automatique"></span> | <span id="cron-automatique"></span> | ||
== 🕐 2. Cron automatique == | == 🕐 2. Cron automatique == | ||
Dernière version du 15 décembre 2025 à 08:51
🏁 Scripts installés dans les VM clients suivants
[modifier | modifier le wikicode]| Clients | Mise en place de la rotation de logs |
|---|---|
| ad53 | ✅ |
| Collège de France | ✅ |
| ad44 | ✅ |
| apbp | ✅ |
| Pandor | ✅ |
| ens-lyon | ✅ |
| cnd | ✅ |
| ad64 | |
| bm-dijon | |
| am-angers | |
| Drac-Alsace | |
| Mercure:/home/ajlsm/recette/... | ✅ |
🧩 Archivage mensuel et nettoyage automatique des logs Tomcat / Java
[modifier | modifier le wikicode]
🎯 Objectif
[modifier | modifier le wikicode]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).
Ce script automatise la rotation, l’archivage et la purge des logs Tomcat, selon une politique de rétention mensuelle.
Il regroupe les fichiers journaliers (.log, .txt) en archives mensuelles compressées (.gz), conserve le mois courant en clair, et supprime automatiquement les plus anciens.
Paramètres à modifier selon l’installation
[modifier | modifier le wikicode]# ---------- PARAMÈTRES À ADAPTER ---------- DIRS=( "/home/ajlsm/tomcats/preprod/logs" # "/home/ajlsm/tomcats/slecture/logs" "/home/ajlsm/tomcats/internet/logs" "/home/ajlsm/tomcats/internet/webapps/pleade/WEB-INF/logs" # "/home/ajlsm/tomcats/slecture/webapps/pleade/WEB-INF/logs" "/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs" ) RETENTION_COMPRESSED_MONTHS=11 # Nombre de mois d’archives compressées à conserver (hors mois courant) RETENTION_PLAIN_MONTHS=1 # Nombre de mois non compressés (fichiers journaliers ou mensuels actifs) 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=0 # 1 = corriger *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage ARCHIVE_CURRENT_MONTH=0 # 1 = inclure le mois courant (ré-agrège au fil du mois) DEBUG=0 # 1 = activer affichage détaillé des opérations # ------------------------------------------- # Familles par style + extensions (séparées par espaces si plusieurs) # DOT : base.YYYY-MM-DD.ext 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" # HYPH : base-YYYYMMDD.ext (quotidien) 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" # HMTH : base-YYYYMM.ext (mensuel) declare -A FAMILIES_HMTH FAMILIES_HMTH["pleade-stats"]="log" # -------------------------------------------
⚙️ 1. Script d’archivage (archive-logs.sh)
[modifier | modifier le wikicode]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
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH
# 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, cocoon-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
#
# Installer le script ici : /usr/local/sbin/archive-logs.sh
# Lancer avec crontab -e, par exe :
# Rotation des logs des 3 tomcats tous les 1er de chaque mois.
# 10 6 1 * * /usr/local/sbin/archive-logs.sh >> /home/ajlsm/rotation-logs-pleade/archive-logs-$(date +\%Y-\%m-\%d).log 2>&1
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/logs"
"/home/ajlsm/tomcats/internet/webapps/pleade/WEB-INF/logs"
"/home/ajlsm/tomcats/slecture/webapps/pleade/WEB-INF/logs"
"/home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs"
)
RETENTION_COMPRESSED_MONTHS=11 # Nombre de mois d’archives compressées à conserver (hors mois courant)
RETENTION_PLAIN_MONTHS=1 # Nombre de mois non compressés (fichiers journaliers ou mensuels actifs)
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=0 # 1 = corriger *.txt-YYYYMMDD / *.log-YYYYMMDD avant archivage
ARCHIVE_CURRENT_MONTH=0 # 1 = inclure le mois courant (ré-agrège au fil du mois)
DEBUG=0 # 1 = activer affichage détaillé des opérations
# -------------------------------------------
# Familles par style + extensions (séparées par espaces si plusieurs)
# DOT : base.YYYY-MM-DD.ext
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"
# HYPH : base-YYYYMMDD.ext (quotidien)
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"
# HMTH : base-YYYYMM.ext (mensuel)
declare -A FAMILIES_HMTH
FAMILIES_HMTH["pleade-stats"]="log"
# -------------------------------------------
log() { printf "[%s] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
# --- Helpers génériques ---
current_month() { date +%Y-%m; }
# Extrait YYYY-MM depuis DOT (base.YYYY-MM-DD.ext ou base-YYYY-MM-DD.ext)
month_from_dot_name() {
local fname
if [[ -n "${1:-}" ]]; then
fname="$1"
else
# lit depuis stdin, mais silencieusement sans renvoyer de codes parasites
IFS= read -r fname || return 1
fi
[[ "$fname" =~ [.-]([0-9]{4})-([0-9]{2})-[0-9]{2}\. ]] || return 0
printf "%s-%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
}
# Extrait YYYY-MM depuis HYPH (base-YYYYMMDD.ext)
month_from_hyph_name() {
local fname
if [[ -n "${1:-}" ]]; then
fname="$1"
else
IFS= read -r fname || return 1
fi
[[ "$fname" =~ -([0-9]{4})([0-9]{2})[0-9]{2}\. ]] || return 0
printf "%s-%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
}
# Extrait YYYY-MM depuis HMTH (base-YYYYMM.ext)
month_from_hmth_name() {
local fname
if [[ -n "${1:-}" ]]; then
fname="$1"
else
IFS= read -r fname || return 1
fi
[[ "$fname" =~ -([0-9]{4})([0-9]{2})\. ]] || return 0
printf "%s-%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
}
# Actions protégées par DRY_RUN
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"; }
# Normalisation des suffixes parasites: *.txt-YYYYMMDD / *.log-YYYYMMDD
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
}
# Construit le nom de sortie de l’archive mensuelle
# - style "dot" -> base.YYYY-MM.ext.gz
# - style "hyph" -> base-YYYY-MM.ext.gz
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
}
# Archive mensuelle à partir d’une liste de fichiers
make_monthly_archive() {
# args: style dir base ext files...
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 # <-- ajout du ="" ici pour éviter "variable sans liaison"
# Déterminer le mois sur le 1er fichier selon le style
case "$style" in
dot) month="$(month_from_dot_name "$(basename -- "${list[0]}")")";;
hyph) month="$(month_from_hyph_name "$(basename -- "${list[0]}")")";;
hmth) month="$(month_from_hmth_name "$(basename -- "${list[0]}")")";;
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"
# Si déjà présent et non vide → on ne refait rien
if [[ -s "$out" ]]; then
log "Archive déjà présente: $out"
return 0
fi
log "Création archive mensuelle: $out"
# Cas HMTH (un seul fichier par mois en général) : on compresse directement
if [[ "$style" == "hmth" ]]; then
# On ne concatène pas, on agrège ce(s) fichier(s) mensuel(s)
: > "$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 mensuels (${#list[@]})"
do_rm "${list[@]}"
fi
return 0
fi
# Cas DOT/HYPH (quotidiens) : concaténer puis compresser
: > "$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 quotidiens (${#list[@]})"
do_rm "${list[@]}"
else
log "⚠️ Échec création archive: $out (aucune suppression faite)"
fi
}
# Parcours d’un style donné
process_style() {
local style="$1" ; shift
declare -n families="$1" # référence associative
local nowm; nowm="$(current_month)"
local m y mm
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} "$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
(( DEBUG )) && log "[DEBUG] style=$style base=$base ext=$ext dir=$d → ${#files[@]} fichiers"
[[ ${#files[@]} -eq 0 ]] && continue
# Regrouper par mois (hors mois courant sauf si ARCHIVE_CURRENT_MONTH=1)
declare -A months=()
for f in "${files[@]}"; do
case "$style" in
dot) m="$(month_from_dot_name "$(basename -- "$f")")";;
hyph) m="$(month_from_hyph_name "$(basename -- "$f")")";;
hmth) m="$(month_from_hmth_name "$(basename -- "$f")")";;
esac
[[ -z "$m" ]] && continue # <-- ajoute cette ligne
if (( ! ARCHIVE_CURRENT_MONTH )) && [[ "$m" == "$nowm" ]]; then
continue
fi
months["$m"]=1
done
if (( DEBUG )); then
if (( ${#months[@]} )); then
# Affiche les clés (mois) séparées par des espaces
log "[DEBUG] Mois détectés : ${!months[@]}"
else
log "[DEBUG] Mois détectés : aucun"
fi
fi
[[ ${#months[@]} -eq 0 ]] && continue
# Pour chaque mois, lister les fichiers et archiver
for m in "${!months[@]}"; do
local -a month_files=()
case "$style" in
dot)
while IFS= read -r line; do month_files+=( "$line" ); done < <(
printf "%s\n" "${files[@]}" |
grep -E "/${base}[.-]${m}-[0-9]{2}\.${ext}$" |
LC_ALL=C sort
)
;;
hyph)
y="${m%%-*}"; mm="${m##*-}"
while IFS= read -r line; do month_files+=( "$line" ); done < <(
printf "%s\n" "${files[@]}" |
grep -E "/${base}-${y}${mm}[0-9]{2}\.${ext}$" |
LC_ALL=C sort
)
;;
hmth)
y="${m%%-*}"; mm="${m##*-}"
while IFS= read -r line; do month_files+=( "$line" ); done < <(
printf "%s\n" "${files[@]}" |
grep -E "/${base}-${y}${mm}\.${ext}$" |
LC_ALL=C sort
)
;;
esac
(( DEBUG )) && log "[DEBUG] Archivage mois=$m → ${#month_files[@]} fichiers"
[[ ${#month_files[@]} -eq 0 ]] && continue
make_monthly_archive "$style" "$d" "$base" "$ext" "${month_files[@]}"
done
# Mode “paquets de N” (pour DOT & HYPH uniquement)
if (( BATCH_SIZE > 0 )) && [[ "$style" != "hmth" ]]; then
local -a oldest=()
while IFS= read -r line; do oldest+=( "$line" ); done < <(
printf "%s\n" "${files[@]}" | LC_ALL=C sort | head -n "$BATCH_SIZE"
)
if (( ${#oldest[@]} == BATCH_SIZE )); then
make_monthly_archive "$style" "$d" "$base" "$ext" "${oldest[@]}"
fi
fi
done
done
done
}
# ----- PURGE -----
purge_old_archives() {
local keep_compressed=$((RETENTION_COMPRESSED_MONTHS))
local keep_plain=$((RETENTION_PLAIN_MONTHS))
local now_y now_m
now_y=$(date +%Y)
now_m=$(date +%m)
for d in "${DIRS[@]}"; do
[[ -d "$d" ]] || continue
# ---- Purge des archives compressées (base-YYYY-MM.ext.gz ou base.YYYY-MM.ext.gz)
while IFS= read -r -d '' f; do
local y m diff
if [[ "$f" =~ ([0-9]{4})-([0-9]{2})\. ]]; then
y="${BASH_REMATCH[1]}"
m="${BASH_REMATCH[2]}"
diff=$(( (10#$now_y - 10#$y) * 12 + (10#$now_m - 10#$m) ))
if (( diff > keep_compressed )); then
(( DRY_RUN )) && log "[DRY] suppression archive ancienne ($diff mois): $f" || { log "Suppression ancienne archive: $f"; rm -f -- "$f"; }
fi
fi
done < <(find "$d" -maxdepth 1 -type f -regextype posix-extended \
\( -regex '.*/[^/]+\.[0-9]{4}-[0-9]{2}\.(log|txt)\.gz' -o -regex '.*/[^/]+-[0-9]{4}-[0-9]{2}\.(log|txt)\.gz' \) -print0)
# ---- Purge des fichiers mensuels non compressés (cas HMTH: pleade-stats-YYYYMM.log)
while IFS= read -r -d '' f; do
local y m diff
if [[ "$f" =~ ([0-9]{4})([0-9]{2})\.log$ ]]; then
y="${BASH_REMATCH[1]}"
m="${BASH_REMATCH[2]}"
diff=$(( (10#$now_y - 10#$y) * 12 + (10#$now_m - 10#$m) ))
if (( diff > keep_plain )); then
(( DRY_RUN )) && log "[DRY] suppression ancien mensuel ($diff mois): $f" || { log "Suppression ancien mensuel: $f"; rm -f -- "$f"; }
fi
fi
done < <(find "$d" -maxdepth 1 -type f -name '*-[0-9][0-9][0-9][0-9][0-1][0-9].log' -print0)
done
}
# ----- Verrou -----
LOCK_DIR="/home/ajlsm/.lock"
LOCK="$LOCK_DIR/archive-logs.lock"
mkdir -p "$LOCK_DIR"
exec 9>"$LOCK"
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
[modifier | modifier le wikicode]
➤ Exécution mensuelle (chaque 1er du mois à 06:10)
[modifier | modifier le wikicode]10 6 1 * * /usr/local/sbin/archive-logs.sh >> /var/log/archive-logs.log 2>&1
➤ Option quotidienne (si BATCH_SIZE > 0))
[modifier | modifier le wikicode]5 6 * * * /usr/local/sbin/archive-logs.sh >> /var/log/archive-logs.log 2>&1
🧹 3. Renommage automatique
[modifier | modifier le wikicode]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
[modifier | modifier le wikicode]| 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
[modifier | modifier le wikicode]- 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
[modifier | modifier le wikicode]
Avant
[modifier | modifier le wikicode]sdx-20251101.log sdx-20251102.log sdx-20251103.log ... pleade-stats-202510.log
Après exécution
[modifier | modifier le wikicode]sdx-2025-11.log.gz pleade-stats-2025-10.log.gz
⚙️ Configuration principale
[modifier | modifier le wikicode]
Répertoires surveillés
[modifier | modifier le wikicode]Le script agit sur les répertoires renseignés dans la section « DIR », par exemple :
/home/ajlsm/tomcats/preprod/logs /home/ajlsm/tomcats/internet/logs /home/ajlsm/tomcats/internet/webapps/pleade/WEB-INF/logs /home/ajlsm/tomcats/preprod/webapps/pleade/WEB-INF/logs
Durées de conservation
[modifier | modifier le wikicode]RETENTION_PLAIN_MONTHS=1 # Mois récents non compressés
RETENTION_COMPRESSED_MONTHS=11 # Mois plus anciens archivés (.gz)
➡️ En tout : 1 an de rétention (1 mois clair + 11 mois compressés)
➡️ Le mois courant reste toujours présent (non compressé)
Autres options importantes
[modifier | modifier le wikicode]DRY_RUN=1 # 1 = simulation (aucune modification)
DEBUG=1 # 1 = affiche les opérations détaillées
NORMALIZE_SUFFIX=1 # Corrige les fichiers mal nommés (*.log-YYYYMMDD)
ARCHIVE_CURRENT_MONTH=0 # N’archive pas le mois en cours
🧩 Typologie des logs
[modifier | modifier le wikicode]| Style | Exemple de nom | Description | Familles |
|---|---|---|---|
| DOT | manager.2025-11-07.log
|
Nom avec point avant la date | manager, localhost, catalina, host-manager
|
| HYPH | sdx-20251107.log
|
Nom avec tiret et date concaténée | sdx, cocoon, publication, auto-publication, oai
|
| HMTH | pleade-stats-202511.log
|
Un seul fichier mensuel | pleade-stats
|
Chaque style est traité différemment : - DOT / HYPH → fusion journalière → archive mensuelle compressée.
- HMTH → compression directe (un seul fichier par mois).
🔁 Étapes d’exécution
[modifier | modifier le wikicode]
1. Normalisation
[modifier | modifier le wikicode]Corrige les fichiers mal suffixés :
catalina.log-20251107 → catalina.log
2. Groupement par mois
[modifier | modifier le wikicode]Détection automatique des fichiers d’un même mois (ex : 2025-10).
3. Archivage mensuel
[modifier | modifier le wikicode]Concaténation puis compression :
publication-20251001.log … publication-20251031.log ⮕ publication-2025-10.log.gz
4. Purge automatique
[modifier | modifier le wikicode]- Supprime les archives
.gzplus vieilles queRETENTION_COMPRESSED_MONTHS. - Supprime les fichiers mensuels
.log(HMTH) plus vieux queRETENTION_PLAIN_MONTHS. - Ignore toujours le mois courant.
5. Gestion de concurrence
[modifier | modifier le wikicode]Empêche les exécutions simultanées via un verrou :
/var/lock/archive-logs.lock
🧰 Modes de fonctionnement
[modifier | modifier le wikicode]| Option | Effet |
|---|---|
DRY_RUN=1
|
Mode simulation (aucune écriture/suppression) |
DEBUG=1
|
Affiche les mois détectés, les familles traitées et les actions prévues |
ARCHIVE_CURRENT_MONTH=1
|
Autorise la réarchivage du mois en cours |
NORMALIZE_SUFFIX=1
|
Active la correction des suffixes parasites |
🔒 Sécurité et robustesse
[modifier | modifier le wikicode]set -euo pipefail: arrêt sur erreur, variable non définie ou pipe brisé.
flock: verrou d’exécution exclusif.
umask 022: permissions sûres pour les archives.
- Wrappers
do_mv,do_rm,do_gzip_f: toutes les actions respectent le modeDRY_RUN.
🧾 Exemple concret
[modifier | modifier le wikicode]Avant archivage :
publication-20251001.log publication-20251002.log ... publication-20251031.log
Après archivage :
publication-2025-10.log.gz publication-20251101.log (mois en cours)
🧮 Cas particuliers
[modifier | modifier le wikicode]
🔹 pleade-stats
[modifier | modifier le wikicode]Fichiers mensuels natifs (HMTH).
Le script les compresse directement, sans concaténation.
Rétention : 12 mois (1 clair + 11 compressés).
🔹 Fichiers journaliers
[modifier | modifier le wikicode]Agrégés mois par mois, puis supprimés une fois l’archive validée.
🧹 Exemple de nettoyage automatique
[modifier | modifier le wikicode]
Après un an de fonctionnement :
[modifier | modifier le wikicode]- Le mois courant reste en clair.
- Les 11 derniers mois compressés sont conservés.
- Tout le reste (fichiers + archives anciennes) est supprimé.
🔧 Bonnes pratiques
[modifier | modifier le wikicode]Lancer le script une fois par jour via cron :
5 6 * * * /usr/local/sbin/archive-logs.sh >/var/log/archive-logs-run.log 2>&1
Tester d’abord en mode
DRY_RUN=1.
Vérifier les tailles et dates avec :
ls -lhtr /home/ajlsm/tomcats/*/logs
🏁 Résumé rapide
[modifier | modifier le wikicode]| Élément | Valeur |
|---|---|
| Rotation | Mensuelle |
| Compression | GZIP |
| Rétention totale | 12 mois |
| Sécurité | Verrouillage + set -euo pipefail
|
| Mode test | DRY_RUN=1
|
| Journalisation | Messages datés [YYYY-MM-DD HH:MM:SS]
|
Dernière version fonctionnelle : novembre 2025
👨💻 Mainteneur : Jean-Luc Arvers
📍 /usr/local/sbin/archive-logs.sh