21
2010
Script de sauvegarde de serveur Web

Il est important, pour des raisons évidentes de sécurité (aucun serveur n'étant fiable à 100 %, tant au niveau logiciel qu'au niveau matériel), de sauvegarder régulièrement ses données. Important pour un particulier, cela est tout simplement crucial pour une société informatique : perdre les données de dizaines de clients risque d'avoir un bilan juridique très lourd... :/
Heureusement pour vous, je vous ai contacté un petit script qui sauvegardera sur un FTP distant (OVH fournit généralement un serveur de sauvegarde) toutes vos bases de données et vos fichiers Web. Il ne fonctionnera que sous Linux, étant en Bash. [En même temps, faire un serveur Web sous Windows... Fin du troll. :p]
Nous allons procéder étapes par étapes, afin de ne pas vous effrayer avec un gros pavé de code. A noter que le script est intégralement téléchargeable et librement distribuable et modifiable (avec attribution de paternité tout de même).
Configuration du script
Commençons donc par la définition de quelques variables, qui nous serviront plus tard.
#!/bin/bash
BACKUP_ROOT="/home/backups/"
WEB_FOLDER="/home/www/"
WEB_BACKUP_FOLDER=${BACKUP_ROOT}"web/"
MYSQL_BACKUP_FOLDER=${BACKUP_ROOT}"mysql/"
MYSQL_USER="root"
MYSQL_PASSWORD="password"
FTP_HOST="ftp.backup.net"
FTP_USERNAME="ftpuser"
FTP_PASSWORD="password"
DATE=`date '+%Y-%m-%d'`
Les noms des variables devraient être assez explicites. Néanmoins, quelques explications complémentaires :
- BACKUP_ROOT : dossier où seront stockés temporairement les sauvegardes. On aurait pu mettre /tmp, mais pour des raisons de places disponibles, il est préférable d'enregistrer dans la même partition que celle hébergeant tous les sites Web. En effet, sur un serveur, on attribuera (par exemple) 490 Go pour la partie Web et seulement 10 Go pour la partie racine (incluant /tmp).
- WEB_BACKUP_FOLDER : dossier de sauvegarde des fichiers Web.
- MYSQL_BACKUP_FOLDER : dossier de sauvegarde des bases de données.
- MYSQL_USER et MYSQL_PASSWORD : identifiants à la base de données. Vu que nous sauvegarderons toutes les bases, il est important de mettre les identifiants administrateurs.
- DATE : date du jour. Utile pour renommer le fichier de sauvegarde à envoyer sur le FTP.
A présent, il est temps de faire quelques vérifications. Regardons donc si les fichiers sus-cités existent. Si non, nous les crééons.
[ ! -e ${MYSQL_BACKUP_FOLDER} ] && mkdir -p ${MYSQL_BACKUP_FOLDER}
[ ! -e ${WEB_BACKUP_FOLDER} ] && mkdir -p ${WEB_BACKUP_FOLDER}
On effectue pour cela une double condition avec un ET logique. Ainsi, si la première est fausse, l'interpréteur ne cherchera pas à évaluer la seconde condition (vue que 0 ET n'importe quoi donne toujours 0), donc le dossier ne sera pas créé.
Le -e sert à tester l'existence de l'objet qui suit (ici un dossier), et le point d'exclamation est le NON logique.
Sauvegarde des bases de données MySQL
Il est temps à présent de sauvegarder nos bases de données. Afin de ne pas avoir un fichier SQL extrêmement lourd et difficilement gérable, nous préférerons avoir un fichier par base de données. Voici donc comment procéder.
echo Backuping databases...
for db in `mysql -u ${MYSQL_USER} --password=${MYSQL_PASSWORD} -sBe 'SHOW DATABASES'` ; do
mysqldump -u ${MYSQL_USER} --password=${MYSQL_PASSWORD} ${db} > ${MYSQL_BACKUP_FOLDER}${db}".sql"
done
echo Databases saved.
Tout d'abord, on récupère la liste des bases de données en exécutant la requête SQL SHOW DATABASES. On se connecte donc au serveur MySQL avec les attributs classiques -u (username) et --password afin de pouvoir spécifier le mot de passe directement dans la commande. On lui demande également d'être silencieux (s) afin d'avoir juste le nom des bases de données, sans blabla inutile. Le résultat devra être en mode Batch (B), c'est à dire sans le formatage ASCII sous forme de tableaux : chaque ligne de résultats sera sur une ligne séparée, chaque colonne étant séparée par une tabulation. Enfin, on exécute (e) notre requête.
Ainsi, pour chaque base, on effectue un mysqldump dont le résultat (l'exportation SQL de la base de données) sera dans le dossier de sauvegarde des bases, sous le nom "database.sql".
Sauvegarde des fichiers
Une fois les bases préparées, on prépare la sauvegarde des fichiers Web.
echo Saving FTP files...
for folder in `find ${WEB_FOLDER}* -type d -prune | cut -f 4 -d /`; do
CURRENT_FILE=${WEB_BACKUP_FOLDER}${folder}
tar -cf ${CURRENT_FILE}.tar ${WEB_FOLDER}${folder}
bzip2 ${CURRENT_FILE}.tar
echo ${folder} saved!
done
echo Files saved.
On commence par récupérer la liste des dossiers dans notre répertoire Web. Pour ce faire, la commande find est notre alliée. On lui passe le paramètre -type d afin de ne chercher que des dossiers (directory). Puis, l'option prune permet de ne pas descendre dans l'arborescence, et donc de rester au premier niveau.
Comme nous ne voulons que le nom des dossiers en relatif, nous utiliserons la commande cut. Nous explosons la chaîne au niveau du caractère délimiteur (-d), et prenons le quatrième élément (-f). Ce nombre peut varier selon l'emplacement de vos fichiers Web. :)
Puis, nous archivons tous nos fichiers Web dans des fichiers portant le nom domaine.tar avant de les compresser avec bzip2.
Nos fichiers sont également prêts à être envoyés sur le FTP.
Envoi du fichier sur le FTP
Mais avant, compressons nos deux dossiers (bases de données et fichiers) afin de n'en former plus qu'un seul, et compressons le. Cela sera plus simple à transférer sur le FTP.
echo Archiving all files...
tar -cf ${BACKUP_ROOT}${DATE}.tar ${BACKUP_ROOT}*
bzip2 ${BACKUP_ROOT}${DATE}.tar
echo Backup file ${BACKUP_ROOT}${DATE}.tar.bz2 done.
On peut remarquer que tous nos fichiers porteront comme nom la date du jour au format américain. Par exemple : 2010-05-21.tar.bz2.
Il ne nous reste plus qu'à envoyer nos fichiers sur le serveur.
echo Migrating files on backup server...
ftp -in << EOF
open ${FTP_HOST}
user ${FTP_USERNAME} ${FTP_PASSWORD}
bin
verbose
prompt
lcd ${BACKUP_ROOT}
put ${DATE}.tar.bz2
delete `date --date '7 days ago' '+%Y-%m-%d'`.tar.bz2
bye
EOF
echo Backup successfully completed.
On se connecte au serveur FTP, en entrant les différentes commandes sans passer par un prompt (d'où le -in).
On initialise la connection avec open, puis on s'identifie avec user. On se met en mode binaire (bin) afin de ne pas avoir de problème lors de transfert. On le met en mode silencieux (verbose). On désactive alors le prompt, histoire de ne pas avoir de demande de confirmation lors par exemple de la suppression d'un fichier.
On se place alors dans le dossier local des sauvegardes grâce à la commande lcd (local change directory) et plaçons (put) le fichier de sauvegarde final sur le serveur. Puis, nous supprimons la sauvegarde d'il y a une semaine en se basant sur la date du fichier, et donc son nom. Pour trouver la date d'il y a 7 jours, la commande date est notre amie.
Puis, on dit au revoir au serveur afin de se déconnecter. La sauvegarde est à présent achevée.
N'hésitez pas à télécharger et distribuer ce script : script de sauvegarde de serveur Web.
Automatisation quotidienne de la sauvegarde
Nous allons à présent automatiser l'exécution de ce script tous les jours, grâce à Cron.
Pour ce faire, c'est très simple. Il vous suffit de copier votre script dans le dossier /etc/cron.daily/ et de vous assurer de la présence dans le fichier /etc/crontab de la ligne
0 4 * * * root cd / && run-parts --report /etc/cron.daily
Cela exécutera tous les scripts contenus dans /etc/cron.daily en tant que root à 4h du matin, tous les jours.
Et c'est tout. Il ne vous reste plus qu'à regarder les prochains jours si tout fonctionne comme il faut (point important : on s'aperçoit souvent des erreurs qu'une fois un drame arrivé), et vous pourrez enfin dormir sur vos deux oreilles. :)
Pas terrible comme système. Il est bien mieux de ne pas compresser et d'utiliser rsync avec ssh pour faire des sauvegardes incrémentées.
Perso j'utilise rdiff-backup à la place, c'est encore mieux...
Salut,
Moi je trouve ça intéressant même si le FTP me semble un peu lourd pour sauvegarder une quantité importante de données (des photos ou autres). Je me pencherais plutôt vers rsync pour palier à ce problème, mais le FTP est parfois la seule solution quand on n'a qu'un seul serveur et que sa machine perso ne peut pas être connectée au net pendant quelques temps.
Merci d'avoir partagé ça. Je suis novice en scripts shell, j'ai trouvé ça bien expliqué.
++
Merci de vos retours. Après avoir (enfin) eu le temps de me documenter un peu sur RSync, je ne peux malheureusement pas l'utiliser.
OVH met en effet à disposition un serveur de sauvegarde dont l'accès est uniquement en FTP. Cette solution convient donc aux personnes ne disposant que d'un serveur. Après, effectivement, dans une architecture plus solide avec plusieurs serveurs, RSync est tout à fait utilisable et même bien plus efficace.