btrfs-backup.sh
· 4.3 KiB · Bash
Raw
#!/usr/bin/env bash
# Config
SOURCE="/home"
LOCAL_DEST="/snapshots"
DEST="/run/media/mathieu/ext_ssd/backups"
KEEP_LOCAL=10 # Nombre de snapshots locaux à conserver
KEEP_DISTANT=31 # Nombre de snapshots distant à conserver
# KEEP_DAILY=7 # Rétention des snapshots distants
# KEEP_WEEKLY=4
# KEEP_MONTHLY=6
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
SNAPSHOT_NAME="$DATE"
LAST_RUN_FILE="$DEST/.last_run"
LAST_SNAPSHOT_FILE="$DEST/.last_snapshot"
get_age_days() {
local file=$1
local file_time=$(date -r "$file" +%s)
local current_time=$(date +%s)
echo $(((current_time - file_time) / 86400))
}
if ! mountpoint -q "$DEST/.."; then
echo "Erreur: Le disque externe n'est pas monté sur $DEST"
exit 1
fi
# Vérifier la dernière exécution
if [ -f "$LAST_RUN_FILE" ]; then
last_run=$(cat "$LAST_RUN_FILE")
days_since_last_run=$((($(date +%s) - $(date -d "$last_run" +%s)) / 86400))
if [ $days_since_last_run -gt 7 ]; then
echo "Attention: $days_since_last_run jours se sont écoulés depuis la dernière sauvegarde."
fi
else
echo "Première exécution détectée."
fi
# Créer un nouveau snapshot en lecture seule de /home
if sudo btrfs subvolume snapshot -r "$SOURCE" "$LOCAL_DEST/$SNAPSHOT_NAME"; then
echo "Snapshot local créé avec succès: $LOCAL_DEST/$SNAPSHOT_NAME"
else
echo "Erreur lors de la création du snapshot local"
exit 1
fi
# Envoyer le snapshot vers la destination
if [ -f "$LAST_SNAPSHOT_FILE" ]; then
last_snapshot=$(cat "$LAST_SNAPSHOT_FILE")
if [ -d "$LOCAL_DEST/$last_snapshot" ]; then
echo "Envoi d'un snapshot incrémentiel..."
if sudo btrfs send -p "$LOCAL_DEST/$last_snapshot" "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then
echo "Snapshot incrémental envoyé avec succès vers $DEST/$SNAPSHOT_NAME"
else
echo "Erreur lors de l'envoi du snapshot incrémentiel. Tentative d'envoi complet..."
if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then
echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME"
else
echo "Erreur lors de l'envoi du snapshot complet"
sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME"
exit 1
fi
fi
else
echo "Le snapshot précédent n'existe pas localement. Envoi d'un snapshot complet..."
if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs.receive "$DEST"; then
echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME"
else
echo "Erreur lors de l'envoi du snapshot complet"
sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME"
exit 1
fi
fi
else
echo "Aucun snapshot précédent trouvé. Envoi d'un snapshot complet..."
if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then
echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME"
else
echo "Erreur lors de l'envoi du snapshot complet"
sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME"
exit 1
fi
fi
# Mettre à jour les fichiers de suivi
date +"%Y-%m-%d %H:%M:%S" >"$LAST_RUN_FILE"
echo "$SNAPSHOT_NAME" >"$LAST_SNAPSHOT_FILE"
# Fonction de nettoyage des snapshots locaux
cleanup_local_snapshots() {
echo "Nettoyage des snapshots locaux..."
local snapshots=($(ls -1d "$LOCAL_DEST"/20*_*-*-* | sort -r))
local count=0
for snapshot in "${snapshots[@]}"; do
if [ $count -ge $KEEP_LOCAL ]; then
echo "Suppression du snapshot local: $snapshot"
sudo btrfs subvolume delete "$snapshot"
fi
count=$((count + 1))
done
}
# Fonction de nettoyage des snapshots sur la destination
cleanup_remote_snapshots() {
echo "Nettoyage des snapshots distants..."
cd "$DEST" || exit
local snapshots=($(ls -1d 20*_*-*-* | sort -r))
for snapshot in "${snapshots[@]}"; do
local age=$(get_age_days "$snapshot")
# Supprimer tous les snapshots plus vieux que 31 jours
if [ $age -gt $KEEP_DISTANT ]; then
echo "Suppression du snapshot distant: $snapshot"
sudo btrfs subvolume delete "$snapshot"
fi
done
}
# Exécuter le nettoyage
cleanup_local_snapshots
cleanup_remote_snapshots
echo "Sauvegarde et nettoyage terminés"
1 | #!/usr/bin/env bash |
2 | |
3 | # Config |
4 | SOURCE="/home" |
5 | LOCAL_DEST="/snapshots" |
6 | DEST="/run/media/mathieu/ext_ssd/backups" |
7 | KEEP_LOCAL=10 # Nombre de snapshots locaux à conserver |
8 | KEEP_DISTANT=31 # Nombre de snapshots distant à conserver |
9 | # KEEP_DAILY=7 # Rétention des snapshots distants |
10 | # KEEP_WEEKLY=4 |
11 | # KEEP_MONTHLY=6 |
12 | DATE=$(date +"%Y-%m-%d_%H-%M-%S") |
13 | SNAPSHOT_NAME="$DATE" |
14 | LAST_RUN_FILE="$DEST/.last_run" |
15 | LAST_SNAPSHOT_FILE="$DEST/.last_snapshot" |
16 | |
17 | get_age_days() { |
18 | local file=$1 |
19 | local file_time=$(date -r "$file" +%s) |
20 | local current_time=$(date +%s) |
21 | echo $(((current_time - file_time) / 86400)) |
22 | } |
23 | |
24 | if ! mountpoint -q "$DEST/.."; then |
25 | echo "Erreur: Le disque externe n'est pas monté sur $DEST" |
26 | exit 1 |
27 | fi |
28 | |
29 | # Vérifier la dernière exécution |
30 | if [ -f "$LAST_RUN_FILE" ]; then |
31 | last_run=$(cat "$LAST_RUN_FILE") |
32 | days_since_last_run=$((($(date +%s) - $(date -d "$last_run" +%s)) / 86400)) |
33 | if [ $days_since_last_run -gt 7 ]; then |
34 | echo "Attention: $days_since_last_run jours se sont écoulés depuis la dernière sauvegarde." |
35 | fi |
36 | else |
37 | echo "Première exécution détectée." |
38 | fi |
39 | |
40 | # Créer un nouveau snapshot en lecture seule de /home |
41 | if sudo btrfs subvolume snapshot -r "$SOURCE" "$LOCAL_DEST/$SNAPSHOT_NAME"; then |
42 | echo "Snapshot local créé avec succès: $LOCAL_DEST/$SNAPSHOT_NAME" |
43 | else |
44 | echo "Erreur lors de la création du snapshot local" |
45 | exit 1 |
46 | fi |
47 | |
48 | # Envoyer le snapshot vers la destination |
49 | if [ -f "$LAST_SNAPSHOT_FILE" ]; then |
50 | last_snapshot=$(cat "$LAST_SNAPSHOT_FILE") |
51 | if [ -d "$LOCAL_DEST/$last_snapshot" ]; then |
52 | echo "Envoi d'un snapshot incrémentiel..." |
53 | if sudo btrfs send -p "$LOCAL_DEST/$last_snapshot" "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then |
54 | echo "Snapshot incrémental envoyé avec succès vers $DEST/$SNAPSHOT_NAME" |
55 | else |
56 | echo "Erreur lors de l'envoi du snapshot incrémentiel. Tentative d'envoi complet..." |
57 | if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then |
58 | echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME" |
59 | else |
60 | echo "Erreur lors de l'envoi du snapshot complet" |
61 | sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME" |
62 | exit 1 |
63 | fi |
64 | fi |
65 | else |
66 | echo "Le snapshot précédent n'existe pas localement. Envoi d'un snapshot complet..." |
67 | if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs.receive "$DEST"; then |
68 | echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME" |
69 | else |
70 | echo "Erreur lors de l'envoi du snapshot complet" |
71 | sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME" |
72 | exit 1 |
73 | fi |
74 | fi |
75 | else |
76 | echo "Aucun snapshot précédent trouvé. Envoi d'un snapshot complet..." |
77 | if sudo btrfs send "$LOCAL_DEST/$SNAPSHOT_NAME" | sudo btrfs receive "$DEST"; then |
78 | echo "Snapshot complet envoyé avec succès vers $DEST/$SNAPSHOT_NAME" |
79 | else |
80 | echo "Erreur lors de l'envoi du snapshot complet" |
81 | sudo btrfs subvolume delete "$LOCAL_DEST/$SNAPSHOT_NAME" |
82 | exit 1 |
83 | fi |
84 | fi |
85 | |
86 | # Mettre à jour les fichiers de suivi |
87 | date +"%Y-%m-%d %H:%M:%S" >"$LAST_RUN_FILE" |
88 | echo "$SNAPSHOT_NAME" >"$LAST_SNAPSHOT_FILE" |
89 | |
90 | # Fonction de nettoyage des snapshots locaux |
91 | cleanup_local_snapshots() { |
92 | echo "Nettoyage des snapshots locaux..." |
93 | local snapshots=($(ls -1d "$LOCAL_DEST"/20*_*-*-* | sort -r)) |
94 | local count=0 |
95 | for snapshot in "${snapshots[@]}"; do |
96 | if [ $count -ge $KEEP_LOCAL ]; then |
97 | echo "Suppression du snapshot local: $snapshot" |
98 | sudo btrfs subvolume delete "$snapshot" |
99 | fi |
100 | count=$((count + 1)) |
101 | done |
102 | } |
103 | |
104 | # Fonction de nettoyage des snapshots sur la destination |
105 | cleanup_remote_snapshots() { |
106 | echo "Nettoyage des snapshots distants..." |
107 | cd "$DEST" || exit |
108 | |
109 | local snapshots=($(ls -1d 20*_*-*-* | sort -r)) |
110 | |
111 | for snapshot in "${snapshots[@]}"; do |
112 | local age=$(get_age_days "$snapshot") |
113 | |
114 | # Supprimer tous les snapshots plus vieux que 31 jours |
115 | if [ $age -gt $KEEP_DISTANT ]; then |
116 | echo "Suppression du snapshot distant: $snapshot" |
117 | sudo btrfs subvolume delete "$snapshot" |
118 | fi |
119 | done |
120 | } |
121 | |
122 | # Exécuter le nettoyage |
123 | cleanup_local_snapshots |
124 | cleanup_remote_snapshots |
125 | |
126 | echo "Sauvegarde et nettoyage terminés" |