Objectif du Projet
Mettre en pratique toutes les compétences de scripting Bash acquises pour créer un outil en ligne de commande flexible, robuste et réutilisable pour effectuer des sauvegardes de dossiers.
Le Scénario
Vous avez plusieurs dossiers importants sur votre système (ex: /var/www, /home/alice/documents, /etc/nginx), et vous voulez un seul script capable de sauvegarder n’importe lequel d’entre eux dans une archive compressée, horodatée, et qui gère automatiquement la suppression des plus anciennes sauvegardes.
Fonctionnalités attendues
- Le script doit prendre le dossier source et le dossier de destination en arguments.
- Il doit créer une archive
.tar.gzavec un nom contenant la date et l’heure. - Il doit mettre en place une “rotation” : ne conserver, par exemple, que les 7 dernières sauvegardes.
- Il doit être robuste : afficher une aide, valider ses arguments, et s’arrêter en cas d’erreur.
Le Script Complet
Ce script est une synthèse de tout ce que nous avons vu : set -e, fonctions, getopts pour les arguments, date pour le nommage, tar pour l’archivage, et find pour le nettoyage.
#!/usr/bin/env bash
# Mode strict
set -euo pipefail
# --- Documentation et Constantes ---
readonly SCRIPT_NAME="$(basename "$0")"
# --- Fonctions ---
# Affiche un message d'erreur sur stderr et quitte
die() {
echo >&2 "[ERREUR] $@"
exit 1
}
# Affiche le message d'aide
usage() {
echo "Usage: $SCRIPT_NAME -s <dossier_source> -d <dossier_destination> [-k <jours>]"
echo "Crée une sauvegarde compressée d'un dossier avec rotation."
echo ""
echo "Options:"
echo " -s <source> Dossier à sauvegarder (obligatoire)."
echo " -d <dest> Dossier où stocker les sauvegardes (obligatoire)."
echo " -k <jours> Nombre de jours de rétention (optionnel, 7 par défaut)."
echo " -h Affiche cette aide."
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
# On crée le dossier de destination s'il n'existe pas
mkdir -p "$DEST_DIR"
# --- Logique Principale ---
local DATE_TAG
DATE_TAG=$(date +"%Y-%m-%d_%H%M%S")
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 "INFO: Création de la sauvegarde : '$DEST_FILE'..."
tar -czf "$DEST_FILE" -C "$(dirname "$SOURCE_DIR")" "$BASENAME_SOURCE"
echo "INFO: Sauvegarde terminée avec succès."
# --- Rotation des sauvegardes ---
echo "INFO: Application de la politique de rétention (${RETENTION_DAYS} jours)..."
# Le '|| true' est une sécurité si find ne trouve aucun fichier, pour ne pas faire échouer le script
find "$DEST_DIR" -type f -name "backup-${BASENAME_SOURCE}-*.tar.gz" -mtime "+$RETENTION_DAYS" -print -delete || true
echo "INFO: Rotation terminée."
}
# --- Point d'entrée ---
main "$@"
Comment l’utiliser et l’automatiser ?
- Sauvegardez ce script (ex: dans
/usr/local/bin/mon_backup.sh) et rendez-le exécutable (chmod +x). - Lancez-le manuellement pour tester :
sudo /usr/local/bin/mon_backup.sh -s /var/log -d /mnt/backups -k 30 - Automatisez-le avec
cron:- Ouvrez la crontab de
root(sudo crontab -e). - Ajoutez une ligne pour l’exécuter tous les jours à 2h du matin.
0 2 * * * /usr/local/bin/mon_backup.sh -s /var/www -d /mnt/backups > /var/log/backup.log 2>&1 - Ouvrez la crontab de
Exercices et améliorations
-
Mise en place :
- Enregistrez le script sur votre machine.
- Créez un dossier
source_testavec quelques fichiers et un dossierdest_test. - Exécutez le script pour sauvegarder
source_testdansdest_test. Vérifiez que l’archive est créée.
-
Ajouter des logs :
- Modifiez le script pour qu’il accepte une option
-l <fichier_log>. - S’il reçoit cette option, tous les messages
echodoivent être redirigés à la fois vers le terminal et vers le fichier de log. (Indice :echo "message" | tee -a "$LOG_FILE").
- Modifiez le script pour qu’il accepte une option
-
Vérifier l’espace disque :
- Avant de lancer
tar, ajoutez une vérification avecdfpour vous assurer qu’il y a suffisamment d’espace disque disponible dans la destination. - Si ce n’est pas le cas, appelez la fonction
dieavec un message d’erreur clair.
- Avant de lancer