#!/usr/bin/env bash set -euo pipefail METHOD="${1:-unknown}" LOG_DIR="/var/log" TS="$(date +'%Y%m%d-%H%M%S')" LOG_FILE="${LOG_DIR}/lxc-updater.log" LOG_ARCHIVE="${LOG_DIR}/lxc-updater-${TS}.log" mkdir -p "$LOG_DIR" # On réinitialise le log courant, et on garde une archive : > "$LOG_FILE" touch "$LOG_ARCHIVE" # Tout ce qui est "debug/commande" -> log fichier (mais pas console) log_file() { echo "[$(date -Is)] $*" >> "$LOG_FILE" echo "[$(date -Is)] $*" >> "$LOG_ARCHIVE" } # Messages courts console (et aussi dans le fichier) log_console() { echo "$1" log_file "$1" } # Spinner simple (points qui bougent) spinner_start() { # $1 = message console local msg="$1" printf "%s" "$msg" ( while true; do printf "." sleep 0.35 done ) & SPINNER_PID=$! } spinner_stop_ok() { local rc="${1:-0}" if [[ -n "${SPINNER_PID:-}" ]]; then kill "$SPINNER_PID" >/dev/null 2>&1 || true wait "$SPINNER_PID" 2>/dev/null || true unset SPINNER_PID fi if [[ "$rc" -eq 0 ]]; then echo " ✅" else echo " ❌" fi } # Exécute une commande en envoyant toute sa sortie dans le log run_cmd() { local title="$1"; shift spinner_start "⏳ $title" log_file "----- $title -----" log_file "CMD: $*" set +e "$@" >>"$LOG_FILE" 2>&1 local rc=$? set -e spinner_stop_ok "$rc" if [[ $rc -ne 0 ]]; then log_file "ERREUR (code=$rc) sur: $title" return $rc fi return 0 } log_console "🧭 Mode de mise à jour : ${METHOD}" update_apt() { log_console "📦 Mise à jour Debian/Ubuntu (APT)" export DEBIAN_FRONTEND=noninteractive # Optionnel: rendre apt plus silencieux dans le log (tu peux enlever -qq si tu veux tout) run_cmd "Mise à jour de la liste des paquets" apt-get update -y run_cmd "Installation des mises à jour" apt-get upgrade -y run_cmd "Rechargement systemd (si nécessaire)" systemctl daemon-reload } update_apk() { log_console "📦 Mise à jour Alpine (APK)" run_cmd "Mise à jour des dépôts" apk update run_cmd "Installation des mises à jour" apk upgrade } update_docker() { log_console "🐳 Mise à jour Docker" run_cmd "Vérification Docker" docker ps log_console "🔍 Recherche de projets Docker Compose" mapfile -t dirs < <( docker ps -q | while read -r cid; do docker inspect -f '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$cid" 2>/dev/null || true done | sed '/^$/d;/^$/d' | sort -u ) if (( ${#dirs[@]} > 0 )); then log_console "📁 Projet(s) Compose détecté(s) : ${#dirs[@]}" for d in "${dirs[@]}"; do log_console "📂 Projet : $d" # On loggue aussi le cd log_file "CD: $d" cd "$d" if docker compose version >/dev/null 2>&1; then run_cmd "Compose pull" docker compose pull run_cmd "Compose up -d" docker compose up -d elif command -v docker-compose >/dev/null 2>&1; then run_cmd "Compose pull (v1)" docker-compose pull run_cmd "Compose up -d (v1)" docker-compose up -d else log_console "❌ Docker Compose n'est pas installé (voir logs)" return 2 fi done return 0 fi log_console "⚠️ Aucun Compose détecté → pull des images uniquement (pas de recréation auto)" # Pull images uniques while read -r img; do [[ -n "$img" ]] || continue run_cmd "Pull image: $img" docker pull "$img" done < <(docker ps --format '{{.Image}}' | sort -u) } case "$METHOD" in apt) update_apt ;; apk) update_apk ;; docker) update_docker ;; *) log_console "❌ Méthode inconnue : $METHOD" exit 2 ;; esac log_console "🧾 Log : $LOG_FILE" log_console "🗃️ Archive : $LOG_ARCHIVE" log_console "🎉 Terminé"