Depuis que j'ai mon serveur perso chez moi, je me suis dit qu'il serait intéressant d'automatiser cette sauvegarde. Je n'aurai donc plus à me soucier de le faire "manuellement" une fois par mois.
Voici les scripts que j'ai utilisé, ma procédure, mon automatisation, bref, un petit tuto pour sauvegarder automatiquement ses sites web hébergés loin de chez soi.
I. L'environnement
Je m'occupe actuellement de 3 "gros" sites 'propulsés par Joomla' hébergés chez un hébergeur qui me propose un accès FTP sur le répertoire www ainsi qu'une base de données que j'administre via phpmyadmin.Je vais prendre l'exemple du plus gros site que j'administre et que je veux sauvegarder chez moi automatiquement :
- Un répertoire www de 1,2 Go (1945 répertoires et 20017 fichiers) accessible uniquement en FTP
- Une base de donnée de plusieurs dizaines de Mo et d'une centaine de tables
- La base de données n'est pas accessible à distance (je ne peux pas faire un mysqldump de chez moi sur la base)
- Les modifications sur le www ne sont pas fréquentes, en revanche, les modifications sur la base sont nombreuses et quotidiennes
- Les backups du www via FTP durent environ 1h30, 2h (très grand nombre de petits fichiers et grosses photos)
- Je veux une sauvegarde mensuelle pour le répertoire www et une sauvegarde hebdomadaire pour la base de données.
II. La sauvegarde
La sauvegarde va se dérouler en 3 étapes : la sauvegarde de la base de données (qui, elle aussi, va se découper en 2 temps), la sauvegarde du répertoire www et enfin, l'automatisation de tout cela.
- La base de données
Il faut donc, dans un premier temps, écrire le script de génération de dump. Ce sera un script php que nous appelleront, via curl, dans notre script shell de backup (voir après).
<?phpÀ ma racine www, j'ai créé un répertoire backup dans lequel j'ai ajouté ce script backup.php. Ainsi, dès qu'on appellera la page http://monsite.fr/backup/backup.php, un dump mydatabase.sql.gz sera généré dans ce répertoire backup.
$host = 'myhost';
$user = 'myuser';
$db = 'mydatabase';
$password = 'mypassword';
system("mysqldump --host=$host --user=$user --password=$password $db > $db.sql");
#On vire l'ancienne version gzippée du dump
system("rm $db.sql.gz");
#On gzip la nouvelle version
system("gzip $db.sql");
?>
Ensuite, sur mon serveur je créé mon script shell de backup de mysql :
#!/bin/bash
#Ce script fait un backup de la BDD et la récupère en ftp
#
FICHIER_DUMP='/www/backup/mydatabase.sql.gz'
FICHIER_DEST='/sauvegardes/monsite/mysql/mydatabase.sql.gz'
MAIL_CONTACT='[email protected]'
#On génère le fichier sur le serveur (voir ci-dessus)
curl -s http://monsite.fr/backup/backup.php
sleep 10
#On vire l'ancienne version sur le serveur
rm -f $FICHIER_DEST
#On ramène le fichier sauvegardé via ftp sur notre serveur
lftp ftp://login:pass@ftp.monsite.fr -e "get $FICHIER_DUMP -o $FICHIER_DEST ; quit"
RET=$?
if [ $RET -gt 0 ]
then
MESSAGE="Erreur de dump de la base $FICHIER_DUMP"
echo $MESSAGE | /usr/bin/mail -s "Erreur sur le serveur" $MAIL_CONTACT
fi
Explications :
- La variable FICHIER_DUMP contient le chemin sur le serveur distant du dump généré avec le script php backup.php
- La variable FICHIER_DEST contient le chemin où sera stocké le dump sur mon serveur
- Le MAIL_CONTACT est l'adresse mail où sera envoyé un mail d'erreur (s'il y en a une)
- Grâce à curl, j'interroge mon script php qui, nous l'avons vu, génère mon dump sur le serveur distant
- J'enlève l'ancien backup de mon serveur
- J'utilise le programme lftp pour rapatrier, en FTP, le dump ainsi généré. La commande est assez claire je pense
- Je contrôle que la commande s'est bien passée, le cas contraire, j'envoie un mail
- Le répertoire www
#!/bin/bash
#Ce script fait un backup du www en ftp
#
REP_DUMP='/www/'
REP_DEST='/sauvegardes/monsite/www/'
FICHIER_LOG='/sauvegardes/monsite/backup.log'
MAIL_CONTACT='[email protected]'
echo "*****************************************************************" >> $FICHIER_LOG
/bin/date >> $FICHIER_LOG
echo "Backup en cours" >> $FICHIER_LOG
#Ici, on sauvegarde tout sauf le répertoire compteur
lftp ftp://login:pass@ftp.monsite.fr -e "mirror -e -x cours/ -x logs/ $REP_DUMP $REP_DEST ; quit"
RET=$?
RETOUR=`expr $RETOUR + $RET`
if [ $RET -gt 0 ]
then
MESSAGE="Erreur de backup sur $REP_DEST\n"
echo $MESSAGE | /usr/bin/mail -s "Erreur sur le serveur" $MAIL_CONTACT
fi
/bin/date >> $FICHIER_LOG
/usr/bin/du -hs $REP_DEST >> $FICHIER_LOG
echo "Backup terminé" >> $FICHIER_LOG
echo "*****************************************************************" >> $FICHIER_LOG
echo "Voir fichier $FICHIER_LOG" | /usr/bin/mail -s "Backup monsite OK" $MAIL_CONTACT
Explications :
- La variable REP_DUMP contient le nom du répertoire distant à sauvegarder
- La variable REP_DEST et FICHIER_LOG contiennent respectivement le chemin où sera sauvegardé le site sur mon serveur et le fichier de log qu'il génèrera
- Le MAIL_CONTACT est l'adresse mail où sera envoyé un mail d'erreur (s'il y en a une)
- Je commence par écrire l'heure de départ du script dans le fichier de log puis "Backup en cours"
- J'utilise, là aussi, lftp pour rapatrier le site. La commande mirror permet d'avoir une copie parfaite du site distant (les répertoires supprimées du www seront effacés aussi sur mon serveur, etc.). Le paramètre -x me permet d'exclure certain répertoires de la sauvegarde. Voir cette page pour plus de détails sur la commande lftp.
- Je contrôle que la commande s'est bien passée, le cas contraire, j'envoie un mail
- J'écris la date et l'heure de fin du script dans le fichier de log.
Notez qu'on pourrait, si on voulait être bien synchro, lancer l'exécution du script de sauvegarde de la base de données dans ce script. Ainsi, on ferait un backup de la base et on rapatrierait l'ensemble en même temps.
III. L'automatisation
Une fois que ces scripts sont prêts (ont peut les tester "à la main" pour s'en assurer), il ne nous reste plus qu'à tout automatiser grâce au cron. Pour ceux qui ne connaissent pas le cron, j'en ai fait un cours dans cet article.Pour faire rapide, voici ma crontab :
#Backup des BDD des sites distants (hebdomadaire, le dimanche soir)
45 23 * * 0 /home/moi/scripts/backup_mysql_sitedistant.sh >/dev/null 2>&1
#Backup du www des sites distants (une fois par mois, la premiere nuit)
0 1 1 * * /home/moi/scripts/backup_www_sitedistant.sh >/dev/null 2>&1
Explications :
- J'exécute mon script de sauvegarde de la base de données tous les dimanches à 23h45
- J'exécute mon script de sauvegarde du répertoire www tous les 1er du mois à 1h du matin
IV. Conclusion
Voici donc comment je sauvegarde mes sites distants, en attendant de tous les remettre directement sur mon serveur, ce qui simplifiera bien les choses.Je pense que ces scripts sont perfectibles, si vous avez des idées, n'hésitez pas à me les suggérer, je suis toujours à l'affut des bons conseils :)