Última atividade 1 month ago

Full backup zip + all compose file ! Compose Docker + Report Html

Erreur32's Avatar Erreur32 revisou este gist 4 months ago. Ir para a revisão

1 file changed, 482 insertions, 168 deletions

Backup-Home-docker.tar.gz.sh

@@ -1,38 +1,47 @@
1 1 #!/bin/bash
2 2
3 + # Backup complet Docker + (CasaOS si présent) + Portainer
4 + # + export docker-compose + rapport HTML + index
5 + # + last/ + rotation + publication WEB (HTML only)
6 +
3 7 #############################
4 8 # CONFIG
5 9 #############################
6 10
7 - # Backup complet des data docker , casaos et portainer
8 - # avec liste de tous les compose files des containers classés par répertoire.
9 -
10 -
11 - # Répertoire contenant tes containers
12 11 SOURCE_DIR="/home/docker"
13 12
14 - # Répertoire où stocker les sauvegardes
15 - BACKUP_DIR="/home/backup/docker"
16 -
17 - # Nombre max de backups à conserver (dossiers datés)
13 + # Base des backups datés
14 + BACKUP_DIR="/home/backup/docker/compose"
18 15 MAX_BACKUPS=3
19 16
20 - # Date interne (pour logs / JSON)
21 17 DATE_RAW="$(date +'%Y%m%d_%H%M%S')"
22 - # Date pour le dossier de backup (format humain demandé)
23 18 DATE_DIR="$(date +'%Y.%m.%d_%H-%M-%S')"
24 19
25 - # Dossier de ce backup
20 + # Dossier daté du run courant
26 21 RUN_DIR="$BACKUP_DIR/$DATE_DIR"
27 22
28 - # Fichiers TAR dans le dossier de ce backup
23 + # Dossier "dernier backup"
24 + LAST_DIR="$BACKUP_DIR/last"
25 +
26 + # Archives dans le dossier daté
29 27 BACKUP_FILE="$RUN_DIR/docker_backup.tar.gz"
30 28 CASAOS_FULL_TAR="$RUN_DIR/casaos_full_backup.tar.gz"
31 29
32 - # Dossier où l'on met les compose / configs
30 + # Dossier de configs / compose dans le run
33 31 CONFIG_DIR="$RUN_DIR"
34 32
35 - # Dossiers à exclure (chemins relatifs à $SOURCE_DIR pour le tar Docker)
33 + # Logs
34 + LOG_FILE="/var/log/docker_backup.log"
35 +
36 + # Rapports HTML
37 + HTML_REPORT="$RUN_DIR/report.html"
38 + HTML_REPORT_LAST="$LAST_DIR/report.html"
39 + HTML_INDEX_LAST="$LAST_DIR/index.html"
40 +
41 + # Publication WEB (HTML uniquement)
42 + WEB_PUBLIC_DIR="/home/www-adm1n/docker_compose"
43 +
44 + # Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
36 45 EXCLUDE_DIRS=(
37 46 "docker_var_lib"
38 47 "1_Backups"
@@ -41,17 +50,42 @@ EXCLUDE_DIRS=(
41 50 "yt-dl/video/*"
42 51 )
43 52
44 - # LOGS
45 - LOG_FILE="/var/log/docker_backup.log"
53 + #############################
54 + # MODE TTY / CRON
55 + #############################
56 +
57 + # Si pas de terminal (cron), on désactive les couleurs
58 + if [ -t 1 ]; then
59 + USE_COLORS=1
60 + else
61 + USE_COLORS=0
62 + fi
46 63
47 64 #############################
48 65 # COULEURS
49 66 #############################
50 - NC="\e[0m"
51 - GREEN="\e[32m"
52 - YELLOW="\e[33m"
53 - CYAN="\e[36m"
54 - RED="\e[31m"
67 + if [ "$USE_COLORS" = "1" ]; then
68 + NC="\e[0m"
69 + GREEN="\e[32m"
70 + YELLOW="\e[33m"
71 + CYAN="\e[36m"
72 + RED="\e[31m"
73 + else
74 + NC=""
75 + GREEN=""
76 + YELLOW=""
77 + CYAN=""
78 + RED=""
79 + fi
80 +
81 + #############################
82 + # DÉTECTION CASAOS
83 + #############################
84 +
85 + CASAOS_PRESENT=0
86 + if [ -d "/var/lib/casaos" ] || [ -d "$SOURCE_DIR/casaos_data" ] || command -v casaos >/dev/null 2>&1; then
87 + CASAOS_PRESENT=1
88 + fi
55 89
56 90 #############################
57 91 # FONCTIONS
@@ -75,29 +109,42 @@ format_time() {
75 109
76 110 check_pigz() {
77 111 if ! command -v pigz >/dev/null 2>&1; then
78 - echo -e "${YELLOW}pigz n'est pas installé. Voulez-vous l’installer ? (y/n)${NC}"
79 - read rep
80 - if [ "$rep" = "y" ]; then
81 - sudo apt update && sudo apt install -y pigz || {
82 - echo -e "${RED}Échec de l’installation de pigz. Abandon.${NC}"
112 + log_message "pigz n'est pas installé."
113 +
114 + if [ "$USE_COLORS" = "1" ]; then
115 + echo -e "${YELLOW}pigz n'est pas installé. Voulez-vous l’installer ? (y/n)${NC}"
116 + read -r rep
117 + if [ "$rep" = "y" ]; then
118 + sudo apt update && sudo apt install -y pigz || {
119 + echo -e "${RED}Échec installation pigz. Abandon.${NC}"
120 + exit 1
121 + }
122 + else
123 + echo -e "${RED}pigz requis. Abandon.${NC}"
83 124 exit 1
84 - }
125 + fi
85 126 else
86 - echo -e "${RED}pigz est requis pour ce script. Abandon.${NC}"
127 + echo "ERREUR: pigz requis (mode cron non-interactif)."
87 128 exit 1
88 129 fi
89 130 fi
90 131 }
91 132
92 133 rotate_backups() {
93 - log_message "Rotation des anciens backups (conserver les $MAX_BACKUPS plus récents)..."
134 + log_message "Rotation backups (max $MAX_BACKUPS)..."
94 135
95 - # On ne garde que les dossiers datés dans BACKUP_DIR
96 - mapfile -t backups_dirs < <(ls -1td "$BACKUP_DIR"/*/ 2>/dev/null || true)
136 + # Liste uniquement les dossiers datés, ignore last/
137 + mapfile -t backups_dirs < <(
138 + find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d \
139 + ! -name "last" \
140 + -printf "%T@ %p\n" 2>/dev/null \
141 + | sort -nr \
142 + | awk '{print $2}'
143 + )
97 144
98 145 if [ "${#backups_dirs[@]}" -gt "$MAX_BACKUPS" ]; then
99 146 for d in "${backups_dirs[@]:$MAX_BACKUPS}"; do
100 - log_message "Suppression ancien backup (dossier) : $d"
147 + log_message "Suppression ancien backup : $d"
101 148 rm -rf "$d"
102 149 done
103 150 fi
@@ -107,6 +154,140 @@ get_size() {
107 154 du -sh "$1" 2>/dev/null | awk '{print $1}'
108 155 }
109 156
157 + html_escape() {
158 + sed -e 's/&/\&amp;/g' \
159 + -e 's/</\&lt;/g' \
160 + -e 's/>/\&gt;/g'
161 + }
162 +
163 + html_line() {
164 + # $1=label $2=value $3=emoji $4=class
165 + echo "<div class='row $4'><span class='emoji'>$3</span><span class='label'>$1</span><span class='value'>$2</span></div>" >> "$HTML_REPORT"
166 + }
167 +
168 +
169 + html_container_table() {
170 + local dirs
171 + dirs=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
172 + ! -path "$SOURCE_DIR/casaos_data" \
173 + ! -path "$SOURCE_DIR/docker_var_lib" \
174 + ! -path "$SOURCE_DIR/portainer" \
175 + 2>/dev/null)
176 +
177 + if [ -z "$dirs" ]; then
178 + echo "<div class='empty'>Aucun dossier Docker trouvé.</div>" >> "$HTML_REPORT"
179 + return
180 + fi
181 +
182 + echo "<div class='tblwrap'><table class='tbl'>" >> "$HTML_REPORT"
183 + echo "<thead><tr><th>📦 Container</th><th>📏 Taille</th><th>📁 Chemin</th></tr></thead>" >> "$HTML_REPORT"
184 + echo "<tbody>" >> "$HTML_REPORT"
185 +
186 + # tri par taille desc
187 + du -sh $dirs 2>/dev/null | sort -hr | while read -r size path; do
188 + name="$(basename "$path")"
189 + esc_path="$(echo "$path" | html_escape)"
190 + echo "<tr><td><b>$name</b></td><td>$size</td><td><code>$esc_path</code></td></tr>" >> "$HTML_REPORT"
191 + done
192 +
193 + echo "</tbody></table></div>" >> "$HTML_REPORT"
194 + }
195 +
196 +
197 + generate_index_html() {
198 + local base_dir="$1"
199 + local output_file="$2"
200 +
201 + cat > "$output_file" <<EOF
202 + <!doctype html>
203 + <html lang="fr">
204 + <head>
205 + <meta charset="utf-8">
206 + <title>Index Backups Docker</title>
207 + <style>
208 + body{font-family:Arial,sans-serif;background:#0b1220;color:#e5e7eb;margin:0;padding:24px}
209 + .card{background:#111827;border:1px solid #1f2937;border-radius:12px;padding:16px;max-width:980px;margin:auto}
210 + h1{margin:0 0 12px;font-size:22px}
211 + a{color:#93c5fd;text-decoration:none}
212 + a:hover{text-decoration:underline}
213 + hr{border:0;border-top:1px solid #1f2937;margin:12px 0}
214 + .toolbar{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:12px}
215 + .btn{display:inline-block;padding:8px 12px;border-radius:10px;background:#0f172a;border:1px solid #1f2937}
216 + .btn:hover{background:#111c33}
217 + .item{padding:10px;border-radius:12px;margin:8px 0;background:#0f172a;border:1px solid #1f2937}
218 + .row{display:flex;justify-content:space-between;gap:12px;align-items:center;flex-wrap:wrap}
219 + .left{display:flex;gap:10px;align-items:center}
220 + .badge{font-size:12px;padding:4px 8px;border-radius:999px;background:#1f2937}
221 + .badge-ok{background:#052e16;color:#86efac;border:1px solid #14532d}
222 + .badge-warn{background:#451a03;color:#fcd34d;border:1px solid #92400e}
223 + .meta{color:#94a3b8;font-size:12px;margin-top:6px}
224 + small{color:#94a3b8}
225 + .note{color:#94a3b8;font-size:12px;margin-top:10px}
226 + </style>
227 + </head>
228 + <body>
229 + <div class="card">
230 + <h1>📦 Index des Backups Docker</h1>
231 + <small>Dossier backups: $base_dir</small>
232 +
233 + <div class="toolbar">
234 + <a class="btn" href="./report.html">📌 Ouvrir le LAST</a>
235 + </div>
236 +
237 + <div class="note">
238 + ℹ️ Les backups datés ne sont pas exposés sur le web (sécurité).
239 + Seul le rapport <b>LAST</b> est accessible.
240 + </div>
241 +
242 + <hr>
243 + EOF
244 +
245 + # Liste dossiers datés (ignore last)
246 + find "$base_dir" -mindepth 1 -maxdepth 1 -type d ! -name "last" 2>/dev/null \
247 + | sort -r \
248 + | while read -r d; do
249 +
250 + name="$(basename "$d")"
251 + tarfile="$d/docker_backup.tar.gz"
252 + report="$d/report.html"
253 +
254 + mtime="$(date -r "$d" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo 'N/A')"
255 +
256 + if [ -f "$tarfile" ]; then
257 + tarsize="$(du -sh "$tarfile" 2>/dev/null | awk '{print $1}')"
258 + else
259 + tarsize="N/A"
260 + fi
261 +
262 + if [ -f "$report" ]; then
263 + status="OK"
264 + badge="badge-ok"
265 + else
266 + status="missing report"
267 + badge="badge-warn"
268 + fi
269 +
270 + cat >> "$output_file" <<EOF
271 + <div class="item">
272 + <div class="row">
273 + <div class="left">
274 + <span>📄</span>
275 + <span><b>$name</b></span>
276 + </div>
277 + <span class="badge $badge">$status</span>
278 + </div>
279 + <div class="meta">🕒 $mtime — 🗜️ docker_backup.tar.gz : <b>$tarsize</b></div>
280 + </div>
281 + EOF
282 + done
283 +
284 + cat >> "$output_file" <<EOF
285 + </div>
286 + </body>
287 + </html>
288 + EOF
289 + }
290 +
110 291 #############################
111 292 # DÉBUT SCRIPT
112 293 #############################
@@ -116,16 +297,20 @@ SECONDS=0
116 297 check_pigz
117 298
118 299 mkdir -p "$RUN_DIR"
300 + mkdir -p "$BACKUP_DIR"
119 301 touch "$LOG_FILE"
120 302
121 303 echo -e "${CYAN}=== Backup Docker + Configs (Portainer / CasaOS) ===${NC}"
122 - log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."
123 - log_message "Dossier de backup : $RUN_DIR"
304 + log_message "Début sauvegarde..."
305 + log_message "Dossier backup (run) : $RUN_DIR"
306 + log_message "Dossier backup (last): $LAST_DIR"
307 + log_message "CasaOS détecté : $CASAOS_PRESENT"
124 308
125 309 ##############################################
126 - # 1) Sauvegarde TAR Docker via pigz + exclusions
310 + # 1) Archive Docker
127 311 ##############################################
128 - log_message "Création de l’archive Docker : $BACKUP_FILE"
312 +
313 + log_message "Création archive Docker : $BACKUP_FILE"
129 314
130 315 EXCLUDE_ARGS=(
131 316 "--exclude=*.log"
@@ -167,37 +352,44 @@ if [ $? -ne 0 ]; then
167 352 fi
168 353
169 354 ##############################################
170 - # 2) Extraction des docker-compose
171 - # - CasaOS: RUN_DIR/casaos/<container>/
172 - # - Docker: RUN_DIR/docker/<container>/
355 + # 2) Extraction docker-compose CasaOS (si présent)
173 356 ##############################################
174 357
175 - log_message "Extraction des docker-compose CasaOS..."
176 - if [ -d "$SOURCE_DIR/casaos_data" ]; then
177 - find "$SOURCE_DIR/casaos_data" -maxdepth 3 -type f -name "docker-compose.y*ml" | while read file; do
178 - container_name=$(basename "$(dirname "$file")")
179 - dest_dir="$CONFIG_DIR/casaos/$container_name"
180 - mkdir -p "$dest_dir"
181 - cp "$file" "$dest_dir/"
182 - log_message " [CasaOS] → Compose trouvé : $file"
183 - done
358 + if [ "$CASAOS_PRESENT" = "1" ]; then
359 + log_message "Extraction des docker-compose CasaOS..."
360 + if [ -d "$SOURCE_DIR/casaos_data" ]; then
361 + find "$SOURCE_DIR/casaos_data" -maxdepth 3 -type f -name "docker-compose.y*ml" | while read -r file; do
362 + container_name=$(basename "$(dirname "$file")")
363 + dest_dir="$CONFIG_DIR/casaos/$container_name"
364 + mkdir -p "$dest_dir"
365 + cp "$file" "$dest_dir/"
366 + log_message " [CasaOS] compose : $file"
367 + done
368 + fi
369 + else
370 + log_message "CasaOS non détecté → ignoré."
184 371 fi
185 372
186 - log_message "Extraction des docker-compose Docker (hors casaos_data & dossiers exclus)..."
373 + ##############################################
374 + # 3) Extraction docker-compose Docker (hors CasaOS)
375 + ##############################################
376 +
377 + log_message "Extraction des docker-compose Docker..."
187 378 find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
188 379 ! -path "$SOURCE_DIR/casaos_data/*" \
189 380 ! -path "$SOURCE_DIR/docker_var_lib/*" \
190 - 2>/dev/null | while read file; do
381 + 2>/dev/null | while read -r file; do
191 382 container_name=$(basename "$(dirname "$file")")
192 383 dest_dir="$CONFIG_DIR/Compose/$container_name"
193 384 mkdir -p "$dest_dir"
194 385 cp "$file" "$dest_dir/"
195 - log_message " [Docker] → Compose trouvé : $file"
386 + log_message " [Docker] compose : $file"
196 387 done
197 388
198 389 ##############################################
199 - # 3) Config Portainer (full)
390 + # 4) Backup config Portainer (si volume présent)
200 391 ##############################################
392 +
201 393 PORTAINER_CONFIG_DIR="$CONFIG_DIR/portainer"
202 394 PORTAINER_FILES=0
203 395
@@ -211,197 +403,319 @@ else
211 403 fi
212 404
213 405 ##############################################
214 - # 4) Config CasaOS (full + tar.gz)
406 + # 5) Backup CasaOS (config + FULL TAR) si présent
215 407 ##############################################
408 +
216 409 CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"
217 410
218 - if [ -d "/var/lib/casaos" ]; then
219 - log_message "Sauvegarde config CasaOS (full vers $CASAOS_CONFIG_DIR)..."
220 - mkdir -p "$CASAOS_CONFIG_DIR"
221 - cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
222 - fi
411 + if [ "$CASAOS_PRESENT" = "1" ]; then
412 + if [ -d "/var/lib/casaos" ]; then
413 + log_message "Sauvegarde config CasaOS full..."
414 + mkdir -p "$CASAOS_CONFIG_DIR"
415 + cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
416 + fi
223 417
224 - # Création du second tar.gz CasaOS FULL (config + volumes casaos_data)
225 - if [ -d "/var/lib/casaos" ] || [ -d "$SOURCE_DIR/casaos_data" ]; then
226 418 CASAOS_TAR_SOURCES=()
227 419 [ -d "/var/lib/casaos" ] && CASAOS_TAR_SOURCES+=( "/var/lib/casaos" )
228 420 [ -d "$SOURCE_DIR/casaos_data" ] && CASAOS_TAR_SOURCES+=( "$SOURCE_DIR/casaos_data" )
229 421
230 422 if [ "${#CASAOS_TAR_SOURCES[@]}" -gt 0 ]; then
231 - log_message "Création de l’archive CASAOS FULL : $CASAOS_FULL_TAR"
423 + log_message "Création archive CasaOS FULL : $CASAOS_FULL_TAR"
232 424 tar -cf "$CASAOS_FULL_TAR" -I pigz "${CASAOS_TAR_SOURCES[@]}" 2>>"$LOG_FILE"
233 - if [ $? -ne 0 ]; then
234 - log_message "ERREUR lors de la création du tar CasaOS."
235 - echo -e "${RED}Erreur lors de la création de l’archive CasaOS.${NC}"
236 - fi
237 425 fi
238 426 fi
239 427
240 428 ##############################################
241 - # 5) Comptages finaux (sur le backup courant)
429 + # 6) Stats + rotation
242 430 ##############################################
243 431
244 - # Compose dans le backup (docker + CasaOS compose seulement)
245 - CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "docker-compose.y*ml" ! -path "$CASAOS_CONFIG_DIR/*" 2>/dev/null | wc -l)
246 - DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/docker" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
432 + CASAOS_COMPOSE_BACKUP=0
433 + if [ "$CASAOS_PRESENT" = "1" ]; then
434 + CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
435 + fi
436 +
437 + DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/Compose" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
247 438
248 - # Compose dans le dossier source (uniquement /home/docker/<container>/docker-compose.*)
249 439 SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
250 440 ! -path "$SOURCE_DIR/casaos_data/*" \
251 441 ! -path "$SOURCE_DIR/docker_var_lib/*" \
252 442 2>/dev/null | wc -l)
253 443
254 - # Containers Docker "valides"
255 444 CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
256 445 ! -path "$SOURCE_DIR/casaos_data" \
257 446 ! -path "$SOURCE_DIR/docker_var_lib" \
258 447 ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)
259 448
260 - # Rotation des anciens backups (par dossiers)
261 449 rotate_backups
262 450
263 - # Nombre total de sets de backup (dossiers datés)
264 - TOTAL_BACKUP_SETS=$(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | wc -l)
451 + TOTAL_BACKUP_SETS=$(find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d ! -name "last" 2>/dev/null | wc -l)
265 452
266 - # Oldest / newest backup set
267 - mapfile -t CURRENT_SETS < <(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | sort)
453 + mapfile -t CURRENT_SETS < <(find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d ! -name "last" 2>/dev/null | sort)
268 454 OLDEST_DIR="${CURRENT_SETS[0]}"
269 455 NEWEST_DIR="${CURRENT_SETS[${#CURRENT_SETS[@]}-1]}"
270 456
271 457 DURATION="$(format_time $SECONDS)"
272 458
273 - # Tailles des backups courants
274 - TAR_SIZE=$(get_size "$BACKUP_FILE")
275 - CONFIG_SIZE=$(get_size "$CONFIG_DIR")
276 - DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")
459 + TAR_SIZE="$(get_size "$BACKUP_FILE")"
277 460
278 - # CasaOS full config size (copie dans RUN_DIR/casaos/full_config)
279 - if [ -d "$CASAOS_CONFIG_DIR" ]; then
280 - CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
281 - else
282 - CASAOS_CONFIG_SIZE=""
283 - fi
461 + CASAOS_FULL_TAR_SIZE=""
462 + [ -f "$CASAOS_FULL_TAR" ] && CASAOS_FULL_TAR_SIZE="$(get_size "$CASAOS_FULL_TAR")"
284 463
285 - # CasaOS FULL TAR size
286 - if [ -f "$CASAOS_FULL_TAR" ]; then
287 - CASAOS_FULL_TAR_SIZE=$(get_size "$CASAOS_FULL_TAR")
288 - else
289 - CASAOS_FULL_TAR_SIZE=""
290 - fi
464 + PORTAINER_CONFIG_SIZE=""
465 + [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ] && PORTAINER_CONFIG_SIZE="$(get_size "$PORTAINER_CONFIG_DIR")"
466 +
467 +
468 + ##############################################
469 + # 7) Génération rapport HTML (run daté)
470 + ##############################################
291 471
292 - # Portainer full config size
293 - if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
294 - PORTAINER_CONFIG_SIZE=$(get_size "$PORTAINER_CONFIG_DIR")
472 + cat > "$HTML_REPORT" <<EOF
473 + <!doctype html>
474 + <html lang="fr">
475 + <head>
476 + <meta charset="utf-8">
477 + <meta name="viewport" content="width=device-width, initial-scale=1">
478 + <title>Backup Docker Report - $DATE_DIR</title>
479 + <style>
480 + :root{
481 + --bg:#0b1220;
482 + --card:#111827;
483 + --border:#1f2937;
484 + --muted:#94a3b8;
485 + --text:#e5e7eb;
486 + --blue:#93c5fd;
487 + --ok:#22c55e;
488 + --warn:#f59e0b;
489 + --bad:#ef4444;
490 + --row:#0f172a;
491 + --row2:#0c1428;
492 + }
493 + *{box-sizing:border-box}
494 + body{font-family:Arial,system-ui,sans-serif;background:var(--bg);color:var(--text);margin:0;padding:22px}
495 + .card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px;max-width:1100px;margin:auto}
496 + h1{margin:0 0 8px;font-size:22px}
497 + small{color:var(--muted)}
498 + hr{border:0;border-top:1px solid var(--border);margin:14px 0}
499 + h2{margin:16px 0 8px;font-size:15px;color:var(--blue)}
500 +
501 + .row{display:flex;gap:12px;padding:10px;border-radius:12px;align-items:center}
502 + .row:nth-child(odd){background:var(--row)}
503 + .row:nth-child(even){background:var(--row2)}
504 + .label{flex:1;color:#cbd5e1}
505 + .value{font-weight:bold;color:#f8fafc}
506 + .emoji{width:26px;display:inline-block}
507 +
508 + .ok{border-left:4px solid var(--ok)}
509 + .warn{border-left:4px solid var(--warn)}
510 + .bad{border-left:4px solid var(--bad)}
511 + .info{border-left:4px solid #3b82f6}
512 +
513 + .grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
514 + @media (max-width:900px){.grid{grid-template-columns:1fr}}
515 +
516 + .tblwrap{overflow:auto;border:1px solid var(--border);border-radius:14px}
517 + .tbl{width:100%;border-collapse:collapse;min-width:720px}
518 + .tbl th,.tbl td{padding:10px;border-bottom:1px solid var(--border);text-align:left;vertical-align:top}
519 + .tbl th{color:#cbd5e1;background:#0f172a;position:sticky;top:0}
520 + .tbl tr:hover td{background:#0a1020}
521 + code{color:#cbd5e1}
522 + .empty{padding:10px;color:var(--muted)}
523 + .footer{margin-top:14px;color:var(--muted);font-size:12px}
524 + .badge{display:inline-block;padding:3px 8px;border-radius:999px;border:1px solid var(--border);font-size:12px;margin-left:8px}
525 + .badge-ok{background:#052e16;color:#86efac;border-color:#14532d}
526 + .badge-warn{background:#451a03;color:#fcd34d;border-color:#92400e}
527 + </style>
528 + </head>
529 + <body>
530 + <div class="card">
531 + <h1>📦 Backup Docker / CasaOS / Portainer</h1>
532 + <small>📅 $DATE_DIR — 🕒 $(date +'%Y-%m-%d %H:%M:%S')</small>
533 +
534 + <hr>
535 +
536 + <h2>🔧 Global</h2>
537 + EOF
538 +
539 + # lignes global
540 + html_line "Dossier backup courant" "$(echo "$RUN_DIR" | html_escape)" "📁" "info"
541 + html_line "Durée totale" "$DURATION" "⏱️" "info"
542 + html_line "Nombre de sets de backup" "$TOTAL_BACKUP_SETS" "🗂️" "info"
543 +
544 + echo "<h2>🐳 Docker</h2>" >> "$HTML_REPORT"
545 + html_line "Containers détectés" "$CONTAINERS_DOCKER" "🧱" "ok"
546 + html_line "Compose source" "$SOURCE_COMPOSE_COUNT" "📄" "info"
547 + html_line "Compose backup" "$DOCKER_COMPOSE_BACKUP" "📦" "info"
548 + html_line "Archive Docker (.tar.gz)" "$(echo "$BACKUP_FILE ($TAR_SIZE)" | html_escape)" "🗜️" "ok"
549 +
550 + echo "<h2>🏠 CasaOS</h2>" >> "$HTML_REPORT"
551 + if [ "$CASAOS_PRESENT" = "1" ]; then
552 + html_line "CasaOS détecté" "OUI" "✅" "ok"
553 + html_line "Compose CasaOS backup" "$CASAOS_COMPOSE_BACKUP" "📄" "info"
554 + if [ -f "$CASAOS_FULL_TAR" ]; then
555 + html_line "Archive CasaOS FULL (.tar.gz)" "$(echo "$CASAOS_FULL_TAR ($CASAOS_FULL_TAR_SIZE)" | html_escape)" "🗜️" "ok"
556 + else
557 + html_line "Archive CasaOS FULL (.tar.gz)" "Non générée" "⚠️" "warn"
558 + fi
295 559 else
296 - PORTAINER_CONFIG_SIZE=""
560 + html_line "CasaOS détecté" "NON (ignoré)" "🚫" "warn"
297 561 fi
298 562
563 + echo "<h2>🧭 Portainer</h2>" >> "$HTML_REPORT"
564 + html_line "Fichiers config Portainer" "$PORTAINER_FILES" "📁" "info"
565 + [ -n "$PORTAINER_CONFIG_SIZE" ] && html_line "Taille config Portainer" "$PORTAINER_CONFIG_SIZE" "📏" "info"
566 +
567 + echo "<h2>📊 Containers / Tailles (dossiers dans $SOURCE_DIR)</h2>" >> "$HTML_REPORT"
568 + html_container_table
569 +
570 + cat >> "$HTML_REPORT" <<EOF
571 + <div class="footer">
572 + ✅ Rapport généré automatiquement par le script de backup.<br>
573 + ⚠️ Ne partage pas ce rapport publiquement : il révèle des chemins et des infos de structure.
574 + </div>
575 + </div>
576 + </body>
577 + </html>
578 + EOF
579 +
580 + log_message "Rapport HTML généré : $HTML_REPORT"
581 +
582 + ##################
583 +
584 +
299 585 ##############################################
300 - # 6) RÉSUMÉS
586 + # 8) MAJ last/ (SANS copier les archives .gz)
301 587 ##############################################
302 588
303 - echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
304 - echo -e "${CYAN}Dossier backup courant : ${YELLOW}$RUN_DIR${NC}"
589 + log_message "Mise à jour du dossier LAST : $LAST_DIR"
590 +
591 + rm -rf "$LAST_DIR"
592 + mkdir -p "$LAST_DIR"
593 +
594 + # HTML
595 + cp -f "$HTML_REPORT" "$LAST_DIR/report.html"
596 +
597 + # Compose / configs (pas d'archives)
598 + [ -d "$CONFIG_DIR/Compose" ] && cp -a "$CONFIG_DIR/Compose" "$LAST_DIR/"
599 + [ -d "$CONFIG_DIR/portainer" ] && cp -a "$CONFIG_DIR/portainer" "$LAST_DIR/"
600 + [ "$CASAOS_PRESENT" = "1" ] && [ -d "$CONFIG_DIR/casaos" ] && cp -a "$CONFIG_DIR/casaos" "$LAST_DIR/"
601 +
602 + # Index HTML last/
603 + generate_index_html "$BACKUP_DIR" "$HTML_INDEX_LAST"
604 +
605 + log_message "LAST mis à jour ✅"
606 + log_message "Dernier rapport HTML : $HTML_REPORT_LAST"
607 + log_message "Index HTML last : $HTML_INDEX_LAST"
608 +
609 + ##############################################
610 + # 9) Publication WEB (HTML UNIQUEMENT)
611 + ##############################################
612 +
613 + log_message "Publication web (HTML only) vers : $WEB_PUBLIC_DIR"
614 +
615 + rm -rf "$WEB_PUBLIC_DIR"
616 + mkdir -p "$WEB_PUBLIC_DIR"
617 +
618 +
619 + cp -f "$LAST_DIR/report.html" "$WEB_PUBLIC_DIR/report.html"
620 + cp -f "$LAST_DIR/index.html" "$WEB_PUBLIC_DIR/" 2>/dev/null || true
621 +
622 + log_message "Publication web OK ✅"
623 +
624 + ##############################################
625 + # 10) Rapport CONSOLE
626 + ##############################################
627 +
628 + echo -e "${GREEN}===== BACKUP TERMINÉ ✅ =====${NC}"
305 629
306 630 ##############################################
307 631 # LISTE DES DOSSIERS DOCKER PAR TAILLE (ASCII)
308 632 ##############################################
309 633
310 - echo -e "\n${CYAN}----- LISTE/TAILLE DES RÉPERTOIRES DOCKER -----${NC}"
634 + echo ""
635 + echo -e "${CYAN}----- LISTE/TAILLE DES RÉPERTOIRES DOCKER -----${NC}"
311 636
312 637 DOCKER_DIRS=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
313 638 ! -path "$SOURCE_DIR/casaos_data" \
314 639 ! -path "$SOURCE_DIR/docker_var_lib" \
315 - ! -path "$SOURCE_DIR/portainer" 2>/dev/null)
640 + ! -path "$SOURCE_DIR/portainer" \
641 + 2>/dev/null)
316 642
317 643 if [ -z "$DOCKER_DIRS" ]; then
318 644 echo -e "${YELLOW}(Aucun dossier Docker trouvé)${NC}"
319 645 else
320 - echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────┐"
321 - printf "│ %-24s │ %-7s │ %-38s │\n" "Container" "Taille" "Chemin"
322 - echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────┤"
646 + echo -e "${CYAN}┌──────────────────────────┬─────────┬────────────────────────────────────────┐${NC}"
647 + printf "${CYAN}│ %-24s │ %-7s │ %-38s │${NC}\n" "Container" "Taille" "Chemin"
648 + echo -e "${CYAN}├──────────────────────────┼─────────┼────────────────────────────────────────┤${NC}"
649 +
650 + # du + tri par taille desc
323 651 du -sh $DOCKER_DIRS 2>/dev/null | sort -hr | while read -r size path; do
324 652 name=$(basename "$path")
325 653 printf "│ %-24s │ %-7s │ %-38s │\n" "$name" "$size" "$path"
326 654 done
327 - echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────┘"
328 - fi
329 655
330 - #################################
331 - # DOCKER
332 - #################################
333 - echo -e "${CYAN}\n----- DOCKER -----${NC}"
334 - echo -e "${CYAN}Containers Docker détectés : ${GREEN}$CONTAINERS_DOCKER${NC}"
335 - echo -e "${CYAN}Compose source (Docker) : ${GREEN}$SOURCE_COMPOSE_COUNT${NC}"
336 - echo -e "${CYAN}Compose backup (Docker) : ${GREEN}$DOCKER_COMPOSE_BACKUP${NC}"
337 - echo -e "${CYAN}Dossier compose Docker : ${YELLOW}$CONFIG_DIR/docker${NC}"
338 - echo -e "${CYAN}Taille compose Docker : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"
339 -
340 - #################################
341 - # CASAOS (si présent)
342 - #################################
343 - if [ -d "$CONFIG_DIR/casaos" ] || [ -f "$CASAOS_FULL_TAR" ]; then
344 - echo -e "${CYAN}\n----- CASAOS -----${NC}"
345 - echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
346 - echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
347 - [ -n "$CASAOS_CONFIG_SIZE" ] && echo -e "${CYAN}Taille config CasaOS (full) : ${GREEN}$CASAOS_CONFIG_SIZE${NC}"
348 - if [ -f "$CASAOS_FULL_TAR" ]; then
349 - echo -e "${CYAN}Tar CasaOS FULL : ${YELLOW}$CASAOS_FULL_TAR${NC}"
350 - echo -e "${CYAN}Taille tar CasaOS FULL : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
351 - fi
656 + echo -e "${CYAN}└──────────────────────────┴─────────┴────────────────────────────────────────┘${NC}"
352 657 fi
353 658
354 - #################################
355 - # PORTAINER (si présent)
356 - #################################
357 - if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
358 - echo -e "${CYAN}\n----- PORTAINER -----${NC}"
359 - echo -e "${CYAN}Fichiers config Portainer : ${GREEN}$PORTAINER_FILES${NC}"
360 - echo -e "${CYAN}Dossier Portainer backup : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"
361 - [ -n "$PORTAINER_CONFIG_SIZE" ] && echo -e "${CYAN}Taille Portainer (full) : ${GREEN}$PORTAINER_CONFIG_SIZE${NC}"
659 + ##############################################
660 +
661 + echo -e "${CYAN}Dossier backup courant : ${YELLOW}$RUN_DIR${NC}"
662 + echo ""
663 +
664 + echo -e "${CYAN}----- DOCKER -----${NC}"
665 + echo "Containers Docker détectés : $CONTAINERS_DOCKER"
666 + echo "Compose source (Docker) : $SOURCE_COMPOSE_COUNT"
667 + echo "Compose backup (Docker) : $DOCKER_COMPOSE_BACKUP"
668 + echo "Archive Docker (run) : $BACKUP_FILE ($TAR_SIZE)"
669 + echo ""
670 +
671 + echo -e "${CYAN}----- CASAOS -----${NC}"
672 + if [ "$CASAOS_PRESENT" = "1" ]; then
673 + echo "CasaOS détecté : OUI"
674 + echo "Compose CasaOS backup : $CASAOS_COMPOSE_BACKUP"
675 + [ -f "$CASAOS_FULL_TAR" ] && echo "Archive CasaOS FULL (run) : $CASAOS_FULL_TAR ($CASAOS_FULL_TAR_SIZE)"
676 + else
677 + echo "CasaOS détecté : NON (ignoré)"
362 678 fi
679 + echo ""
680 +
681 + echo -e "${CYAN}----- PORTAINER -----${NC}"
682 + echo "Fichiers config Portainer : $PORTAINER_FILES"
683 + [ -n "$PORTAINER_CONFIG_SIZE" ] && echo "Taille Portainer (run) : $PORTAINER_CONFIG_SIZE"
684 + echo ""
685 +
686 + echo -e "${CYAN}----- GLOBAL -----${NC}"
687 + echo "Sets de backup : $TOTAL_BACKUP_SETS"
688 + echo "Oldest backup : ${OLDEST_DIR:-N/A}"
689 + echo "Newest backup : ${NEWEST_DIR:-N/A}"
690 + echo "Durée totale : $DURATION"
691 + echo ""
692 + echo "HTML (run) : $HTML_REPORT"
693 + echo "HTML (last) : $HTML_REPORT_LAST"
694 + echo "WEB index : $WEB_PUBLIC_DIR/index.html"
695 + echo "WEB report : $WEB_PUBLIC_DIR/report.html"
696 +
697 + ##############################################
698 + # JSON optionnel
699 + ##############################################
363 700
364 - #################################
365 - # GLOBAL
366 - #################################
367 - echo -e "${CYAN}\n----- GLOBAL -----${NC}"
368 - echo -e "${CYAN}Nombre de sets de backup : ${GREEN}$TOTAL_BACKUP_SETS${NC}"
369 - echo -e "${CYAN}Oldest backup dir : ${YELLOW}${OLDEST_DIR:-N/A}${NC}"
370 - echo -e "${CYAN}Newest backup dir : ${YELLOW}${NEWEST_DIR:-N/A}${NC}"
371 - echo -e "${CYAN}Taille archive Docker tar.gz : ${GREEN}$TAR_SIZE${NC}"
372 - [ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Taille archive CasaOS tar.gz : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
373 - echo -e "${CYAN}Taille dossier backup courant: ${GREEN}$CONFIG_SIZE${NC}"
374 - echo -e "${CYAN}Archive Docker courante : ${YELLOW}$BACKUP_FILE${NC}"
375 - [ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Archive CasaOS courante : ${YELLOW}$CASAOS_FULL_TAR${NC}"
376 - echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
377 -
378 - #################################
379 - # JSON (optionnel : ./script.sh --json)
380 - #################################
381 701 if [ "$1" = "--json" ]; then
382 702 echo ""
383 703 echo "{"
384 704 echo " \"date_raw\": \"$DATE_RAW\","
385 705 echo " \"date_dir\": \"$DATE_DIR\","
386 706 echo " \"run_dir\": \"$RUN_DIR\","
707 + echo " \"last_dir\": \"$LAST_DIR\","
387 708 echo " \"docker_backup_file\": \"$BACKUP_FILE\","
388 709 echo " \"docker_backup_size\": \"$TAR_SIZE\","
710 + echo " \"casaos_present\": $CASAOS_PRESENT,"
389 711 echo " \"casaos_full_backup_file\": \"${CASAOS_FULL_TAR:-}\","
390 712 echo " \"casaos_full_backup_size\": \"${CASAOS_FULL_TAR_SIZE:-}\","
391 - echo " \"docker\": {"
392 - echo " \"containers\": $CONTAINERS_DOCKER,"
393 - echo " \"compose_source\": $SOURCE_COMPOSE_COUNT,"
394 - echo " \"compose_backup\": $DOCKER_COMPOSE_BACKUP"
395 - echo " },"
396 - echo " \"casaos\": {"
397 - echo " \"compose_backup\": $CASAOS_COMPOSE_BACKUP"
398 - echo " },"
399 - echo " \"portainer\": {"
400 - echo " \"files\": $PORTAINER_FILES"
401 - echo " },"
713 + echo " \"portainer_files\": $PORTAINER_FILES,"
402 714 echo " \"backup_sets\": $TOTAL_BACKUP_SETS,"
403 - echo " \"oldest_backup_dir\": \"${OLDEST_DIR:-}\","
404 - echo " \"newest_backup_dir\": \"${NEWEST_DIR:-}\","
405 - echo " \"duration\": \"$DURATION\""
715 + echo " \"duration\": \"$DURATION\","
716 + echo " \"html_report_run\": \"$HTML_REPORT\","
717 + echo " \"html_report_last\": \"$HTML_REPORT_LAST\","
718 + echo " \"web_index\": \"$WEB_PUBLIC_DIR/index.html\","
719 + echo " \"web_report\": \"$WEB_PUBLIC_DIR/report.html\""
406 720 echo "}"
407 721 fi

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 4 insertions

Backup-Home-docker.tar.gz.sh

@@ -4,6 +4,10 @@
4 4 # CONFIG
5 5 #############################
6 6
7 + # Backup complet des data docker , casaos et portainer
8 + # avec liste de tous les compose files des containers classés par répertoire.
9 +
10 +
7 11 # Répertoire contenant tes containers
8 12 SOURCE_DIR="/home/docker"
9 13

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

Sem alterações

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 1 insertion, 1 deletion

Backup-Home-docker.tar.gz.sh

@@ -185,7 +185,7 @@ find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
185 185 ! -path "$SOURCE_DIR/docker_var_lib/*" \
186 186 2>/dev/null | while read file; do
187 187 container_name=$(basename "$(dirname "$file")")
188 - dest_dir="$CONFIG_DIR/docker/$container_name"
188 + dest_dir="$CONFIG_DIR/Compose/$container_name"
189 189 mkdir -p "$dest_dir"
190 190 cp "$file" "$dest_dir/"
191 191 log_message " [Docker] → Compose trouvé : $file"

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

Sem alterações

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

Sem alterações

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 49 insertions, 85 deletions

Backup-Home-docker.tar.gz.sh

@@ -10,22 +10,25 @@ SOURCE_DIR="/home/docker"
10 10 # Répertoire où stocker les sauvegardes
11 11 BACKUP_DIR="/home/backup/docker"
12 12
13 - # Nombre max de backups à conserver
14 - MAX_BACKUPS=5
13 + # Nombre max de backups à conserver (dossiers datés)
14 + MAX_BACKUPS=3
15 15
16 - # Date format
17 - DATE="$(date +'%Y%m%d_%H%M%S')"
16 + # Date interne (pour logs / JSON)
17 + DATE_RAW="$(date +'%Y%m%d_%H%M%S')"
18 + # Date pour le dossier de backup (format humain demandé)
19 + DATE_DIR="$(date +'%Y.%m.%d_%H-%M-%S')"
18 20
19 - # Fichier TAR final Docker
20 - BACKUP_FILE="$BACKUP_DIR/docker_backup_${DATE}.tar.gz"
21 + # Dossier de ce backup
22 + RUN_DIR="$BACKUP_DIR/$DATE_DIR"
21 23
22 - # Fichier TAR FULL CasaOS (config + volumes)
23 - CASAOS_FULL_TAR="$BACKUP_DIR/casaos_full_backup_${DATE}.tar.gz"
24 + # Fichiers TAR dans le dossier de ce backup
25 + BACKUP_FILE="$RUN_DIR/docker_backup.tar.gz"
26 + CASAOS_FULL_TAR="$RUN_DIR/casaos_full_backup.tar.gz"
24 27
25 - # Dossier de configs des compose à côté du TAR
26 - CONFIG_DIR="$BACKUP_DIR/config_${DATE}"
28 + # Dossier où l'on met les compose / configs
29 + CONFIG_DIR="$RUN_DIR"
27 30
28 - # Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
31 + # Dossiers à exclure (chemins relatifs à $SOURCE_DIR pour le tar Docker)
29 32 EXCLUDE_DIRS=(
30 33 "docker_var_lib"
31 34 "1_Backups"
@@ -83,46 +86,20 @@ check_pigz() {
83 86 }
84 87
85 88 rotate_backups() {
86 - log_message "Nettoyage des anciens backups (conserver les $MAX_BACKUPS plus récents)..."
87 -
88 - # TAR Docker
89 - mapfile -t backups_tar < <(ls -1t "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null || true)
90 - if [ "${#backups_tar[@]}" -gt "$MAX_BACKUPS" ]; then
91 - for f in "${backups_tar[@]:$MAX_BACKUPS}"; do
92 - log_message "Suppression ancien backup tar Docker : $f"
93 - rm -f "$f"
94 - done
95 - fi
89 + log_message "Rotation des anciens backups (conserver les $MAX_BACKUPS plus récents)..."
96 90
97 - # TAR CasaOS full
98 - mapfile -t backups_casaos < <(ls -1t "$BACKUP_DIR"/casaos_full_backup_*.tar.gz 2>/dev/null || true)
99 - if [ "${#backups_casaos[@]}" -gt "$MAX_BACKUPS" ]; then
100 - for f in "${backups_casaos[@]:$MAX_BACKUPS}"; do
101 - log_message "Suppression ancien backup tar CasaOS : $f"
102 - rm -f "$f"
103 - done
104 - fi
91 + # On ne garde que les dossiers datés dans BACKUP_DIR
92 + mapfile -t backups_dirs < <(ls -1td "$BACKUP_DIR"/*/ 2>/dev/null || true)
105 93
106 - # Dossiers config_
107 - mapfile -t backups_cfg < <(ls -1td "$BACKUP_DIR"/config_* 2>/dev/null || true)
108 - if [ "${#backups_cfg[@]}" -gt "$MAX_BACKUPS" ]; then
109 - for d in "${backups_cfg[@]:$MAX_BACKUPS}"; do
110 - log_message "Suppression ancien dossier config : $d"
94 + if [ "${#backups_dirs[@]}" -gt "$MAX_BACKUPS" ]; then
95 + for d in "${backups_dirs[@]:$MAX_BACKUPS}"; do
96 + log_message "Suppression ancien backup (dossier) : $d"
111 97 rm -rf "$d"
112 98 done
113 99 fi
114 100 }
115 101
116 - human_date() {
117 - # Convertit 20251203_172811 → "03/12/2025 17:28:11"
118 - local d="$1"
119 - local date_part="${d:0:8}"
120 - local time_part="${d:9:6}"
121 - echo "${date_part:6:2}/${date_part:4:2}/${date_part:0:4} ${time_part:0:2}:${time_part:2:2}:${time_part:4:2}"
122 - }
123 -
124 102 get_size() {
125 - # Taille lisible
126 103 du -sh "$1" 2>/dev/null | awk '{print $1}'
127 104 }
128 105
@@ -134,18 +111,18 @@ SECONDS=0
134 111
135 112 check_pigz
136 113
137 - mkdir -p "$BACKUP_DIR" "$CONFIG_DIR"
114 + mkdir -p "$RUN_DIR"
138 115 touch "$LOG_FILE"
139 116
140 117 echo -e "${CYAN}=== Backup Docker + Configs (Portainer / CasaOS) ===${NC}"
141 118 log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."
119 + log_message "Dossier de backup : $RUN_DIR"
142 120
143 121 ##############################################
144 122 # 1) Sauvegarde TAR Docker via pigz + exclusions
145 123 ##############################################
146 124 log_message "Création de l’archive Docker : $BACKUP_FILE"
147 125
148 - # Construction des arguments d'exclusion dynamiques pour le TAR Docker
149 126 EXCLUDE_ARGS=(
150 127 "--exclude=*.log"
151 128 "--exclude=.composer"
@@ -187,8 +164,8 @@ fi
187 164
188 165 ##############################################
189 166 # 2) Extraction des docker-compose
190 - # - CasaOS: config_<date>/casaos/<container>/
191 - # - Docker: config_<date>/docker/<container>/
167 + # - CasaOS: RUN_DIR/casaos/<container>/
168 + # - Docker: RUN_DIR/docker/<container>/
192 169 ##############################################
193 170
194 171 log_message "Extraction des docker-compose CasaOS..."
@@ -217,7 +194,7 @@ find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
217 194 ##############################################
218 195 # 3) Config Portainer (full)
219 196 ##############################################
220 - PORTAINER_CONFIG_DIR="$CONFIG_DIR/portainer/full_config"
197 + PORTAINER_CONFIG_DIR="$CONFIG_DIR/portainer"
221 198 PORTAINER_FILES=0
222 199
223 200 if docker volume inspect portainer_data >/dev/null 2>&1; then
@@ -230,7 +207,7 @@ else
230 207 fi
231 208
232 209 ##############################################
233 - # 4) Config CasaOS (full + second tar.gz)
210 + # 4) Config CasaOS (full + tar.gz)
234 211 ##############################################
235 212 CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"
236 213
@@ -260,10 +237,9 @@ fi
260 237 # 5) Comptages finaux (sur le backup courant)
261 238 ##############################################
262 239
263 - # Compose dans le backup (docker + casaos compose seulement)
240 + # Compose dans le backup (docker + CasaOS compose seulement)
264 241 CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "docker-compose.y*ml" ! -path "$CASAOS_CONFIG_DIR/*" 2>/dev/null | wc -l)
265 242 DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/docker" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
266 - TOTAL_COMPOSE_BACKUP=$((CASAOS_COMPOSE_BACKUP + DOCKER_COMPOSE_BACKUP))
267 243
268 244 # Compose dans le dossier source (uniquement /home/docker/<container>/docker-compose.*)
269 245 SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
@@ -277,28 +253,25 @@ CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
277 253 ! -path "$SOURCE_DIR/docker_var_lib" \
278 254 ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)
279 255
280 - # Rotation des anciens backups (Docker tar + CasaOS tar + configs)
256 + # Rotation des anciens backups (par dossiers)
281 257 rotate_backups
282 258
283 - # Nombre total de tar.gz Docker
284 - TOTAL_TAR_DOCKER=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | wc -l)
285 - # Nombre total de tar.gz CasaOS full
286 - TOTAL_TAR_CASAOS=$(ls -1 "$BACKUP_DIR"/casaos_full_backup_*.tar.gz 2>/dev/null | wc -l)
259 + # Nombre total de sets de backup (dossiers datés)
260 + TOTAL_BACKUP_SETS=$(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | wc -l)
287 261
288 - # Oldest / newest Docker après rotation
289 - OLDEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | head -n1)
290 - NEWEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | tail -n1)
262 + # Oldest / newest backup set
263 + mapfile -t CURRENT_SETS < <(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | sort)
264 + OLDEST_DIR="${CURRENT_SETS[0]}"
265 + NEWEST_DIR="${CURRENT_SETS[${#CURRENT_SETS[@]}-1]}"
291 266
292 267 DURATION="$(format_time $SECONDS)"
293 268
294 - # Tailles des backups
269 + # Tailles des backups courants
295 270 TAR_SIZE=$(get_size "$BACKUP_FILE")
296 271 CONFIG_SIZE=$(get_size "$CONFIG_DIR")
297 -
298 - # Docker compose directory size
299 272 DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")
300 273
301 - # CasaOS full config size (copie dans config_)
274 + # CasaOS full config size (copie dans RUN_DIR/casaos/full_config)
302 275 if [ -d "$CASAOS_CONFIG_DIR" ]; then
303 276 CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
304 277 else
@@ -319,15 +292,12 @@ else
319 292 PORTAINER_CONFIG_SIZE=""
320 293 fi
321 294
322 - # Dates humaines
323 - HUMAN_OLDEST=$( [ -n "$OLDEST_BACKUP" ] && human_date "$(basename "$OLDEST_BACKUP" | sed 's/docker_backup_//; s/.tar.gz//')" )
324 - HUMAN_NEWEST=$( [ -n "$NEWEST_BACKUP" ] && human_date "$(basename "$NEWEST_BACKUP" | sed 's/docker_backup_//; s/.tar.gz//')" )
325 -
326 295 ##############################################
327 296 # 6) RÉSUMÉS
328 297 ##############################################
329 298
330 299 echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
300 + echo -e "${CYAN}Dossier backup courant : ${YELLOW}$RUN_DIR${NC}"
331 301
332 302 ##############################################
333 303 # LISTE DES DOSSIERS DOCKER PAR TAILLE (ASCII)
@@ -366,7 +336,7 @@ echo -e "${CYAN}Taille compose Docker : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"
366 336 #################################
367 337 # CASAOS (si présent)
368 338 #################################
369 - if [ -d "$CASAOS_CONFIG_DIR" ] || [ "$CASAOS_COMPOSE_BACKUP" -gt 0 ] || [ -f "$CASAOS_FULL_TAR" ]; then
339 + if [ -d "$CONFIG_DIR/casaos" ] || [ -f "$CASAOS_FULL_TAR" ]; then
370 340 echo -e "${CYAN}\n----- CASAOS -----${NC}"
371 341 echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
372 342 echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
@@ -391,17 +361,14 @@ fi
391 361 # GLOBAL
392 362 #################################
393 363 echo -e "${CYAN}\n----- GLOBAL -----${NC}"
364 + echo -e "${CYAN}Nombre de sets de backup : ${GREEN}$TOTAL_BACKUP_SETS${NC}"
365 + echo -e "${CYAN}Oldest backup dir : ${YELLOW}${OLDEST_DIR:-N/A}${NC}"
366 + echo -e "${CYAN}Newest backup dir : ${YELLOW}${NEWEST_DIR:-N/A}${NC}"
394 367 echo -e "${CYAN}Taille archive Docker tar.gz : ${GREEN}$TAR_SIZE${NC}"
395 368 [ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Taille archive CasaOS tar.gz : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
396 - echo -e "${CYAN}Taille dossier config : ${GREEN}$CONFIG_SIZE${NC}"
397 - echo -e "${CYAN}Nombre tar Docker : ${GREEN}$TOTAL_TAR_DOCKER${NC}"
398 - echo -e "${CYAN}Nombre tar CasaOS : ${GREEN}$TOTAL_TAR_CASAOS${NC}"
399 - echo -e "${CYAN}Oldest backup Docker : ${YELLOW}$OLDEST_BACKUP${NC}"
400 - echo -e "${CYAN}Oldest backup (human) : ${GREEN}${HUMAN_OLDEST:-N/A}${NC}"
401 - echo -e "${CYAN}Newest backup Docker : ${YELLOW}$NEWEST_BACKUP${NC}"
402 - echo -e "${CYAN}Newest backup (human) : ${GREEN}${HUMAN_NEWEST:-N/A}${NC}"
369 + echo -e "${CYAN}Taille dossier backup courant: ${GREEN}$CONFIG_SIZE${NC}"
403 370 echo -e "${CYAN}Archive Docker courante : ${YELLOW}$BACKUP_FILE${NC}"
404 - echo -e "${CYAN}Dossier config courant : ${YELLOW}$CONFIG_DIR${NC}"
371 + [ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Archive CasaOS courante : ${YELLOW}$CASAOS_FULL_TAR${NC}"
405 372 echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
406 373
407 374 #################################
@@ -410,13 +377,13 @@ echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
410 377 if [ "$1" = "--json" ]; then
411 378 echo ""
412 379 echo "{"
413 - echo " \"date\": \"$DATE\","
380 + echo " \"date_raw\": \"$DATE_RAW\","
381 + echo " \"date_dir\": \"$DATE_DIR\","
382 + echo " \"run_dir\": \"$RUN_DIR\","
414 383 echo " \"docker_backup_file\": \"$BACKUP_FILE\","
415 384 echo " \"docker_backup_size\": \"$TAR_SIZE\","
416 385 echo " \"casaos_full_backup_file\": \"${CASAOS_FULL_TAR:-}\","
417 386 echo " \"casaos_full_backup_size\": \"${CASAOS_FULL_TAR_SIZE:-}\","
418 - echo " \"config_dir\": \"$CONFIG_DIR\","
419 - echo " \"config_size\": \"$CONFIG_SIZE\","
420 387 echo " \"docker\": {"
421 388 echo " \"containers\": $CONTAINERS_DOCKER,"
422 389 echo " \"compose_source\": $SOURCE_COMPOSE_COUNT,"
@@ -428,12 +395,9 @@ if [ "$1" = "--json" ]; then
428 395 echo " \"portainer\": {"
429 396 echo " \"files\": $PORTAINER_FILES"
430 397 echo " },"
431 - echo " \"tar_docker_count\": $TOTAL_TAR_DOCKER,"
432 - echo " \"tar_casaos_count\": $TOTAL_TAR_CASAOS,"
433 - echo " \"oldest_backup_docker\": \"$OLDEST_BACKUP\","
434 - echo " \"oldest_backup_docker_human\": \"${HUMAN_OLDEST:-N/A}\","
435 - echo " \"newest_backup_docker\": \"$NEWEST_BACKUP\","
436 - echo " \"newest_backup_docker_human\": \"${HUMAN_NEWEST:-N/A}\","
398 + echo " \"backup_sets\": $TOTAL_BACKUP_SETS,"
399 + echo " \"oldest_backup_dir\": \"${OLDEST_DIR:-}\","
400 + echo " \"newest_backup_dir\": \"${NEWEST_DIR:-}\","
437 401 echo " \"duration\": \"$DURATION\""
438 402 echo "}"
439 403 fi

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 77 insertions, 32 deletions

Backup-Home-docker.tar.gz.sh

@@ -16,16 +16,19 @@ MAX_BACKUPS=5
16 16 # Date format
17 17 DATE="$(date +'%Y%m%d_%H%M%S')"
18 18
19 - # Fichier TAR final
19 + # Fichier TAR final Docker
20 20 BACKUP_FILE="$BACKUP_DIR/docker_backup_${DATE}.tar.gz"
21 21
22 + # Fichier TAR FULL CasaOS (config + volumes)
23 + CASAOS_FULL_TAR="$BACKUP_DIR/casaos_full_backup_${DATE}.tar.gz"
24 +
22 25 # Dossier de configs des compose à côté du TAR
23 26 CONFIG_DIR="$BACKUP_DIR/config_${DATE}"
24 27
25 28 # Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
26 29 EXCLUDE_DIRS=(
27 30 "docker_var_lib"
28 - "1_Backups"
31 + "1_Backups"
29 32 "casaos_data/*"
30 33 "nginx_proxy/data/logs/*"
31 34 "yt-dl/video/*"
@@ -82,11 +85,20 @@ check_pigz() {
82 85 rotate_backups() {
83 86 log_message "Nettoyage des anciens backups (conserver les $MAX_BACKUPS plus récents)..."
84 87
85 - # TAR
88 + # TAR Docker
86 89 mapfile -t backups_tar < <(ls -1t "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null || true)
87 90 if [ "${#backups_tar[@]}" -gt "$MAX_BACKUPS" ]; then
88 91 for f in "${backups_tar[@]:$MAX_BACKUPS}"; do
89 - log_message "Suppression ancien backup tar : $f"
92 + log_message "Suppression ancien backup tar Docker : $f"
93 + rm -f "$f"
94 + done
95 + fi
96 +
97 + # TAR CasaOS full
98 + mapfile -t backups_casaos < <(ls -1t "$BACKUP_DIR"/casaos_full_backup_*.tar.gz 2>/dev/null || true)
99 + if [ "${#backups_casaos[@]}" -gt "$MAX_BACKUPS" ]; then
100 + for f in "${backups_casaos[@]:$MAX_BACKUPS}"; do
101 + log_message "Suppression ancien backup tar CasaOS : $f"
90 102 rm -f "$f"
91 103 done
92 104 fi
@@ -129,11 +141,11 @@ echo -e "${CYAN}=== Backup Docker + Configs (Portainer / CasaOS) ===${NC}"
129 141 log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."
130 142
131 143 ##############################################
132 - # 1) Sauvegarde TAR via pigz + exclusions
144 + # 1) Sauvegarde TAR Docker via pigz + exclusions
133 145 ##############################################
134 - log_message "Création de l’archive : $BACKUP_FILE"
146 + log_message "Création de l’archive Docker : $BACKUP_FILE"
135 147
136 - # Construction des arguments d'exclusion dynamiques pour le TAR
148 + # Construction des arguments d'exclusion dynamiques pour le TAR Docker
137 149 EXCLUDE_ARGS=(
138 150 "--exclude=*.log"
139 151 "--exclude=.composer"
@@ -168,8 +180,8 @@ tar -cf "$BACKUP_FILE" -I pigz \
168 180 . 2>> "$LOG_FILE"
169 181
170 182 if [ $? -ne 0 ]; then
171 - log_message "ERREUR lors de la création du tar."
172 - echo -e "${RED}Erreur lors de la création de l’archive.${NC}"
183 + log_message "ERREUR lors de la création du tar Docker."
184 + echo -e "${RED}Erreur lors de la création de l’archive Docker.${NC}"
173 185 exit 1
174 186 fi
175 187
@@ -194,7 +206,7 @@ log_message "Extraction des docker-compose Docker (hors casaos_data & dossiers e
194 206 find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
195 207 ! -path "$SOURCE_DIR/casaos_data/*" \
196 208 ! -path "$SOURCE_DIR/docker_var_lib/*" \
197 - | while read file; do
209 + 2>/dev/null | while read file; do
198 210 container_name=$(basename "$(dirname "$file")")
199 211 dest_dir="$CONFIG_DIR/docker/$container_name"
200 212 mkdir -p "$dest_dir"
@@ -218,17 +230,32 @@ else
218 230 fi
219 231
220 232 ##############################################
221 - # 4) Config CasaOS (full)
233 + # 4) Config CasaOS (full + second tar.gz)
222 234 ##############################################
223 235 CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"
224 - CASAOS_FILES=0
225 236
226 237 if [ -d "/var/lib/casaos" ]; then
227 - log_message "Sauvegarde config CasaOS (full)..."
238 + log_message "Sauvegarde config CasaOS (full vers $CASAOS_CONFIG_DIR)..."
228 239 mkdir -p "$CASAOS_CONFIG_DIR"
229 240 cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
230 241 fi
231 242
243 + # Création du second tar.gz CasaOS FULL (config + volumes casaos_data)
244 + if [ -d "/var/lib/casaos" ] || [ -d "$SOURCE_DIR/casaos_data" ]; then
245 + CASAOS_TAR_SOURCES=()
246 + [ -d "/var/lib/casaos" ] && CASAOS_TAR_SOURCES+=( "/var/lib/casaos" )
247 + [ -d "$SOURCE_DIR/casaos_data" ] && CASAOS_TAR_SOURCES+=( "$SOURCE_DIR/casaos_data" )
248 +
249 + if [ "${#CASAOS_TAR_SOURCES[@]}" -gt 0 ]; then
250 + log_message "Création de l’archive CASAOS FULL : $CASAOS_FULL_TAR"
251 + tar -cf "$CASAOS_FULL_TAR" -I pigz "${CASAOS_TAR_SOURCES[@]}" 2>>"$LOG_FILE"
252 + if [ $? -ne 0 ]; then
253 + log_message "ERREUR lors de la création du tar CasaOS."
254 + echo -e "${RED}Erreur lors de la création de l’archive CasaOS.${NC}"
255 + fi
256 + fi
257 + fi
258 +
232 259 ##############################################
233 260 # 5) Comptages finaux (sur le backup courant)
234 261 ##############################################
@@ -244,19 +271,21 @@ SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name
244 271 ! -path "$SOURCE_DIR/docker_var_lib/*" \
245 272 2>/dev/null | wc -l)
246 273
247 - # Containers Docker "valides" (dossiers de premier niveau, hors exclusions évidentes)
274 + # Containers Docker "valides"
248 275 CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
249 276 ! -path "$SOURCE_DIR/casaos_data" \
250 277 ! -path "$SOURCE_DIR/docker_var_lib" \
251 278 ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)
252 279
253 - # Rotation des anciens backups
280 + # Rotation des anciens backups (Docker tar + CasaOS tar + configs)
254 281 rotate_backups
255 282
256 - # Nombre total de tar.gz
257 - TOTAL_TAR=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | wc -l)
283 + # Nombre total de tar.gz Docker
284 + TOTAL_TAR_DOCKER=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | wc -l)
285 + # Nombre total de tar.gz CasaOS full
286 + TOTAL_TAR_CASAOS=$(ls -1 "$BACKUP_DIR"/casaos_full_backup_*.tar.gz 2>/dev/null | wc -l)
258 287
259 - # Oldest / newest après rotation
288 + # Oldest / newest Docker après rotation
260 289 OLDEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | head -n1)
261 290 NEWEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | tail -n1)
262 291
@@ -269,13 +298,20 @@ CONFIG_SIZE=$(get_size "$CONFIG_DIR")
269 298 # Docker compose directory size
270 299 DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")
271 300
272 - # CasaOS full config size
301 + # CasaOS full config size (copie dans config_)
273 302 if [ -d "$CASAOS_CONFIG_DIR" ]; then
274 303 CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
275 304 else
276 305 CASAOS_CONFIG_SIZE=""
277 306 fi
278 307
308 + # CasaOS FULL TAR size
309 + if [ -f "$CASAOS_FULL_TAR" ]; then
310 + CASAOS_FULL_TAR_SIZE=$(get_size "$CASAOS_FULL_TAR")
311 + else
312 + CASAOS_FULL_TAR_SIZE=""
313 + fi
314 +
279 315 # Portainer full config size
280 316 if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
281 317 PORTAINER_CONFIG_SIZE=$(get_size "$PORTAINER_CONFIG_DIR")
@@ -330,11 +366,15 @@ echo -e "${CYAN}Taille compose Docker : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"
330 366 #################################
331 367 # CASAOS (si présent)
332 368 #################################
333 - if [ -d "$CASAOS_CONFIG_DIR" ] || [ "$CASAOS_COMPOSE_BACKUP" -gt 0 ]; then
369 + if [ -d "$CASAOS_CONFIG_DIR" ] || [ "$CASAOS_COMPOSE_BACKUP" -gt 0 ] || [ -f "$CASAOS_FULL_TAR" ]; then
334 370 echo -e "${CYAN}\n----- CASAOS -----${NC}"
335 371 echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
336 372 echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
337 373 [ -n "$CASAOS_CONFIG_SIZE" ] && echo -e "${CYAN}Taille config CasaOS (full) : ${GREEN}$CASAOS_CONFIG_SIZE${NC}"
374 + if [ -f "$CASAOS_FULL_TAR" ]; then
375 + echo -e "${CYAN}Tar CasaOS FULL : ${YELLOW}$CASAOS_FULL_TAR${NC}"
376 + echo -e "${CYAN}Taille tar CasaOS FULL : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
377 + fi
338 378 fi
339 379
340 380 #################################
@@ -351,14 +391,16 @@ fi
351 391 # GLOBAL
352 392 #################################
353 393 echo -e "${CYAN}\n----- GLOBAL -----${NC}"
354 - echo -e "${CYAN}Taille archive tar.gz : ${GREEN}$TAR_SIZE${NC}"
394 + echo -e "${CYAN}Taille archive Docker tar.gz : ${GREEN}$TAR_SIZE${NC}"
395 + [ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Taille archive CasaOS tar.gz : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
355 396 echo -e "${CYAN}Taille dossier config : ${GREEN}$CONFIG_SIZE${NC}"
356 - echo -e "${CYAN}Nombre de .tar.gz : ${GREEN}$TOTAL_TAR${NC}"
357 - echo -e "${CYAN}Oldest backup : ${YELLOW}$OLDEST_BACKUP${NC}"
397 + echo -e "${CYAN}Nombre tar Docker : ${GREEN}$TOTAL_TAR_DOCKER${NC}"
398 + echo -e "${CYAN}Nombre tar CasaOS : ${GREEN}$TOTAL_TAR_CASAOS${NC}"
399 + echo -e "${CYAN}Oldest backup Docker : ${YELLOW}$OLDEST_BACKUP${NC}"
358 400 echo -e "${CYAN}Oldest backup (human) : ${GREEN}${HUMAN_OLDEST:-N/A}${NC}"
359 - echo -e "${CYAN}Newest backup : ${YELLOW}$NEWEST_BACKUP${NC}"
401 + echo -e "${CYAN}Newest backup Docker : ${YELLOW}$NEWEST_BACKUP${NC}"
360 402 echo -e "${CYAN}Newest backup (human) : ${GREEN}${HUMAN_NEWEST:-N/A}${NC}"
361 - echo -e "${CYAN}Archive courante : ${YELLOW}$BACKUP_FILE${NC}"
403 + echo -e "${CYAN}Archive Docker courante : ${YELLOW}$BACKUP_FILE${NC}"
362 404 echo -e "${CYAN}Dossier config courant : ${YELLOW}$CONFIG_DIR${NC}"
363 405 echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
364 406
@@ -369,8 +411,10 @@ if [ "$1" = "--json" ]; then
369 411 echo ""
370 412 echo "{"
371 413 echo " \"date\": \"$DATE\","
372 - echo " \"backup_file\": \"$BACKUP_FILE\","
373 - echo " \"backup_size\": \"$TAR_SIZE\","
414 + echo " \"docker_backup_file\": \"$BACKUP_FILE\","
415 + echo " \"docker_backup_size\": \"$TAR_SIZE\","
416 + echo " \"casaos_full_backup_file\": \"${CASAOS_FULL_TAR:-}\","
417 + echo " \"casaos_full_backup_size\": \"${CASAOS_FULL_TAR_SIZE:-}\","
374 418 echo " \"config_dir\": \"$CONFIG_DIR\","
375 419 echo " \"config_size\": \"$CONFIG_SIZE\","
376 420 echo " \"docker\": {"
@@ -384,11 +428,12 @@ if [ "$1" = "--json" ]; then
384 428 echo " \"portainer\": {"
385 429 echo " \"files\": $PORTAINER_FILES"
386 430 echo " },"
387 - echo " \"tar_count\": $TOTAL_TAR,"
388 - echo " \"oldest_backup\": \"$OLDEST_BACKUP\","
389 - echo " \"oldest_backup_human\": \"${HUMAN_OLDEST:-N/A}\","
390 - echo " \"newest_backup\": \"$NEWEST_BACKUP\","
391 - echo " \"newest_backup_human\": \"${HUMAN_NEWEST:-N/A}\","
431 + echo " \"tar_docker_count\": $TOTAL_TAR_DOCKER,"
432 + echo " \"tar_casaos_count\": $TOTAL_TAR_CASAOS,"
433 + echo " \"oldest_backup_docker\": \"$OLDEST_BACKUP\","
434 + echo " \"oldest_backup_docker_human\": \"${HUMAN_OLDEST:-N/A}\","
435 + echo " \"newest_backup_docker\": \"$NEWEST_BACKUP\","
436 + echo " \"newest_backup_docker_human\": \"${HUMAN_NEWEST:-N/A}\","
392 437 echo " \"duration\": \"$DURATION\""
393 438 echo "}"
394 439 fi

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 4 insertions, 3 deletions

Backup-Home-docker.tar.gz.sh

@@ -25,6 +25,7 @@ CONFIG_DIR="$BACKUP_DIR/config_${DATE}"
25 25 # Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
26 26 EXCLUDE_DIRS=(
27 27 "docker_var_lib"
28 + "1_Backups"
28 29 "casaos_data/*"
29 30 "nginx_proxy/data/logs/*"
30 31 "yt-dl/video/*"
@@ -306,14 +307,14 @@ DOCKER_DIRS=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
306 307 if [ -z "$DOCKER_DIRS" ]; then
307 308 echo -e "${YELLOW}(Aucun dossier Docker trouvé)${NC}"
308 309 else
309 - echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────────┐"
310 + echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────┐"
310 311 printf "│ %-24s │ %-7s │ %-38s │\n" "Container" "Taille" "Chemin"
311 - echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────────┤"
312 + echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────┤"
312 313 du -sh $DOCKER_DIRS 2>/dev/null | sort -hr | while read -r size path; do
313 314 name=$(basename "$path")
314 315 printf "│ %-24s │ %-7s │ %-38s │\n" "$name" "$size" "$path"
315 316 done
316 - echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────────┘"
317 + echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────┘"
317 318 fi
318 319
319 320 #################################

Erreur32's Avatar Erreur32 revisou este gist 6 months ago. Ir para a revisão

1 file changed, 154 insertions, 31 deletions

Backup-Home-docker.tar.gz.sh

@@ -24,6 +24,7 @@ CONFIG_DIR="$BACKUP_DIR/config_${DATE}"
24 24
25 25 # Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
26 26 EXCLUDE_DIRS=(
27 + "docker_var_lib"
27 28 "casaos_data/*"
28 29 "nginx_proxy/data/logs/*"
29 30 "yt-dl/video/*"
@@ -99,6 +100,19 @@ rotate_backups() {
99 100 fi
100 101 }
101 102
103 + human_date() {
104 + # Convertit 20251203_172811 → "03/12/2025 17:28:11"
105 + local d="$1"
106 + local date_part="${d:0:8}"
107 + local time_part="${d:9:6}"
108 + echo "${date_part:6:2}/${date_part:4:2}/${date_part:0:4} ${time_part:0:2}:${time_part:2:2}:${time_part:4:2}"
109 + }
110 +
111 + get_size() {
112 + # Taille lisible
113 + du -sh "$1" 2>/dev/null | awk '{print $1}'
114 + }
115 +
102 116 #############################
103 117 # DÉBUT SCRIPT
104 118 #############################
@@ -118,7 +132,7 @@ log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."
118 132 ##############################################
119 133 log_message "Création de l’archive : $BACKUP_FILE"
120 134
121 - # Construction des arguments d'exclusion dynamiques
135 + # Construction des arguments d'exclusion dynamiques pour le TAR
122 136 EXCLUDE_ARGS=(
123 137 "--exclude=*.log"
124 138 "--exclude=.composer"
@@ -141,7 +155,6 @@ EXCLUDE_ARGS=(
141 155 "--exclude=.rvm"
142 156 "--exclude=node_modules"
143 157 "--exclude=lost+found"
144 - "--exclude=casaos_data"
145 158 )
146 159
147 160 for d in "${EXCLUDE_DIRS[@]}"; do
@@ -176,14 +189,17 @@ if [ -d "$SOURCE_DIR/casaos_data" ]; then
176 189 done
177 190 fi
178 191
179 - log_message "Extraction des docker-compose Docker (hors casaos_data)..."
180 - find "$SOURCE_DIR" -type f -name "docker-compose.y*ml" ! -path "$SOURCE_DIR/casaos_data/*" | while read file; do
181 - container_name=$(basename "$(dirname "$file")")
182 - dest_dir="$CONFIG_DIR/docker/$container_name"
183 - mkdir -p "$dest_dir"
184 - cp "$file" "$dest_dir/"
185 - log_message " [Docker] → Compose trouvé : $file"
186 - done
192 + log_message "Extraction des docker-compose Docker (hors casaos_data & dossiers exclus)..."
193 + find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
194 + ! -path "$SOURCE_DIR/casaos_data/*" \
195 + ! -path "$SOURCE_DIR/docker_var_lib/*" \
196 + | while read file; do
197 + container_name=$(basename "$(dirname "$file")")
198 + dest_dir="$CONFIG_DIR/docker/$container_name"
199 + mkdir -p "$dest_dir"
200 + cp "$file" "$dest_dir/"
201 + log_message " [Docker] → Compose trouvé : $file"
202 + done
187 203
188 204 ##############################################
189 205 # 3) Config Portainer (full)
@@ -197,7 +213,7 @@ if docker volume inspect portainer_data >/dev/null 2>&1; then
197 213 cp -r /var/lib/docker/volumes/portainer_data/_data/* "$PORTAINER_CONFIG_DIR/" 2>>"$LOG_FILE"
198 214 PORTAINER_FILES=$(find "$PORTAINER_CONFIG_DIR" -type f 2>/dev/null | wc -l)
199 215 else
200 - log_message "Portainer non détecté (volume portainer_data absent)."
216 + PORTAINER_CONFIG_DIR=""
201 217 fi
202 218
203 219 ##############################################
@@ -210,9 +226,6 @@ if [ -d "/var/lib/casaos" ]; then
210 226 log_message "Sauvegarde config CasaOS (full)..."
211 227 mkdir -p "$CASAOS_CONFIG_DIR"
212 228 cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
213 - CASAOS_FILES=$(find "$CONFIG_DIR/casaos" -type f -name "docker-compose.y*ml" ! -path "$CONFIG_DIR/casaos/full_config/*" 2>/dev/null | wc -l)
214 - else
215 - log_message "CasaOS non détecté (/var/lib/casaos manquant)."
216 229 fi
217 230
218 231 ##############################################
@@ -224,8 +237,17 @@ CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "doc
224 237 DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/docker" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
225 238 TOTAL_COMPOSE_BACKUP=$((CASAOS_COMPOSE_BACKUP + DOCKER_COMPOSE_BACKUP))
226 239
227 - # Compose dans le dossier source (hors casaos_data)
228 - SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -type f -name "docker-compose.y*ml" ! -path "$SOURCE_DIR/casaos_data/*" 2>/dev/null | wc -l)
240 + # Compose dans le dossier source (uniquement /home/docker/<container>/docker-compose.*)
241 + SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
242 + ! -path "$SOURCE_DIR/casaos_data/*" \
243 + ! -path "$SOURCE_DIR/docker_var_lib/*" \
244 + 2>/dev/null | wc -l)
245 +
246 + # Containers Docker "valides" (dossiers de premier niveau, hors exclusions évidentes)
247 + CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
248 + ! -path "$SOURCE_DIR/casaos_data" \
249 + ! -path "$SOURCE_DIR/docker_var_lib" \
250 + ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)
229 251
230 252 # Rotation des anciens backups
231 253 rotate_backups
@@ -239,32 +261,133 @@ NEWEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | tail -n
239 261
240 262 DURATION="$(format_time $SECONDS)"
241 263
264 + # Tailles des backups
265 + TAR_SIZE=$(get_size "$BACKUP_FILE")
266 + CONFIG_SIZE=$(get_size "$CONFIG_DIR")
267 +
268 + # Docker compose directory size
269 + DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")
270 +
271 + # CasaOS full config size
272 + if [ -d "$CASAOS_CONFIG_DIR" ]; then
273 + CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
274 + else
275 + CASAOS_CONFIG_SIZE=""
276 + fi
277 +
278 + # Portainer full config size
279 + if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
280 + PORTAINER_CONFIG_SIZE=$(get_size "$PORTAINER_CONFIG_DIR")
281 + else
282 + PORTAINER_CONFIG_SIZE=""
283 + fi
284 +
285 + # Dates humaines
286 + HUMAN_OLDEST=$( [ -n "$OLDEST_BACKUP" ] && human_date "$(basename "$OLDEST_BACKUP" | sed 's/docker_backup_//; s/.tar.gz//')" )
287 + HUMAN_NEWEST=$( [ -n "$NEWEST_BACKUP" ] && human_date "$(basename "$NEWEST_BACKUP" | sed 's/docker_backup_//; s/.tar.gz//')" )
288 +
242 289 ##############################################
243 290 # 6) RÉSUMÉS
244 291 ##############################################
245 292
246 -
293 + echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
247 294
248 -
295 + ##############################################
296 + # LISTE DES DOSSIERS DOCKER PAR TAILLE (ASCII)
297 + ##############################################
249 298
250 - echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
251 - echo -e "${CYAN}----- DOCKER -----${NC}"
252 - echo -e "${CYAN}Compose source (hors CasaOS) : ${GREEN}$SOURCE_COMPOSE_COUNT${NC}"
299 + echo -e "\n${CYAN}----- LISTE/TAILLE DES RÉPERTOIRES DOCKER -----${NC}"
300 +
301 + DOCKER_DIRS=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
302 + ! -path "$SOURCE_DIR/casaos_data" \
303 + ! -path "$SOURCE_DIR/docker_var_lib" \
304 + ! -path "$SOURCE_DIR/portainer" 2>/dev/null)
305 +
306 + if [ -z "$DOCKER_DIRS" ]; then
307 + echo -e "${YELLOW}(Aucun dossier Docker trouvé)${NC}"
308 + else
309 + echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────────┐"
310 + printf "│ %-24s │ %-7s │ %-38s │\n" "Container" "Taille" "Chemin"
311 + echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────────┤"
312 + du -sh $DOCKER_DIRS 2>/dev/null | sort -hr | while read -r size path; do
313 + name=$(basename "$path")
314 + printf "│ %-24s │ %-7s │ %-38s │\n" "$name" "$size" "$path"
315 + done
316 + echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────────┘"
317 + fi
318 +
319 + #################################
320 + # DOCKER
321 + #################################
322 + echo -e "${CYAN}\n----- DOCKER -----${NC}"
323 + echo -e "${CYAN}Containers Docker détectés : ${GREEN}$CONTAINERS_DOCKER${NC}"
324 + echo -e "${CYAN}Compose source (Docker) : ${GREEN}$SOURCE_COMPOSE_COUNT${NC}"
253 325 echo -e "${CYAN}Compose backup (Docker) : ${GREEN}$DOCKER_COMPOSE_BACKUP${NC}"
254 326 echo -e "${CYAN}Dossier compose Docker : ${YELLOW}$CONFIG_DIR/docker${NC}"
327 + echo -e "${CYAN}Taille compose Docker : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"
328 +
329 + #################################
330 + # CASAOS (si présent)
331 + #################################
332 + if [ -d "$CASAOS_CONFIG_DIR" ] || [ "$CASAOS_COMPOSE_BACKUP" -gt 0 ]; then
333 + echo -e "${CYAN}\n----- CASAOS -----${NC}"
334 + echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
335 + echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
336 + [ -n "$CASAOS_CONFIG_SIZE" ] && echo -e "${CYAN}Taille config CasaOS (full) : ${GREEN}$CASAOS_CONFIG_SIZE${NC}"
337 + fi
255 338
256 - echo -e "${CYAN}----- CASAOS -----${NC}"
257 - echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
258 - echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
259 -
260 - echo -e "${CYAN}----- PORTAINER -----${NC}"
261 - echo -e "${CYAN}Fichiers config Portainer : ${GREEN}$PORTAINER_FILES${NC}"
262 - echo -e "${CYAN}Dossier Portainer backup : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"
339 + #################################
340 + # PORTAINER (si présent)
341 + #################################
342 + if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
343 + echo -e "${CYAN}\n----- PORTAINER -----${NC}"
344 + echo -e "${CYAN}Fichiers config Portainer : ${GREEN}$PORTAINER_FILES${NC}"
345 + echo -e "${CYAN}Dossier Portainer backup : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"
346 + [ -n "$PORTAINER_CONFIG_SIZE" ] && echo -e "${CYAN}Taille Portainer (full) : ${GREEN}$PORTAINER_CONFIG_SIZE${NC}"
347 + fi
263 348
264 - echo -e "${CYAN}----- GLOBAL -----${NC}"
349 + #################################
350 + # GLOBAL
351 + #################################
352 + echo -e "${CYAN}\n----- GLOBAL -----${NC}"
353 + echo -e "${CYAN}Taille archive tar.gz : ${GREEN}$TAR_SIZE${NC}"
354 + echo -e "${CYAN}Taille dossier config : ${GREEN}$CONFIG_SIZE${NC}"
265 355 echo -e "${CYAN}Nombre de .tar.gz : ${GREEN}$TOTAL_TAR${NC}"
266 - echo -e "${CYAN}Oldest backup : ${YELLOW}${OLDEST_BACKUP:-N/A}${NC}"
267 - echo -e "${CYAN}Newest backup : ${YELLOW}${NEWEST_BACKUP:-N/A}${NC}"
356 + echo -e "${CYAN}Oldest backup : ${YELLOW}$OLDEST_BACKUP${NC}"
357 + echo -e "${CYAN}Oldest backup (human) : ${GREEN}${HUMAN_OLDEST:-N/A}${NC}"
358 + echo -e "${CYAN}Newest backup : ${YELLOW}$NEWEST_BACKUP${NC}"
359 + echo -e "${CYAN}Newest backup (human) : ${GREEN}${HUMAN_NEWEST:-N/A}${NC}"
268 360 echo -e "${CYAN}Archive courante : ${YELLOW}$BACKUP_FILE${NC}"
269 361 echo -e "${CYAN}Dossier config courant : ${YELLOW}$CONFIG_DIR${NC}"
270 362 echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
363 +
364 + #################################
365 + # JSON (optionnel : ./script.sh --json)
366 + #################################
367 + if [ "$1" = "--json" ]; then
368 + echo ""
369 + echo "{"
370 + echo " \"date\": \"$DATE\","
371 + echo " \"backup_file\": \"$BACKUP_FILE\","
372 + echo " \"backup_size\": \"$TAR_SIZE\","
373 + echo " \"config_dir\": \"$CONFIG_DIR\","
374 + echo " \"config_size\": \"$CONFIG_SIZE\","
375 + echo " \"docker\": {"
376 + echo " \"containers\": $CONTAINERS_DOCKER,"
377 + echo " \"compose_source\": $SOURCE_COMPOSE_COUNT,"
378 + echo " \"compose_backup\": $DOCKER_COMPOSE_BACKUP"
379 + echo " },"
380 + echo " \"casaos\": {"
381 + echo " \"compose_backup\": $CASAOS_COMPOSE_BACKUP"
382 + echo " },"
383 + echo " \"portainer\": {"
384 + echo " \"files\": $PORTAINER_FILES"
385 + echo " },"
386 + echo " \"tar_count\": $TOTAL_TAR,"
387 + echo " \"oldest_backup\": \"$OLDEST_BACKUP\","
388 + echo " \"oldest_backup_human\": \"${HUMAN_OLDEST:-N/A}\","
389 + echo " \"newest_backup\": \"$NEWEST_BACKUP\","
390 + echo " \"newest_backup_human\": \"${HUMAN_NEWEST:-N/A}\","
391 + echo " \"duration\": \"$DURATION\""
392 + echo "}"
393 + fi
Próximo Anterior