Le boitier de mon serveur permet d'accueillir deux disques dur format 2"1/5. Le premier étant utilisé pour mon système, j'ai décidé d'en ajouter un deuxième et de répliquer les données du premier dessus.

J'aurai pu choisir de mettre en place un système de entre les deux disques mais j'ai préféré opter pour une synchronisation d'un disque vers l'autre plusieurs fois par semaine. Cela me permet de revenir en arrière si besoin. Par exemple, je fais une mise à jour qui se passe mal ou j'écrase un fichier involontairement. Je peux facilement récupérer la configuration ou le fichier de la veille, stocké sur mon deuxième disque, chose qui aurait été impossible en RAID1.

J'ai organisé ma sauvegarde en deux étapes : la base de données MySQL et les répertoires/fichiers de mon système.

Sauvegarde des bases de données

J'ai écrit un script bash qui me permet de faire des dumps de mes bases de données :

#!/bin/sh
#
# Il faut que le user dump ait un droit general de SELECT et RELOAD
 
MYSQL_BIN_PATH=/usr/bin
MYSQL_DATA_PATH=/var/lib/mysql
MYSQL_HOME=/mysql
FIC_ERR=$MYSQL_HOME/dump/erreur.txt
HOSTNAME=`hostname`
SYSTEME="[email protected]"
 
USER=dump
PASSWD="xxdumpxx"
 
