From b60de57c6e0e0f045bf3fb42e59d1657b9011ec0 Mon Sep 17 00:00:00 2001 From: thomas Date: Thu, 5 Mar 2026 17:54:52 +0100 Subject: [PATCH] Actualiser update.sh Signed-off-by: thomas --- update.sh | 151 +++++++++++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 71 deletions(-) diff --git a/update.sh b/update.sh index 7ed1b91..dc71797 100644 --- a/update.sh +++ b/update.sh @@ -2,8 +2,11 @@ set -euo pipefail MODE="${1:-unknown}" +STAGE="${2:-all}" # system | docker | all +# ───────────────────────────────────────────── # 📁 Logs par date +# ───────────────────────────────────────────── LOG_ROOT="/var/log/lxc-updater-TM" DATE="$(date +%F)" TS="$(date +%H%M%S)" @@ -26,7 +29,23 @@ log_file_only() { echo "[$(date -Is)] $*" >>"$LOG_ARCHIVE" } -# ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ spinner +# ───────────────────────────────────────────── +# 🎛️ Header (style Proxmox) +# ───────────────────────────────────────────── +header() { + local title="$1" + log "╔══════════════════════════════════════╗" + log "║ LXC Updater (TM) ║" + log "╚══════════════════════════════════════╝" + log "🖥️ Conteneur : $(hostname)" + log "📅 Date : ${DATE} 🕒 Heure : ${TS}" + log "📌 Étape : ${title}" + log "" +} + +# ───────────────────────────────────────────── +# ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ Spinner +# ───────────────────────────────────────────── spinner_start() { local msg="$1" local -a frames=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏") @@ -62,6 +81,7 @@ spinner_stop() { run_cmd() { local title="$1"; shift + spinner_start "$title" log_file_only "----- ${title} -----" log_file_only "CMD: $*" @@ -80,9 +100,9 @@ run_cmd() { return 0 } -# ------------------------------ +# ───────────────────────────────────────────── # 📦 Mise à jour OS -# ------------------------------ +# ───────────────────────────────────────────── apt_upgradable_count() { LC_ALL=C apt-get -s upgrade 2>/dev/null | grep -c '^Inst ' || true } @@ -114,9 +134,9 @@ update_apk() { log "✅ Mise à jour APK terminée" } -# ------------------------------ +# ───────────────────────────────────────────── # 🐳 Mise à jour Docker -# ------------------------------ +# ───────────────────────────────────────────── docker_image_id() { docker image inspect -f '{{.Id}}' "$1" 2>/dev/null || true } @@ -132,18 +152,25 @@ is_compose_dir_valid() { [[ -d "$d" ]] && { [[ -f "$d/docker-compose.yml" ]] || [[ -f "$d/compose.yml" ]]; } } -update_compose_dir() { +compose_services_in_dir() { local dir="$1" - log "📂 Projet : $dir" - - # 🧾 Liste des services/containeurs du projet local services="" + if docker compose version >/dev/null 2>&1; then services="$(cd "$dir" && docker compose config --services 2>/dev/null | tr '\n' ' ' | sed 's/ *$//')" elif command -v docker-compose >/dev/null 2>&1; then services="$(cd "$dir" && docker-compose config --services 2>/dev/null | tr '\n' ' ' | sed 's/ *$//')" fi + echo "$services" +} + +update_compose_dir() { + local dir="$1" + log "📂 Projet : $dir" + + local services + services="$(compose_services_in_dir "$dir")" if [[ -n "$services" ]]; then log "📦 Conteneurs/Services du projet : $services" log "🔁 Mise à jour des conteneurs : $services" @@ -151,7 +178,6 @@ update_compose_dir() { log "📦 Conteneurs/Services du projet : (inconnus)" fi - # ✅ Pull + recreate safe if docker compose version >/dev/null 2>&1; then run_cmd "Téléchargement des images (Compose)" bash -c "cd '$dir' && docker compose pull" run_cmd "Redéploiement des services (Compose)" bash -c "cd '$dir' && docker compose up -d --remove-orphans" @@ -172,7 +198,6 @@ recreate_docker_run_container() { local name="$1" local image="$2" - # jq obligatoire pour recréer proprement if ! command -v jq >/dev/null 2>&1; then run_cmd "Redémarrage du conteneur : $name" docker restart "$name" log "⚠️ 'jq' absent → redémarrage uniquement (recréation automatique impossible)" @@ -190,13 +215,9 @@ recreate_docker_run_container() { mapfile -t envs < <(jq -r '.[0].Config.Env[]? // empty' "$tmp") mapfile -t binds < <(jq -r '.[0].HostConfig.Binds[]? // empty' "$tmp") - - # Ports: containerPort/proto = HostIp:HostPort mapfile -t port_rules < <( jq -r '.[0].HostConfig.PortBindings | to_entries[]? | "\(.key)=\(.value[0].HostIp // ""):\(.value[0].HostPort)"' "$tmp" ) - - # Réseaux (si default/bridge) mapfile -t nets < <(jq -r '.[0].NetworkSettings.Networks | keys[]? // empty' "$tmp") local new_name="${name}__new" @@ -213,18 +234,14 @@ recreate_docker_run_container() { for e in "${envs[@]}"; do args+=(-e "$e") done - - # volumes/binds -> données conservées for b in "${binds[@]}"; do args+=(-v "$b") done - # ports for pr in "${port_rules[@]}"; do - cport="${pr%%=*}" # ex: 8080/tcp - mapping="${pr#*=}" # ex: 0.0.0.0:8080 ou :8080 + cport="${pr%%=*}" # 8080/tcp + mapping="${pr#*=}" # 0.0.0.0:8080 ou :8080 cportnum="${cport%/*}" # 8080 - if [[ "$mapping" == :* ]]; then hostport="${mapping#:}" args+=(-p "${hostport}:${cportnum}") @@ -235,17 +252,14 @@ recreate_docker_run_container() { fi done - # network mode (si spécial) if [[ "$network_mode" != "default" && "$network_mode" != "bridge" ]]; then args+=(--network "$network_mode") fi - # image args+=("$image") run_cmd "Création du nouveau conteneur : $name" "${args[@]}" - # connecter aux réseaux additionnels si needed if [[ "$network_mode" == "default" || "$network_mode" == "bridge" ]]; then for n in "${nets[@]}"; do [[ "$n" == "bridge" || "$n" == "host" || "$n" == "none" ]] && continue @@ -253,7 +267,6 @@ recreate_docker_run_container() { done fi - # switch run_cmd "Arrêt du conteneur : $name" docker stop "$name" run_cmd "Renommage de l'ancien conteneur" docker rename "$name" "${name}__old" run_cmd "Renommage du nouveau conteneur" docker rename "$new_name" "$name" @@ -268,7 +281,7 @@ update_docker() { run_cmd "Vérification Docker" docker ps - # ---- 1) Compose via labels + # ---- 1) Compose log "🔍 Recherche de projets Docker Compose" mapfile -t dirs < <(compose_dirs_from_labels) @@ -290,7 +303,7 @@ update_docker() { log "⚠️ Aucun projet Compose détecté via labels" fi - # ---- 2) Conteneurs non-Compose = docker run + # ---- 2) docker run (non-Compose) mapfile -t run_containers < <( docker ps -q | while read -r cid; do p="$(docker inspect -f '{{ index .Config.Labels "com.docker.compose.project" }}' "$cid" 2>/dev/null || true)" @@ -335,53 +348,49 @@ update_docker() { log "✅ Mise à jour Docker terminée" } -# ------------------------------ -# 🔎 Mode : base + docker éventuel -# Exemples : apt, apk, apt+docker, apk+docker, docker, unknown -# ------------------------------ +# ───────────────────────────────────────────── +# 🔎 Détection base_mode depuis MODE +# MODE attendu : apt / apk / apt+docker / apk+docker / docker / unknown +# ───────────────────────────────────────────── BASE_MODE="${MODE%%+docker}" -HAS_DOCKER="0" -[[ "$MODE" == *"+docker" ]] && HAS_DOCKER="1" -# Si MODE == "docker" seul (au cas où), on active docker -if [[ "$MODE" == "docker" ]]; then - HAS_DOCKER="1" +# ───────────────────────────────────────────── +# 🚦 Exécution selon STAGE +# ───────────────────────────────────────────── +if [[ "$STAGE" == "system" || "$STAGE" == "all" ]]; then + header "Mise à jour du système" + + case "$BASE_MODE" in + apt) update_apt ;; + apk) update_apk ;; + *) + if command -v apt-get >/dev/null 2>&1; then + update_apt + elif command -v apk >/dev/null 2>&1; then + update_apk + else + log "⚠️ Impossible de détecter le gestionnaire de paquets (apt/apk)" + fi + ;; + esac + + log "" + log "🧾 Log update : ${LOG_FILE}" + log "🗃️ Archive update : ${LOG_ARCHIVE}" + log "🎉 Étape terminée" fi -# ------------------------------ -# 🖥️ Sortie lisible -# ------------------------------ -log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log "📦 Mise à jour du système" -log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +if [[ "$STAGE" == "docker" || "$STAGE" == "all" ]]; then + header "Mise à jour des conteneurs Docker" -case "$BASE_MODE" in - apt) update_apt ;; - apk) update_apk ;; - *) - # Si apt/apk non détecté mais apt-get existe, on tente apt - if command -v apt-get >/dev/null 2>&1; then - update_apt - elif command -v apk >/dev/null 2>&1; then - update_apk - else - log "⚠️ Impossible de détecter le gestionnaire de paquets (apt/apk)" - fi - ;; -esac + if command -v docker >/dev/null 2>&1; then + update_docker + else + log "🐳 Docker non présent" + fi -log "" -log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log "🐳 Mise à jour du ou des conteneurs" -log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - -if command -v docker >/dev/null 2>&1; then - update_docker -else - log "🐳 Docker non présent" -fi - -log "" -log "🧾 Log update : ${LOG_FILE}" -log "🗃️ Archive update : ${LOG_ARCHIVE}" -log "🎉 Mise à jour terminée" \ No newline at end of file + log "" + log "🧾 Log update : ${LOG_FILE}" + log "🗃️ Archive update : ${LOG_ARCHIVE}" + log "🎉 Étape terminée" +fi \ No newline at end of file