Sauvegarder automatiquement ses sites web distants chez soi

I. L’environnement

Je m’occupe actuellement de 3 "gros" sites ‘propulsés par ‘ 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.
      Voila pour les données de base. Voici comment je fais pour sauvegarder tout ça.

    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
    Comme je vous l’ai dit, je ne peux pas accéder directement à la base depuis chez moi. Si j’avais pu, un simple mysqldump aurait fait l’affaire. Si vous avez un accès distant sur votre base, vous pouvez passer cette étape. Ici, c’est un peu plus compliqué : il faut générer un mysqldump sur la machine distante puis récupérer le dump en FTP.

    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
    $host = ‘myhost’;
    $user = ‘myuser’;
    $db = ‘mydatabase’;
    $password = ‘mypassword’;

("mysqldump –host=$host –user=$user –password=$password $db > $db.sql");

On vire l’ancienne version gzippée du dump

("rm $db.sql.gz");

On gzip la nouvelle version

("gzip $db.sql");
?> À 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.

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:[email protected] -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

lftp ftp://login:[email protected] -e "rm $FICHIER_DUMP ; quit"
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
    • Enfin, je supprime le dump sur le site distant (par précaution, merci JN)
      On a désormais un script qui génère le dump sur le site distant et le ramène sur notre serveur. Nous verrons après pour l’automatisation de ce script.
  • Le répertoire www
    Maintenant que ma base de données est sauvegardée, je vais sauvegarder mon répertoire www. Pour ce faire, j’ai fait ce script :

    !/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:[email protected] -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_DESTn"
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 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.
      On a désormais un script qui récupère et synchronise notre site distant sur notre serveur.
      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 🙂

    Edit : Pour ceux qui essayent, les chemins d’accès on tous été changés dans mes scripts d’exemple et c’est pas mon blog que je sauvegarde automatiquement, donc n’essayez plus d’aller sur generation-linux.fr/backup 😉