Retour au cours

projet backup script

Objectifs

  • Créer un script de sauvegarde réutilisable et configurable.
  • Archiver et compresser un dossier avec tar.
  • Nommer les sauvegardes avec la date pour une meilleure organisation.
  • Mettre en place une politique de rétention simple pour ne pas saturer l’espace disque.
  • Aborder le chiffrement d’une sauvegarde pour la sécurité.

Le Scénario

Vous avez un dossier important sur votre serveur (par exemple, /var/www/mon_site) et vous voulez automatiser sa sauvegarde quotidienne dans un dossier de destination (par exemple, /mnt/backups). Chaque sauvegarde doit être datée, compressée, et vous ne voulez conserver que les 7 dernières.

Les Outils à Combiner

  • tar : Pour créer l’archive.
  • date : Pour générer un nom de fichier unique et horodaté.
  • find : Pour trouver et supprimer les anciennes sauvegardes.
  • Un squelette de script robuste avec gestion d’arguments et d’erreurs.
  • gpg (en option) : Pour le chiffrement.

Le Script Complet

Voici un script complet et commenté qui réalise cette tâche.

#!/usr/bin/env bash

# Mode strict
set -euo pipefail

# --- Documentation et Constantes ---
# Description:
#   Crée une archive .tar.gz compressée d'un dossier source
#   vers un dossier de destination, et applique une rotation.
#
# Usage:
#   ./backup.sh -s <dossier_source> -d <dossier_destination> [-k <jours>]
#
# Options:
#   -s <source>   Dossier à sauvegarder (obligatoire).
#   -d <dest>     Dossier où stocker les sauvegardes (obligatoire).
#   -k <jours>    Nombre de jours de rétention (optionnel, 7 par défaut).
#   -h            Affiche cette aide.

readonly SCRIPT_NAME="$(basename "$0")"

# --- Fonctions ---

die() {
  echo >&2 "[ERREUR] $@"
  exit 1
}

usage() {
  echo "Usage: $SCRIPT_NAME -s <source> -d <dest> [-k <jours>]"
  echo "       Crée une sauvegarde compressée avec rotation."
  exit 0
}

# --- Fonction Principale ---
main() {
  local SOURCE_DIR=""
  local DEST_DIR=""
  local RETENTION_DAYS=7

  while getopts ":hs:d:k:" opt; do
    case "$opt" in
      h) usage ;;
      s) SOURCE_DIR="$OPTARG" ;;
      d) DEST_DIR="$OPTARG" ;;
      k) RETENTION_DAYS="$OPTARG" ;;
      \?|:) die "Option invalide ou argument manquant. Utilisez -h pour l'aide." ;;
    esac
  done
  shift $((OPTIND - 1))

  # --- Validation ---
  if [[ -z "$SOURCE_DIR" || -z "$DEST_DIR" ]]; then
    usage
  fi
  if [[ ! -d "$SOURCE_DIR" ]]; then
    die "Le dossier source '$SOURCE_DIR' n'existe pas."
  fi
  if [[ ! -d "$DEST_DIR" ]]; then
    # On peut décider de le créer s'il n'existe pas
    echo "Le dossier de destination '$DEST_DIR' n'existe pas, création..."
    mkdir -p "$DEST_DIR"
  fi

  # --- Logique Principale ---
  local DATE_TAG
  DATE_TAG=$(date +"%Y-%m-%d_%H%M%S")
  # On utilise 'basename' pour n'avoir que le nom du dossier source, pas son chemin
  local BASENAME_SOURCE
  BASENAME_SOURCE=$(basename "$SOURCE_DIR")
  local ARCHIVE_NAME="backup-${BASENAME_SOURCE}-${DATE_TAG}.tar.gz"
  local DEST_FILE="${DEST_DIR}/${ARCHIVE_NAME}"

  echo "Création de la sauvegarde : '$DEST_FILE'..."
  
  # c: create, z: gzip, f: file
  # L'option -C permet de se "déplacer" dans un dossier avant d'archiver,
  # ce qui évite d'avoir toute l'arborescence dans le .tar.gz
  tar -czf "$DEST_FILE" -C "$(dirname "$SOURCE_DIR")" "$BASENAME_SOURCE"

  echo "Sauvegarde terminée avec succès."

  # --- Chiffrement (Optionnel) ---
  # Si gpg est installé et configuré
  # gpg -c --batch --passphrase "VOTRE_MOT_DE_PASSE_SECRET" -o "${DEST_FILE}.gpg" "$DEST_FILE"
  # if [[ $? -eq 0 ]]; then
  #   rm "$DEST_FILE" # Supprimer l'archive non chiffrée si le chiffrement a réussi
  #   echo "Archive chiffrée."
  # fi

  # --- Rotation des sauvegardes ---
  echo "Application de la politique de rétention (${RETENTION_DAYS} jours)..."
  # Trouve les fichiers .tar.gz dans le dossier de destination qui ont été modifiés
  # il y a plus de RETENTION_DAYS jours, et les supprime.
  find "$DEST_DIR" -type f -name "backup-*.tar.gz" -mtime "+$RETENTION_DAYS" -delete
  
  echo "Rotation terminée."
}

# --- Point d'entrée ---
main "$@"

Bonnes Pratiques Mises en Œuvre

  • Script configurable : L’utilisation de getopts rend le script flexible et réutilisable.
  • Noms de fichiers clairs : L’horodatage permet de savoir immédiatement quand une sauvegarde a été faite et de les trier.
  • Validation des entrées : Le script vérifie que les dossiers existent avant de commencer, ce qui évite les erreurs en cours de route.
  • Gestion de la rétention : L’utilisation de find avec -mtime et -delete est une manière standard et efficace de gérer la rotation des backups.

Pièges Évités

  • Chemins dans l’archive : L’utilisation de tar -C permet de créer une archive “propre” qui contient directement le dossier sauvegardé, et non tout son chemin depuis la racine /.
  • Erreurs silencieuses : Grâce à set -e, si tar échoue, le script s’arrêtera et n’affichera pas le message de succès.

Exercices

  1. Tester le script :

    • Créez un dossier mon_dossier_test avec quelques fichiers à l’intérieur.
    • Créez un dossier destination_backups.
    • Lancez le script pour sauvegarder mon_dossier_test dans destination_backups.
    • Vérifiez que l’archive a bien été créée.
  2. Ajouter des logs :

    • Modifiez le script pour qu’il écrive ses messages (echo) à la fois dans le terminal et dans un fichier de log (ex: /var/log/backup.log).
    • Indice : vous pouvez utiliser la commande tee -a.
  3. Tester la rotation :

    • Créez manuellement plusieurs fausses archives dans votre dossier de destination avec des dates de modification différentes en utilisant la commande touch.
    • Ajustez la rétention (-k) à 1 ou 2 jours et lancez le script (même s’il ne fait pas de nouvelle sauvegarde) pour vérifier que les anciennes archives sont bien supprimées.