Le petit script de backup de Nono

[Edit du 26/05/2013 : J'ai mis le 'Nono's Backup" sur Github, à toute fin utile]

J'utilisais "historiquement" et surtout par manque de temps libre, la solution backup-manager jusqu'à il y a environs 2/3 semaines. Ca me permettait d'avoir une rotation des logs sur quelques jours, un backup automatique programmable vers un serveur FTP (qui est comprise dans l'offre OVH qui héberge m0le.net). Tout allait bien, jusqu'au jour ou les backup ne se faisait plus correctement...

Pour faire court

Ça a d'abord commencé par la non suppression en local des fichiers. Ca n'a pas loupé :

  • serveur rempli
  • pas mal de services qui foirent ...

Quand on garde cinq jours de backup, et que le serveur dois se prendre dans la tronche cinq fois la taille du disque (à peu de choses près), c'était à prévoir.

J'ai pu corriger (tant bien que mal) le tire, en supprimant quasi manuellement les dossiers non supprimés en local... Fastidieux !

La goutte d'eau, ce fut quand les backup ne s'envoyait pas sur le FTP, mais qu'ils étaient supprimés en local.

Le pompon : j'avais juste plus du tout de backup...

Après avoir cherché un peu la cause de pourquoi et du comment, je me suis quand même tourné vers ma propre solution de backup.

Alors forcément, c'est sans aucun doute loin d'être la meilleure solution, mais elle me convient parfaitement, et me permet de :

  • sauvegarder mes bases de données
  • sauvegarder mes dossiers à archiver
  • faire des exclusions dans mes dossiers de sauvegarde
  • supprimer les dossiers locaux de sauvegarde (inutile ?!?)
  • envoyer les sauvegardes sur un FTP distant.
  • garder toujours cinq jours de sauvegarde.
  • recevoir un rapport tous les jours par mail.

Le script Nonos_Backup_1.0

