Outils pour utilisateurs

Outils du site


projets:informatique:sauvegarde_donnees

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 :

  1. Monte le disque contenant les sauvegardes,
  2. Supprime les sauvegardes antérieures à 30 jours,
  3. Cré une nouvelle sauvegarde des répertoires et fichiers listés dans le fichier de configuration,
  4. Démonte le disque précédemment monté,
  5. 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 :

  1. Attend le montage du disque contenant les sauvegardes,
  2. Supprime les sauvegardes antérieures à 300 jours,
  3. Cré une nouvelle sauvegarde des répertoires et fichiers listés dans le fichier de configuration,
  4. Démonte le disque précédemment monté,
  5. 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é

FIXME

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 :

  1. Sauvegarde les données du cron,
  2. Lance une sauvegarde des bases de données à distance et qui les compresse,
  3. Monte le disque distant en local avec SSHFS,
  4. Synchronise l'ensemble des fichiers montés avec rsync,
  5. 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
1)
Copie en ligne dans un dossier puis montage SSHFS du dossier puis rsync → toute la donnée est copiée à chaque fois
2)
Rsync à travers SSH → refus de connexion après un certain temps
3)
Mysqldump en local → temps de traitements trop long
projets/informatique/sauvegarde_donnees.txt · Dernière modification : 2021/04/12 05:29 de alexis