Files
scripts-admin-debian/backup_and_restore/sauvegarde_docker/sauvegarde_docker.sh

247 lines
8.7 KiB
Bash
Executable File

#!/bin/bash
# Description
# Ce script effectue une sauvegarde de tous les dossiers dans /srv
# Pour les dossiers correspondant à des conteneurs Docker actifs,
# les conteneurs sont arrêtés pendant la sauvegarde puis redémarrés
# Les sauvegardes sont conservées pendant 7 jours
# Configuration
SRV_DIR="/home/docker/srv"
BACKUP_DEST="/home/docker/backup"
RETENTION_DAYS=7
LOG_FILE="/home/docker/docker-backup.log"
# Fonction de logging
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Vérification de l'existence du répertoire de destination
if [ ! -d "$BACKUP_DEST" ]; then
log_message "Création du répertoire de destination $BACKUP_DEST"
mkdir -p "$BACKUP_DEST"
fi
# Vérification de l'espace disque disponible (au moins 1GB)
available_space=$(df "$BACKUP_DEST" | awk 'NR==2 {print $4}')
if [ "$available_space" -lt 1048576 ]; then
log_message "AVERTISSEMENT: Espace disque faible (moins de 1GB disponible)"
fi
log_message "Début de la sauvegarde Docker"
# Compteurs pour les statistiques
success_count=0
error_count=0
docker_stopped=()
docker_errors=()
# Fonction pour sauvegarder un répertoire
backup_directory() {
local source_dir="$1"
local folder_name="$2"
if [ ! -e "$source_dir" ]; then
log_message "AVERTISSEMENT: $source_dir n'existe pas, ignoré"
((error_count++))
return 1
fi
# Créer le dossier de destination pour ce service
local dest_folder="$BACKUP_DEST/$folder_name"
mkdir -p "$dest_folder"
local filename="${folder_name}_$(date +%Y-%m-%d_%H-%M-%S).tar.gz"
local filepath="$dest_folder/$filename"
log_message "Sauvegarde de $source_dir vers $folder_name/$filename"
# Création de l'archive
if tar -czf "$filepath" -C "$(dirname "$source_dir")" "$(basename "$source_dir")" 2>/dev/null; then
# Création du fichier de checksum SHA-256
sha256sum "$filepath" > "$filepath.sha256"
file_size=$(du -h "$filepath" | cut -f1)
log_message "SUCCESS: $filename créé ($file_size) - Checksum généré"
((success_count++))
return 0
else
log_message "ERREUR: Impossible de créer l'archive pour $source_dir"
((error_count++))
return 1
fi
}
# Fonction pour vérifier si Docker est installé
is_docker_available() {
command -v docker >/dev/null 2>&1
}
# Fonction pour vérifier si un conteneur Docker existe et est en cours d'exécution
is_container_running() {
local container_name="$1"
if is_docker_available; then
docker ps --format "table {{.Names}}" | grep -q "^${container_name}$" 2>/dev/null
else
return 1
fi
}
# Fonction pour arrêter un conteneur Docker
stop_container() {
local container_name="$1"
log_message "Arrêt du conteneur Docker: $container_name"
if docker stop "$container_name" >/dev/null 2>&1; then
log_message "Conteneur $container_name arrêté avec succès"
docker_stopped+=("$container_name")
return 0
else
log_message "ERREUR: Impossible d'arrêter le conteneur $container_name"
docker_errors+=("$container_name")
return 1
fi
}
# Fonction pour redémarrer un conteneur Docker
start_container() {
local container_name="$1"
log_message "Redémarrage du conteneur Docker: $container_name"
if docker start "$container_name" >/dev/null 2>&1; then
log_message "Conteneur $container_name redémarré avec succès"
return 0
else
log_message "ERREUR: Impossible de redémarrer le conteneur $container_name"
return 1
fi
}
# Vérifier si Docker est disponible
if ! is_docker_available; then
log_message "AVERTISSEMENT: Docker n'est pas installé ou accessible"
fi
# Sauvegarde des répertoires dans /srv
log_message "=== SAUVEGARDE DES SERVICES DOCKER ==="
if [ -d "$SRV_DIR" ]; then
# Parcourir tous les dossiers dans /srv
for srv_folder in "$SRV_DIR"/*; do
if [ -d "$srv_folder" ]; then
folder_name=$(basename "$srv_folder")
# Vérifier si un conteneur Docker avec ce nom existe et est en cours d'exécution
if is_container_running "$folder_name"; then
log_message "Conteneur Docker actif détecté: $folder_name"
# Arrêter le conteneur
if stop_container "$folder_name"; then
# Attendre un peu pour s'assurer que le conteneur est complètement arrêté
sleep 5
# Effectuer la sauvegarde
backup_directory "$srv_folder" "$folder_name"
# Redémarrer le conteneur
start_container "$folder_name"
else
log_message "AVERTISSEMENT: Sauvegarde de $folder_name sans arrêter le conteneur (risque d'incohérence)"
backup_directory "$srv_folder" "$folder_name"
fi
else
# Pas de conteneur Docker correspondant, sauvegarde normale
log_message "Service sans conteneur actif: $folder_name"
backup_directory "$srv_folder" "$folder_name"
fi
fi
done
else
log_message "ERREUR: Le répertoire $SRV_DIR n'existe pas"
exit 1
fi
# Vérification et génération des checksums pour toutes les archives
log_message "=== VÉRIFICATION ET GÉNÉRATION DES CHECKSUMS ==="
archives_without_checksum=0
archives_with_checksum=0
find "$BACKUP_DEST" -name "*.tar.gz" -type f | while read -r archive_file; do
checksum_file="${archive_file}.sha256"
if [ ! -f "$checksum_file" ]; then
log_message "Génération du checksum manquant pour $(basename "$archive_file")"
sha256sum "$archive_file" > "$checksum_file"
((archives_without_checksum++))
else
((archives_with_checksum++))
fi
done
# Compte final des archives
total_archives=$(find "$BACKUP_DEST" -name "*.tar.gz" -type f | wc -l)
missing_checksums=$(find "$BACKUP_DEST" -name "*.tar.gz" -type f | while read -r archive; do [ ! -f "${archive}.sha256" ] && echo "$archive"; done | wc -l)
log_message "Archives trouvées: $total_archives"
if [ "$missing_checksums" -eq 0 ]; then
log_message "SUCCESS: Toutes les archives ont un fichier checksum"
else
log_message "AVERTISSEMENT: $missing_checksums archives sans checksum"
fi
# Suppression des sauvegardes obsolètes
log_message "=== NETTOYAGE DES ANCIENNES SAUVEGARDES ==="
for service_dir in "$BACKUP_DEST"/*/; do
if [ -d "$service_dir" ]; then
service_name=$(basename "$service_dir")
log_message "Suppression des sauvegardes de plus de $RETENTION_DAYS jours pour $service_name"
# Chercher les fichiers obsolètes (archives et checksums séparément)
deleted_files_tar=$(find "$service_dir" -type f -name "*.tar.gz" -mtime +$RETENTION_DAYS -print 2>/dev/null)
deleted_files_sha=$(find "$service_dir" -type f -name "*.sha256" -mtime +$RETENTION_DAYS -print 2>/dev/null)
if [ -n "$deleted_files_tar" ] || [ -n "$deleted_files_sha" ]; then
# Supprimer et logger les archives
if [ -n "$deleted_files_tar" ]; then
echo "$deleted_files_tar" | while read -r file; do
log_message "Suppression: $service_name/$(basename "$file")"
done
find "$service_dir" -type f -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete 2>/dev/null
fi
# Supprimer et logger les checksums
if [ -n "$deleted_files_sha" ]; then
echo "$deleted_files_sha" | while read -r file; do
log_message "Suppression: $service_name/$(basename "$file")"
done
find "$service_dir" -type f -name "*.sha256" -mtime +$RETENTION_DAYS -delete 2>/dev/null
fi
else
log_message "Aucun fichier obsolète à supprimer pour $service_name"
fi
fi
done
# Redémarrage des conteneurs qui n'ont pas pu être redémarrés
if [ ${#docker_errors[@]} -gt 0 ]; then
log_message "=== TENTATIVE DE REDÉMARRAGE DES CONTENEURS EN ERREUR ==="
for container in "${docker_errors[@]}"; do
start_container "$container"
done
fi
# Statistiques finales
log_message "=== RÉSUMÉ DE LA SAUVEGARDE ==="
log_message "Sauvegardes réussies: $success_count"
log_message "Erreurs: $error_count"
if [ ${#docker_stopped[@]} -gt 0 ]; then
log_message "Conteneurs Docker gérés: ${docker_stopped[*]}"
fi
if [ ${#docker_errors[@]} -gt 0 ]; then
log_message "Conteneurs Docker en erreur: ${docker_errors[*]}"
fi
log_message "Sauvegarde terminée"
# Code de sortie basé sur les erreurs
if [ $error_count -gt 0 ] || [ ${#docker_errors[@]} -gt 0 ]; then
exit 1
else
exit 0
fi