/bin/rm $MYSQL_HOME/dump/*
 
LISTE_BASES=`/usr/bin/find $MYSQL_DATA_PATH/* -maxdepth 0 -type d -printf "%f\n" `
for DB in $LISTE_BASES
do
DATABASE=`echo $DB | sed 's/@002d/-/'`
 
echo base $DATABASE
$MYSQL_BIN_PATH/mysqldump -u $USER --password=$PASSWD --opt --databases --result-file $MYSQL_HOME/dump/$DATABASE.dump $DATABASE 2>>$FIC_ERR
 
RET=$?
RETOUR=`expr $RETOUR + $RET`
if [ $RET -gt 0 ]
then
MESSAGE="$MESSAGE Erreur de dump de la base $DATABASE\n"
fi
 
/bin/gzip $MYSQL_HOME/dump/$DATABASE.dump
 
done
 
/bin/chmod -R 600 $MYSQL_HOME/dump
/bin/chmod -R 700 $MYSQL_HOME/dump*
 
if [ $# -gt 0 ] && [ $RETOUR -gt 0 ]
then
echo $MESSAGE | /bin/mail -s "mysql sur $HOSTNAME. Erreur dump des bases" $SYSTEME
fi

Ce script va interroger le nom de mes différentes bases de données stockées sur mon serveur et en fait un dump séparé. Au final, j'obtiens un répertoire /mysql/dump/ qui contiendra les différents dumps de mes différentes bases de données.

Note : L'utilisateur qui fera le dump doit avoir les droits de SELECT, RELOAD et LOCK TABLES sur les bases de données.

Sauvegarde des répertoires/fichiers de mon serveur

Une fois mes bases de données sauvegardées, je vais copier tous les fichiers importants sur le deuxième disque dur. Pour cela, j'utilise rsync :

#!/bin/bash
# $? = code de retour de la dernière commande. 0 si pas de problème
# on additionne les codes de retour à chaque fin de chaque commande, si ça dépasse 0, c'est qu'il y a eu une erreur quelque part
 
/bin/bash /scripts/dump_mysql.sh
 
FICHIER_LOG="/scripts/backup_rsync.log"
/bin/rm $FICHIER_LOG
/usr/bin/touch $FICHIER_LOG
 
echo "*****************************************************************" >> $FICHIER_LOG
/bin/date >> $FICHIER_LOG

echo "*************Dump MySQL *************" >> $FICHIER_LOG
/usr/bin/rsync -rlpgotD --stats --delete --force /mysql/ /backup/mysql/ >> $FICHIER_LOG
RET=$?
RETOUR=`expr $RETOUR + $RET` 
echo "*************Configuration Apache /etc/apache2 *************" >> $FICHIER_LOG
/usr/bin/rsync -rlpgotD --stats --delete --force /etc/apache2/ /backup/etc/apache2/ >> $FICHIER_LOG
RET=$?
RETOUR=`expr $RETOUR + $RET`
echo "*********************Home /home/*********************" >> $FICHIER_LOG
/usr/bin/rsync -rlpgotD --stats --delete --force /home/ /backup/home/ >> $FICHIER_LOG
RET=$?
RETOUR=`expr $RETOUR + $RET`
/bin/date >> $FICHIER_LOG
RET=$?
RETOUR=`expr $RETOUR + $RET`
echo "*****************************************************************" >> $FICHIER_LOG
 
if [ $RETOUR -ne 0 ]
then
echo "Le script de rsync a echoue. Code erreur : "$RETOUR | /usr/bin/mail -s "Erreur script rsync" mail@me.fr
fi

Ce script va faire une sauvegarde (miroir) des répertoires /home/, /mysql/ et /etc/apache2/ vers /backup/home/, /backup/mysql/ et /backup/etc/apache2. /backup étant le point de montage de mon disque de sauvegarde.

Voici une explication des arguments de rsync :

  • rsync : appelle le programme rsync
  • -r : parcours le dossier indiqué et tous ses sous-dossiers
  • -l : copie les liens symboliques comme liens symboliques
  • -t : préserve les dates
  • -g : préserve le groupe
  • -o : mettre le propriétaire du fichier de destination identique à celui du fichier source
  • -D : préserve les périphériques
  • -p : provoque la mise à jour des permissions sur la destination pour qu'elles soient identiques aux permissions sur la source.
  • --force : force la suppression de répertoires même non-vides
  • --stats : affiche quelques statistiques de transfert de fichiers, ce qui permet de vérifier l'efficacité de la sauvegarde.
  • --delete : efface avant le transfert les fichiers qui n'existent pas sur la source.
On voit qu'au début de ce script appel le script de dump des bases de données. Il nous suffit donc d'appeler uniquement ce dernier script pour avoir une sauvegarde des bases de données et de nos répertoires sur /backup.

Automatisation de la sauvegarde

Je n'ai plus qu'à appeler le script ci-dessus à la fréquence à laquelle je souhaite faire mes sauvegardes dans le cron. Voici ma crontab :
30 23 * * 1,4,6 /root/scripts/backup_rsync.sh >/dev/null 2>&1

Ainsi, tous les lundis, jeudis et samedi à 23h30, je sauvegarde les répertoires importants de mon disque 1 vers mon disque 2.


Bonus

Je fais également une sauvegarde de mes bases de données et de mon répertoire www sur une clé USB une fois par mois avec ce script :
#!/bin/bash
# $? = code de retour de la dernière commande. 0 si pas de problème
# on additionne les codes de retour à chaque fin de chaque commande, si ça dépasse 0, c'est qu'il y a eu une erreur quelque part
 
MAIL_CONTACT='[email protected]'
FICHIER_LOG="/root/scripts/logs/backup_usb.log"
REP_DEST="/mnt/usb/`date +%d%m%Y`"
/bin/rm $FICHIER_LOG
/usr/bin/touch $FICHIER_LOG
 
/bin/mount /dev/sdc1 /mnt/usb/
/bin/rm -rf /mnt/usb/*
/bin/mkdir $REP_DEST
 
echo "*****************************************************************" >> $FICHIER_LOG
/bin/date >> $FICHIER_LOG
 
echo "*************Copie des répertoires /mysql *************" >> $FICHIER_LOG
/bin/cp -pr /mysql/ $REP_DEST
RET=$?
RETOUR=`expr $RETOUR + $RET`
echo "*************Copie du répertoire /www *************" >> $FICHIER_LOG
/bin/cp -pr /www/ $REP_DEST
RET=$?
RETOUR=`expr $RETOUR + $RET`
 
/bin/date >> $FICHIER_LOG
RET=$?
RETOUR=`expr $RETOUR + $RET`
echo "*****************************************************************" >> $FICHIER_LOG
 
if [ $RETOUR -ne 0 ]
then
echo "Le script de backup USB a echoue. Code erreur : "$RETOUR | /usr/bin/mail -s "Erreur script backup USB" $MAIL_CONTACT
fi
 
/bin/umount /mnt/usb/


Si vous cherchiez des pistes pour sauvegarder votre serveur, j'espère vous avoir un peu éclairé.
Comme toujours, si vous avez des suggestions à me proposer ou si vous souhaitez des précisions supplémentaires sur ces scripts, n'hésitez pas à demander.
Par ailleurs, je serais curieux de connaitre vos moyens de sauvegarde en auto-hébergement :)