29 jan
Shell : Backup local et ftp de bases de données Mysql
Comme beaucoup de personnes qui ont un ou plusieurs serveurs dédiés à gérer, j’ai eu l’envie (ou plutôt l’obligation) d’utiliser un système me permettant de sauvegarder mes bases de données tous les jours.
J’ai trouvé pas mal de scripts sur internet faisant ça, la plupart sont très bien, mais il manquait toujours un ou deux petits trucs ou des fois la méthode ne me plaisait pas. Je me suis donc retroussé les manches et je me suis codé mon script tout seul comme un grand. ![]()
L’idée du script
Mon idée était simple : partir avec une distribution Gentoo release 2 (ovh), n’ajouter aucune application dessus et ne se servir que de mon script pour sauvegardes les bases de données.
Le script devait pouvoir sauvegarder chaque base de données indépendemment et non pas toutes en un seul fichier comme on le voit souvent. En cas de réinstallation on ne doit pas être obligé de tout réinstaller à partir d’un dump. Si on a 10 clients ayant chacun une base de données pour son site, je me vois mal avoir à expliquer à 9 clients que leur base de données à été réinstallée avec les données de la veille parce que le 10ème client à perdu des données dans sa base.
J’avais aussi ces quelques exigences :
- Le script devait aussi lister automatiquement toutes les bases de l’utilisateur et non pas inscrire les noms des bases en dur comme je l’ai vu souvent
- Purger proprement les archives trop anciennes en local tout comme en FTP
- Générer un rapport d’actions dans un fichier log temporaire, l’envoyer par mail et l’inscrire dans un log général
- Donner la possibilité d’envoyer par mail en pièce jointe l’archive générée (enfin, si le backup n’est pas trop lourd)
Le script
Le script est beaucoup commenté, normalement c’est assez simple à comprendre.
#!/bin/bash # ------------------------------------------------------------------- # # BACKUP de toutes les bases MySQL d'un utilisateur # ------------------------------------------------- # # Auteur : Denis Métral-Deschamps (Denis Dee Jay) # Site : http://www.denisdeejay.com/ # Date : 29/01/2010 # # Principe : # --------- # Liste les bases de données d'un utilisateur et les sauvegarde # indépendamenent dans un fichier .sql puis compresse les # fichiers dans un tar.gz. # Permet d'uploader sur un serveur FTP, de purger les anciennes # archives en local et sur le ftp. Permet aussi de recevoir # l'archive par mail. # Renseigne ses actions dans un fichier log et poste par mail # un rapport de ses actions (activable ou non) # # Dépendance : # ----------- # Nécessite le client FTP NCFTP : http://www.ncftp.com/ncftp/ # # Reste a faire : # -------------- # - Activer ou non le backup FTP # - Trouver une meilleur solution pour purger # - les anciennes archives sur le FTP # ------------------------------------------------------------------- # # --------------------------------------------------------------------- # # PARAMETRES DU SCRIPT # --------------------------------------------------------------------- # USER="user" # Nom d'utilisateur MySQL DBPASS="pass" # Pass utilisateur EMAIL="mail@mail.com" # Email MAILSEND=1 # Post d'un mail? (1=Oui, 0=Non) JOINDB=0 # Envoyer l'archive en piece jointe au mail? (1=Oui, 0=Non) SUJETMAIL="Backup MySQL quotidien" # Sujet du mail BACKUPDIR="/home/backup/sql/" # Rep de backup (temporaire si KEEPLOCAL = 0). Ne pas oublier le "/" à la fin (important !!) OLD_DAYS=5; # Nombre de jours où les backup sont conservés K_DAYS=`date --date $OLD_DAYS' days ago' "+%Y-%m-%d"`; # On construit la recherche des anciens fichiers LOG="/home/log/backup_sql.log"; # Log des backup DATE="$(date +"%Y-%m-%d")"; # Date du jour DATE_NOW=`date +"%d/%m/%Y - %H:%M:%S"`; # Date et heure en temps réel (pour le log) ARCHIVE="mysql_backup_"$DATE".tar.gz"; # Noms des archives OLD_ARCHIVE="mysql_backup_"$K_DAYS".tar.gz"; # Les anciennes archives KEEPLOCAL=1 # Garder une copie locale? (1=Oui, 0=Non) FTP_BACKUP=1 # Copie sur FTP? (1=Oui, 0=Non) FTP_SERVER="ftp.backup.com" # Serveur FTP FTP_USER="login_ftp" # Login utilisateur FTP FTP_PASS="pass_ftp" # Pass utilisateur FTP FTP_DIR="/bdd" # Répertoire sur le FTP (par exemple : /backups/serveur1/bdd) NCFTPPUT="/usr/bin/ncftpput" # Emplacement de ncftpput NCFTP="/usr/bin/ncftp" # Emplacement de ncftp # --------------------------------------------------------------------- # # FIN DES PARAMETRES, ne rien changer ensuite # # --------------------------------------------------------------------- # # On se place dans le rep cd $BACKUPDIR; # creation du log temporaire TMP_LOG="tmp_backup.log"; >$TMP_LOG; echo "-- Rapport généré automatiquement par $(basename $0)" >> $TMP_LOG; echo "" >> $TMP_LOG; # et c'est partiecho "["$DATE_NOW"] - MySQL : DEBUT sauvegarde des bases" >> $TMP_LOG; # On crée un rep temporaire qui contiendra les sauvegardes if [ ! -d $DATE ]; then mkdir $DATE"/"; chmod 500 $DATE; fi # On liste toutes les bases de données auquel l'utilisateur a access DATABASES="$(mysql -u $USER -p$DBPASS -Bse 'show databases;')"; # Si une erreure survient pendant la liste des bases if [ ! $? -eq 0 ]; then rm -rf $DATE; echo "["$DATE_NOW"] - Une erreure s'est produite pendant le listage des bases de données" >> $TMP_LOG; cat $TMP_LOG >> $LOG; rm $TMP_LOG; exit 1; fi # Boucle : pour chaque base ... for BASE in $DATABASES do # Analyse de la base mysqlcheck -u $USER -p$DBPASS -c -a $BASE > /dev/null echo "["$DATE_NOW"] - Sauvegarde de la base '"$BASE"'" >> $TMP_LOG; # Sauvegarde de la base mysqldump -u $USER -p$DBPASS --add-drop-database --add-drop-table --complete-insert --routines --triggers --allow-keywords --max_allowed_packet=50M --force $BASE -R > $DATE"/"$BASE".sql"; # Note sur les options de mysqldump : # --add-drop-database = Ajoute en tete de fichier la requete "drop database" # --add-drop-table = Ajoute devant chaque creation de table la requete "drop table" # --complete-insert = Utilise les insertions etendues (compresse plus mais ATTENTION, si une erreure dans la requete, tous les champs sont bloques) # --routines = http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_routines # --trigers = http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_triggers # --allow-keywords = Permet la création de colonnes ayant des noms de mots réservés. # --max_allowed_packet = Lors de la création de commandes d'insertions etendues, mysqldump va créer des lignes ayant une taille maximale de max_allowed_packet octets # --force = Continue même si une erreur SQL survient durant l'export. # --opt = Identique à --quick --add-drop-table --add-locks --extended-insert --lock-tables. Obtient l'export le plus rapide à importer dans MySQL. # Une erreure pendant la sauvegarde de la base if [ ! $? -eq 0 ]; then rm -rf $DATE; echo "["$DATE_NOW"] - Une erreure est survenue pendant la sauvegarde de la base '"$BASE"'" >> $TMP_LOG; cat $TMP_LOG >> $LOG; rm $TMP_LOG; exit 1; fi done # On construit l'archive contenant les sauvegardes tar -czf $ARCHIVE $DATE"/"; # Si une erreure survient pendant la création de l'archive if [ ! $? -eq 0 ]; then rm -rf $DATE; echo "["$DATE_NOW"] - Une erreur est survenue pendant la creation de l'archive : '"$ARCHIVE"'" >> $TMP_LOG; cat $TMP_LOG >> $LOG; rm $TMP_LOG; exit 1; fi FILESIZE=`ls -lh ${ARCHIVE} | awk '{print $5}'` echo "["$DATE_NOW"] - L'archive '"$ARCHIVE"' ("$FILESIZE") a bien été crée" >> $TMP_LOG; # On supprime le répertoire temporaire rm -rf $DATE; # On supprime les archives trop anciennes et on renseigne le log echo "["$DATE_NOW"] - Recherche et supprime les archives ayant plus de "$OLD_DAYS" jours" >> $TMP_LOG; find $BACKUPDIR -maxdepth 1 -type f -ctime +$OLD_DAYS -exec rm -v {} \; >> $TMP_LOG ; # Upload sur le serveur FTP echo "["$DATE_NOW"] - Debut d'upload sur le FTP : "$FTP_SERVER >> $TMP_LOG; $NCFTPPUT -m -u $FTP_USER -p $FTP_PASS $FTP_SERVER $FTP_DIR $ARCHIVE OSTAT="$?" case $OSTAT in 0) MESS="Succès.";; 1) MESS="Erreur : ne peut se connecter à l'hôte $FTPH.";; 2) MESS="Erreur : ne peut se connecter à l'hote $FTPH - temps dépassé.";; 3) MESS="Transfert échoué.";; 4) MESS="Transfert échoué - temps dépassé.";; 5) MESS="Changement de répertoire échoué.";; 6) MESS="Changement de répertoire échoué - temps dépassé.";; 7) MESS="URL mal formé.";; 8 ) MESS="Erreur d'utilisation. Peut être que votre version de ncftpput ($NCFTPPUT) est trop ancienne";; 9) MESS="Erreur dans le fichier de configuration de login.";; 10)MESS="Initialisation de la librairie échouée.";; 11) MESS="Initialisation de session échouée.";; *) MESS="Erreur inconnue";; esac echo "["$DATE_NOW"] - Fichier : $ARCHIVE --> $FTP_DIR" >> $TMP_LOG; echo "["$DATE_NOW"] - Status de l'upload : $MESS" >> $TMP_LOG; # on supprime la plus vieille archive sur le ftp # pour l'instant, pas trouvé mieux que de supprimer la dernière archive ... pas trouvé de find ou autre sur ncftp echo "["$DATE_NOW"] - Suppression de l'archive la plus vieille sur le ftp" >> $TMP_LOG; $NCFTP -u $FTP_USER -p $FTP_PASS $FTP_SERVER << EOF rm $FTP_DIR"/"$OLD_ARCHIVE quit EOF # Suppression de la sauvegarde locale si demande if [ "$KEEPLOCAL" = 0 ]; then rm $BACKUPDIR* fi #Envoi du log temporaire par mail if [ "$MAILSEND" = 1 ]; then if [ "$JOINDB" = 1 ]; then (cat $TMP_LOG; uuencode $ARCHIVE $ARCHIVE) | mail -s "$SUJETMAIL ("$DATE")" $EMAIL echo "["$DATE_NOW"] - Email envoyé avec pièce jointe" >> $TMP_LOG; else mail -s "$SUJETMAIL ("$DATE")" $EMAIL < $TMP_LOG; echo "["$DATE_NOW"] - Email envoyé sans pièce jointe" >> $TMP_LOG; fi fi # On finalise le log temporaire, place son contenu dans le log permanent et supprimer le log temporaire echo "["$DATE_NOW"] - FIN du backup" >> $TMP_LOG; echo "" >> $TMP_LOG; cat $TMP_LOG >> $LOG; rm $TMP_LOG; exit
Pour les prochaines mises à jour
- Rendre activable le backup FTP ou non
- Trouver une meilleur solution pour purger les anciennes archives sur le FTP ; Si quelqu’un à une idée en utilisant NCFTP ou non, elle est bienvenue
Utilisation du script
Pour utiliser ce script de backup c’est très simple, il vous suffit de faire seulement ces 3 choses :
1) Régler vos paramètres
2) Un chmod +x pour le rendre executable (a personnaliser au nom du fichier)
chmod +x /root/mes_scripts/mon_fichier.sh
3) Ajout d’une tache cron (a personnaliser bien entendu)
crontab -e 00 05 * * * /root/mes_scripts/mon_fichier.sh
Si vous avez des idées pour améliorer ce script, n’hésitez pas à poster des commentaires


Posté par Denis Dee Jay le 29 janvier 2010 à 16 h 58 min
Faire attention, à la ligne contenant :
» dans le billet sinon
8 ) MESS= »Erreur d’utilisation.
j’ai mis un espace entre 8 et ) qu’il faudra retirer.
ca me mettait le smiley »
Posté par Shell : Backup multiples et séparés de comptes FTP – DenisDeeJay.com » My Web le 2 février 2010 à 2 h 07 min
[...] le script shell de sauvegardes des bases de données mysql je m’attaque à la sauvegardes des comptes FTP liés aux sites internet sur l’un de mes [...]