Vous avez besoin de :

  • mysqldump : pour faire le dump de la base de donnée ...
  • tar : pour créer des paquets pour un dossier donnée (ici, au format tar.bz2)
  • lftp : un outils en ligne de commande qui permet d’exécuter facilement des scripts vers les FTP (et bien d'autre, ce tools est vraiment génial je trouve !)

Sans plus attendre, je vous montre donc le Nonos_Backup_1.0 :

#!/bin/bash
# Auteur :      Nono @ blog.m0le.net
# Date :        06/02/2012
# Version :     1.0
# MaJ :         16/02/2012

#############
# Variables #
#############

# Une date est généré, pour avoir la date de début de processus de backup
date_start=`date +'%d/%m/%Y @ %H:%M:%S'`;

# Choix du format de la date utilisé pour les dossiers
format_date='%d%m%Y'

# Variable de date du jour, en fonction du format choisi
date=`date +${format_date}`;

# Le nombre de jour que vous souhaitez archiver
keepday="5";

# Calcul du nombre de jour, remontant à plus de "$keepday" jour(s)
keepdate=`date --date "-${keepday} days" +${format_date}`;

# Le répertoire de création du backup journalier
backup_dir='/home/archives/'${date};

# Le chemin du rapport (celui-ci sera gardé, et envoyé par mail)
rapport='/home/archives/rapport.log';

# Le mot de pass root de la base de donnée
sql_password='lepassdeladb';

# L'ip ou le hostname de votre serveur FTP
ftp_host='ftphost';

# L'utilisateur de votre serveur FTP
ftp_user='user';

# Le mot de passe de votre serveur FTP
ftp_pass='pass';

# L'adresse mail qui recevra le rapport
mail='mail@du_rapport.com';

##########
# Script #
##########

# Création du repertoire de backup + Initialisation du rapport
mkdir -p ${backup_dir};
echo 'Rapport du '${date_start} > ${rapport};
echo " " >> ${rapport};

# Les répertoires + exclusions des dossiers à archiver ...
# (à modifier à la main ... On peut pas tout avoir dans la vie)
# Syntaxe :
#     tar jcf le_nom_de_larchive.tar.bz2 --exclude='/le/repertoire/a/exclure' --exclude='/eventuellement/le/deuxieme/repertoire/a/exclure' /le/dossier/a/archiver/ 2>/dev/null
tar jcf ${backup_dir}/m0le.net-${date}-home-m0le.tar.bz2 --exclude='/home/m0le/ledossieraexclure1' --exclude='/home/m0le/ledossieraexclure2'  /home/m0le/ 2>/dev/null 
tar jcf ${backup_dir}/m0le.net-${date}-home-blog.tar.bz2 --exclude='*.mp3' /home/blog/ 2>/dev/null 
tar jcf ${backup_dir}/m0le.net-${date}-var-lib-mysql.tar.bz2 /var/lib/mysql/ 2>/dev/null 
tar jcf ${backup_dir}/m0le.net-${date}-etc.tar.bz2 /etc 2>/dev/null

#Création du dump de la base de donnée avec mysqldump
mysqldump -u root --password=${sql_password} --all-databases | gzip -9 > ${backup_dir}/dump_${date}.sql.gz;
echo "Etat du dossier local :" >> ${rapport};
ls -lh ${backup_dir} -I rapport* >> ${rapport};
echo " " >> ${rapport};

# Envoie du dossier de sauvegarde vers le FTP
echo "Etat du dossier distant :" >> ${rapport};
lftp ftp://${ftp_user}:${ftp_pass}@${ftp_host} -e "mirror -R ${backup_dir} /${date} ; ls ${date} ; quit" >> ${rapport};
echo " " >> ${rapport};

# Suppresion du dossier en local
echo "Suppression du dossier local : ${backup_dir}" >> ${rapport};
rm -rf ${backup_dir};
echo " " >> ${rapport};

# Suppression du dossier distant de plus de "$keepday" jour(s)
echo "Suppression du dossier distant de plus de ${keepday} jours : ${keepdate}" >> ${rapport};
echo " " >> ${rapport};

# Copie de l'état des dossiers sur le FTP pour le rapport
echo "Etat du FTP :" >> ${rapport};
lftp ftp://${ftp_user}:${ftp_pass}@${ftp_host} -e "rm -rf ${keepdate} ;ls ; quit" >> ${rapport};

# Une date est généré, pour avoir la date de fin de processus de backup
date_end=`date +'%d/%m/%Y @ %H:%M:%S'`;
echo " " >> ${rapport};

#Finalisation du rapport + envoie par mail
echo 'Fini le '${date_end} >> ${rapport};
mail -s "Backup ${date}" ${mail} > ${rapport};

Au niveau du rapport, ca vous chie un truc a peu de chose près comme ca :

Rapport du 17/02/2012 @ 06:39:58

Etat du dossier local :
total 2,0G
-rw-r--r-- 1 root root   11M 17 févr. 07:05 dump_17022012.sql.gz
-rw-r--r-- 1 root root 1014K 17 févr. 07:05 m0le.net-17022012-etc.tar.bz2
-rw-r--r-- 1 root root  123M 17 févr. 07:04 m0le.net-17022012-home-blog.tar.bz2
-rw-r--r-- 1 root root  1,9G 17 févr. 07:03 m0le.net-17022012-home-m0le.tar.bz2
-rw-r--r-- 1 root root  9,9M 17 févr. 07:04 m0le.net-17022012-var-lib-mysql.tar.bz2

Etat du dossier distant :
drwxr-xr-x    2 100      100            10 Feb 17 08:27 .
drwxr-xr-x    8 100      100             9 Feb 17 06:24 ..
-rw-r--r--    1 100      100      11332377 Feb 17 06:05 dump_17022012.sql.gz
-rw-r--r--    1 100      100       1037695 Feb 17 06:05 m0le.net-17022012-etc.tar.bz2
-rw-r--r--    1 100      100      128892717 Feb 17 06:04 m0le.net-17022012-home-blog.tar.bz2
-rw-r--r--    1 100      100      1950907191 Feb 17 06:03 m0le.net-17022012-home-m0le.tar.bz2
-rw-r--r--    1 100      100      10312445 Feb 17 06:04 m0le.net-17022012-var-lib-mysql.tar.bz2
Total : 1 répertoire, 5 fichiers, 0 liens symboliques
Nouveau : 5 fichiers, 0 liens symboliques
Modifié : 0 fichiers, 0 liens symboliques
2102482425 octets transférés en 4956 secondes (414.3Ko/s)
To be removed: 0 directories, 0 files, 0 symlinks

Suppression du dossier local : /home/archives/17022012

Suppression du dossier distant de plus de 5 jours : 12022012

Etat du FTP :
drwxr-xr-x    8 100      100             9 Feb 17 06:24 .
drwxr-xr-x    8 100      100             9 Feb 17 06:24 ..
-r--------    1 100      100            85 Feb 17 01:00 .banner
drwxr-xr-x    2 100      100             7 Feb 13 06:13 13022012
drwxr-xr-x    2 100      100             7 Feb 14 06:10 14022012
drwxr-xr-x    2 100      100             7 Feb 15 06:13 15022012
drwxr-xr-x    2 100      100             9 Feb 16 23:13 16022012
drwxr-xr-x    2 100      100            10 Feb 17 08:27 17022012
drwxr-xr-x    2 100      100             5 Feb  5 14:01 20012012

Fini le 17/02/2012 @ 08:27:48

N'hésitez pas à me faire par de vos remarques et/ou améliorations, je me réserve juste le droit de les implémenter ... ou pas 🙂

Comments

Comment by TiTi on 2012-02-18 19:10:06 +0100

rsync peut aussi bien servir

Comment by Nono on 2012-02-18 19:13:50 +0100

Je n'ai pas dit le contraire 🙂
J'ai découvert lftp, et j'ai vu qu'il était très simple de scripter des commandes avec, en plus de pouvoir se connecter facilement à un ftp.
Avant ca, je trouvais un peu fastidieux, les méthodes pour simplement me connecter à un FTP et afficher la liste des dossiers/fichiers s'y trouvant.

Disons que c'est une alternative.

Comment by Olivier on 2012-02-18 21:41:52 +0100

Problème avec tes balises strongs !

Comment by Nono on 2012-02-18 22:48:25 +0100

Tiens, oui, du coup, il changeait aussi mes > et < par leur valeurs html (> et < ) J'ai donc édité la chose, et virer les strong ... Il faudra un peu réfléchir et/ou comprendre le truc pour pouvoir l'utiliser ^^

Comment by Mumzi on 2012-02-25 20:59:59 +0100

Pour avoir rencontré plusieurs fois le problème sur différents scripts de backup, je te propose quelques améliorations qui pourront toujours servir :

  • Garder les N (keepday) derniers rapports, au cas où le mail ne soit pas envoyé (problème mail ou erreur lors de l'exécution du script).
  • Vérifier l'existence des dossiers avant/après création/suppression.
  • Récupérer le code de sortie des commandes tar (un simple echo $? par tar suffirait + mise en forme ou affichage uniquement si >0), l'utilisation de 2>/dev/null étant assez brutale (erreur lors du backup, espace disque local insuffisant...etc.).

Comment by Nono on 2012-02-26 23:06:19 +0100

Merci du feedback Mumzi, si je trouve le temps, j'essayerais de sortir une v1.1 😉
Autant les rapports, je n'y avait pas pensé, mais le test des dossiers, c’était par pur flemme 😀

Quand au code de sortie de commande ... Je n'en voyait pas l’intérêt, maintenant oui (on a pas tous nagios ou un moyen de check l’état d'utilisation de ces disques sur son serveur...)

Comment by nadca on 2012-12-29 08:33:43 +0100

Si je ne m'abuse, il y a une coquille, ligne 66 : il manque un dollar devant un nom de variable (mysqldump -u root --password={sql_password})

Par ailleurs, le 'echo " " >> ${rapport}' est peut-être inutile ; s'il s'agit juste de sauter une ligne un simple 'echo >> $rapport' suffira plutôt que rajouter un espace seul sur sa ligne ; mais j'ai peut-être mal compris le but de ce echo.

Comment by Nono on 2012-12-29 20:15:54 +0100

Effectivement, mon plugin (crayon) d'affichage de code, masquait le signe $ que j'ai dû doubler ...
Comprend pas 🙂

Concernant les echo, je sais que :
echo >> file
echo "" >> file
echo " " >> file

Sont identiques ... sur debian ! Je n'ai pas testé ailleurs et je me suis dit que c’était la façon la plus générale possible de l’écrire (pas qu'un lecteur quelconques squeeze les sauts de ligne, si il n'y a pas de caractère dedans) ...

Cela dit, merci de ta vigilance 🙂

Comment by Thymotep on 2013-01-19 16:56:19 +0100

Bonjour,

Merci pour ce script !
Je rencontre un petit soucis, quand je lance le script j'obtiens cette erreur :
mysqldump: Got error: 1045: Access denied for user 'root'@'localhost' (using password: YES) when trying to connect

Pour si je copie/colle la ligne en dehors du shell, elle fonctionne parfaitement en remplacement les variables .. que je l'execute en root ou avec le simple user de la machine. Je n'arrive pas à comprendre d'où cela vient ?

Si quelqu'un à une idée je suis preneur, merci beaucoup !
Thymotep

Comment by greg on 2013-11-25 16:36:00 +0100

Salut bon travail..... possibilité de l'améliorer et de corriger le bugs

merci

Comment by Nono on 2013-11-25 16:43:42 +0100

J'ai mis à jour le github, le script affiché ici rencontre quelques soucis d'encodage (html).