Ceci est une ancienne révision du document !
Mise en place de sauvegardes
Avec les ordinateurs, il y a 2 types d'utilisateurs. Ceux qui ont déjà perdu des données et ceux qui vont en perdre. Généralement, les premiers mettent en place des systèmes pour parer à cet évènement, tandis que les autres vivent dans l'insouciance la plus totale. Je fais partie de la première catégorie depuis de nombreuses années et voici ce que j'ai fait pour ne plus avoir à vivre avec la peur de perdre mon travail, mes photos et autres documents importants.
Pour avoir un système de sauvegardes efficaces, il faut respecter la règle 3-2-1
:
- Avoir 3 sauvegardes différentes,
des copies dans des répertoires différents ne compte pas. Il faut avoir 3 copies sur des supports différents. - Avoir 2 types de support différents pour les sauvegardes,
utiliser 3 disques dur ne fonctionne pas car les mêmes types de supports sont sujet aux mêmes défaillances. - Avoir 1 supports à un emplacement différent,
car nul n'est à l'abri d'un vol, d'un incendie ou tout autre évènement qui pourrait détruire les données.
À cela, j'ajouterai les règles suivantes :
- Il faut tester ses sauvegardes régulièrement car des sauvegardes desquelles on ne peut pas récupérer de données sont des sauvegardes inutiles.
- Il faut sauvegarder régulièrement pour perdre le moins possible de choses en cas de défaillance.
Pour l'instant, je ne suis pas encore tout à fait au point. Je n'ai que 2 sauvegardes différentes, sur 1 seul type de support et aucune de mes sauvegardes est à un emplacement différent.
Sauvegarde des données locales sur un disque local
La première étape fut de sauvegarder mes données sur un disque local. C'est un disque physique différent qui ne sert qu'à cela. Il est dans ma machine à côté de mes disques courants. J'utilise rdiff-backup depuis de nombreuses année même s'il n'est plus maintenu depuis 2009. Il donne de bon résultat mais il faudra que je trouve un remplaçant qui soit encore maintenu.
Pour réaliser ma sauvegarde, j'ai écrit un script qui :
- Monte le disque contenant les sauvegardes,
- Supprime les sauvegardes antérieures à 30 jours,
- Cré une nouvelle sauvegarde des répertoires et fichiers listés dans le fichier de configuration,
- Démonte le disque précédemment monté,
- Nettoie le système.
#!/bin/bash NAME="Automatic.Backup" BACKUP=/media/backup TEMPFILE=/tmp/$NAME echo "-= Mount backup drive =-" if [ `mount | grep -c $BACKUP` -eq 0 ]; then mkdir $BACKUP mount /dev/sdb1 $BACKUP fi echo "-= Delete old backups =-" rdiff-backup --verbosity 0 --force --remove-older-than 30D $BACKUP echo "-= Create new backup =-" find /home -name .$NAME -exec cat {} > $TEMPFILE + echo "**$NAME" >> $TEMPFILE echo "- **" >> $TEMPFILE rdiff-backup --verbosity 0 --include-globbing-filelist $TEMPFILE /home $BACKUP echo "-= Unmount backup drive =-" umount $BACKUP rmdir $BACKUP echo "-= Clean system =-" rm $TEMPFILE
Le fichier de configuration liste les répertoires et fichiers à sauvegarder. Voici un petit exemple de la syntaxe à utiliser :
; Fichier simple /home/user/file.txt ; Fichiers avec un motif /home/user/**.pdf ; Répertoire simple /home/user/folder ; Répertoire avec espaces /home/user/folder\ with\ spaces
Ce script peut être lancé manuellement mais c'est plus intéressant de le lancer automatiquement pour ne plus avoir à y penser. Il y a quelques années j'avais fait le choix de déclencher la sauvegarde à l'extinction de l'ordinateur, mais lorsque le volume de données à sauvegarder était important, je devais attendre. Maintenant, je le fais au démarrage de manière non-bloquante pour ne pas subir ce léger désagrément. C'est systemd qui s'occupe de gérer le lancement.
J'ai créé le fichier /etc/systemd/system/local.backup.service
avec le contenu suivant :
[Unit] Description=Backup on internal disk Requires=home.mount After=home.mount [Service] ExecStart=/home/alexis/Personnalisation/Scripts/Automatic.Backup.sh Type=oneshot [Install] WantedBy=graphical.target
Pour l'enregistrer comme service de démarrage, il suffit de lancer la commande suivante :
systemctl enable local.backup
Je peux également également connaître l'état de ma sauvegarde en lançant la commande suivante :
systemctl status local.backup
Sauvegarde des données locales sur un disque externe
La seconde étape fut de sauvegarder sur un disque externe. Pour cela, j'ai fait quasiment comme pour la sauvegarde sur mon disque interne.
Pour réaliser ma sauvegarde, j'ai écrit un script qui :
- Attend le montage du disque contenant les sauvegardes,
- Supprime les sauvegardes antérieures à 300 jours,
- Cré une nouvelle sauvegarde des répertoires et fichiers listés dans le fichier de configuration,
- Démonte le disque précédemment monté,
- Nettoie le système.
Les actions effectuées sont vraiment similaires, du coup, le script l'est aussi. La différence vient du système d'attente du point de montage.
#!/bin/bash NAME="Automatic.Backup" BACKUP="/run/media/alexis/7d5a54b8-259e-4473-8a85-9e588ca30453" BACKUPDIR=$BACKUP/backup TEMPFILE=/tmp/$NAME".EHDD" USER=alexis USERID=`id -u $USER` BASH=`which bash` sudo -u $USER $BASH -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USERID/bus notify-send -t 10000 -u normal -i /usr/share/icons/Adwaita/32x32/devices/drive-removable-media.png 'Backup started' 'Location: external drive.'" echo "-= Wait until HDD is mounted =-" while [ `mount | grep -c $BACKUP` -eq 0 ]; do sleep 1s done echo "-= Create backup dir =-" if [ ! -e $BACKUPDIR ]; then mkdir $BACKUPDIR fi echo "-= Delete old backups =-" rdiff-backup --verbosity 0 --force --remove-older-than 300D $BACKUPDIR echo "-= Create new backup =-" find /home -name .$NAME -exec cat {} > $TEMPFILE + echo "**$NAME" >> $TEMPFILE echo "- **" >> $TEMPFILE rdiff-backup --verbosity 0 --force --include-globbing-filelist $TEMPFILE /home $BACKUPDIR echo "-= Clean system =-" rm $TEMPFILE sudo -u $USER $BASH -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USERID/bus notify-send -t 10000 -u normal -i /usr/share/icons/Adwaita/32x32/devices/drive-removable-media.png 'Backup done' 'Location: external drive.'"
Comme pour le script précédent, je voulais que le déclenchement de la sauvegarde se fasse automatiquement au moment de la connexion du disque. Pour cela, j'ai utilisé systemd de manière semblable à celle utilisée précédemment.
J'ai créé le fichier /etc/systemd/system/ehdd.backup.service
avec le contenu suivant :
[Unit] Description=Backup on external disk Requires=run-media-alexis-7d5a54b8\x2d259e\x2d4473\x2d8a85\x2d9e588ca30453.mount After=run-media-alexis-7d5a54b8\x2d259e\x2d4473\x2d8a85\x2d9e588ca30453.mount [Service] ExecStart=/home/alexis/Personnalisation/Scripts/Automatic.Backup.EHDD.sh Type=oneshot [Install] WantedBy=graphical.target
À ce moment, il ne reste plus qu'à activer le service pour qu'il soit utilisable au démarrage de la machine.
Pour trouver l'identifiant unique d'un disque, il faut lancer la commande suivante :
ls -l /dev/disk/by-uuid
Pour encoder un chemin en une chaîne de caractères utilisable dans les fichiers de configuration de systemd, il faut lancer la commande suivante :
systemd-escape --path <path>
Sauvegarde des données locales sur un disque délocalisé
Sauvegarde des données distantes
La quatrième étape fut de sauvegarder les données de mes services en ligne (RSS, photos, etc.) sur le disque local. Pour cela, j'ai fait plusieurs tests peu concluants 1)2)3) avant de trouver quelque chose qui fonctionne.
Finalement, j'ai écrit un script qui :
- Sauvegarde les données du cron,
- Lance une sauvegarde des bases de données à distance et qui les compresse,
- Monte le disque distant en local avec SSHFS,
- Synchronise l'ensemble des fichiers montés avec rsync,
- Nettoie le système.
#!/bin/bash SSH_CONNECTION=<user>@<server> IDENTITY=/home/alexis/.ssh/<server> USER_NAME=backup MOUNT_POINT=/media/$USER_NAME MYSQL_HOST=<dbhost> MYSQL_USER=<dbuser> MYSQL_PASSWD=<dbpassword> USER=alexis USERID=`id -u $USER` sudo -u $USER /usr/bin/bash -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USERID/bus notify-send -t 10000 -u normal -i /usr/share/icons/Adwaita/32x32/devices/drive-removable-media.png 'Backup started' 'Distant to internal drive.'" # Extract crontab ssh -i $IDENTITY $SSH_CONNECTION "crontab -l" > /home/$USER_NAME/crontab # Dump databases dbs[0]=<db> … dbs[n]=<db> for i in "${dbs[@]}" do ssh -i $IDENTITY $SSH_CONNECTION "mysqldump --skip-comments --disable-keys --user=$MYSQL_USER --password=$MYSQL_PASSWD --host $MYSQL_HOST --databases $i | gzip" > /home/$USER_NAME/$i.dump.sql.gz done # Save files mkdir $MOUNT_POINT sshfs $SSH_CONNECTION:www $MOUNT_POINT -o IdentityFile=$IDENTITY files[0]=<file> … files[n]=<file> for i in "${files[@]}" do if [[ -d $MOUNT_POINT/$i ]]; then mkdir -p /home/$USER_NAME/$i fi rsync -azq --delete --force $MOUNT_POINT/$i /home/$USER_NAME/$(dirname $i) done umount $MOUNT_POINT rmdir $MOUNT_POINT sudo -u $USER /usr/bin/bash -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USERID/bus notify-send -t 10000 -u normal -i /usr/share/icons/Adwaita/32x32/devices/drive-removable-media.png 'Backup done' 'Distant to internal drive.'"
Comme pour les autres scripts, j'ai laissé systemd s'occuper du déclenchement du script. J'ai créé le fichier /etc/systemd/system/distant.backup.service
avec le contenu suivant :
[Unit] Description=Backup distant on internal disk Requires=home.mount After=home.mount [Service] ExecStart=/home/alexis/Personnalisation/Scripts/Automatic.Backup.Distant.sh Type=oneshot [Install] WantedBy=graphical.target
Cependant, je voulais le lancer un peu en différé par rapport à la séquence de démarrage. J'ai donc créé le fichier /etc/systemd/system/distant.backup.timer
avec le contenu suivant :
[Unit] Description=Run distant backup on boot [Timer] OnBootSec=30min [Install] WantedBy=timers.target
C'est ce dernier qu'il faut activer pour qu'il soit utilisable au démarrage de la machine.
Restauration de données
La dernière étape est de vérifier que les sauvegardes sont utilisables. C'est une opération qu'il faut faire régulièrement pour s'assurer de leur bon fonctionnement. Ce n'est pas le jour où on veut récupérer un fichier qu'il faut s'inquiéter de l'intégrité des données sauvegardées.
Avec rdiff-backup
, ces opérations sont faciles à mettre en place. Je vais en détailler quelques-unes pour donner un aperçu de ce qu'il est possible de faire mais la meilleure source d'information restera le manuel.
- Lister les incréments
# Liste les incréments par date rdiff-backup --list-increments /media/backup/ # Liste les incréments par date en affichant leur taille rdiff-backup --list-increment-sizes /media/backup/
- Lister les fichiers
# Liste les fichiers présents il y a 3 jours rdiff-backup --list-at-time 3D /media/backup # Liste les fichiers présents à la date sélectionnée rdiff-backup --list-at-time "Fri Oct 22 21:29:12 2010" /media/backup # Liste les changements effectués depuis 3 jours rdiff-backup --list-changed-since 3D /media/backup # Liste les changements effectués depuis la date sélectionnée rdiff-backup --list-changed-since "Fri Oct 22 21:29:12 2010" /media/backup
- Restaurer des données
# Restaure le premier incrément antérieur à 3 jours dans le répertoire /tmp/OldBackup # Le répertoire /tmp/OldBackup ne doit pas exister rdiff-backup -r 3D /media/backup/ /tmp/OldBackup # Restaure le premier incrément antérieur ou égal à la date sélectionnée dans le répertoire /tmp/OldBackup # Le répertoire /tmp/OldBackup ne doit pas exister rdiff-backup -r "Fri Oct 22 21:29:12 2010" /media/backup/ /tmp/OldBackup
Liens à étudier :