Introduction.
Pour sauvegarder les bases de données Mysql d’un serveur fonctionnant sous Linux, et récupérer la structure des tables et les données, j’ai pu être confronté à l’élaboration d’un script assez basique mais efficace. Rester enssuite à copier le tout sur un lecteur de bande, et le tour était joué.
Script
#!/bin/sh
###############################################################################
# Programme : backup_mysql.sh
# Application : Sauvegardes
# Date de creation : 25/04/2005
# Auteur : Marc-Henri PAMISEUX
#
# Copyright (c) 2005 Marc-Henri PAMISEUX
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# -----------------------------------------------------------------------------
# ! Date Modif. ! fonction ! description ! auteur !
# -----------------------------------------------------------------------------
# ! ! ! ! !
# ! ! ! ! !
###############################################################################
###############################################################################
# FONCTION Compress_MysqlTable
# LIBELLE Fonction de compression des donées
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE INSTANCE,DATABASE,TABLE
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de compresser les fichiers contenant les
# données d'une table Mysql afin d'économiser de la place
###############################################################################
Compress_MysqlTable()
{
if [ ! -s ${DirBakMysql}/${DATABASE}/${TABLE}.txt ]
then
echo "La table ${TABLE} de la base ${DATABASE} est vide"
else
unset TailleTable
TailleTable=`du -sk ${DirBakMysql}/${DATABASE}/${TABLE}.txt | awk '{print $1}'`
gzip ${DirBakMysql}/${DATABASE}/${TABLE}.txt
echo "Table sauvegardée: ${TABLE} (${TailleTable} Ko)"
fi
}
###############################################################################
# FONCTION Histo_Dech
# LIBELLE Fonction d'historisation de la sauvegarde
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE folderHisto
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet d'ajouter une entrée dans le fichier
# d'historisation des sauvegardes
###############################################################################
Histo_Dech()
{
if [ $# -gt 0 ]
then
folderHisto=$1
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier des historiques existe bien
#...............................................................................
if [ ! -d ${folderHisto} ]
then
echo "Erreur: Le dossier ${folderHisto} n'existe pas"
return 1
fi
if [ -z "${BakDate}" ]
then
export BakDate=`date --iso-8601`
fi
if [ ! -d ${folderHisto}/${BakDate} ]
then
echo "Erreur: Le dossier ${folderHisto}/${BakDate} n'existe pas"
return 1
fi
unset tailleBackup
tailleBackup=`du -sk ${folderHisto}/${BakDate} | awk '{print $1}'`
#...............................................................................
# On vient vérifier que la sauvegarde courante n'a pas déjà été historisée.
#...............................................................................
if [ -s ${folderHisto}/histo_dech ]
then
unset isHisto
isHisto=`cat ${folderHisto}/histo_dech | grep ${BakDate}`
#...............................................................................
# Si isHisto n'est pas vide, c'est qu'il existe une historisation pour ce jour
# Dans ce cas, on l'efface et on la recalcule; Sinon, on l'insère directement
#...............................................................................
if [ ! -z "${isHisto}" ]
then
cat ${folderHisto}/histo_dech | grep -v ${BakDate} > ${folderHisto}/histo_temp
if [ -f ${folderHisto}/histo_temp ]
then
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_temp
rm -f ${folderHisto}/histo_dech
mv ${folderHisto}/histo_temp ${folderHisto}/histo_dech
else
echo "Une erreur est survenue lors de l'historisation de la sauvegarde."
fi
else
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_dech
fi
else
touch ${folderHisto}/histo_dech
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_dech
fi
}
###############################################################################
# FONCTION Test_DblBackup
# LIBELLE Fonction de test de la sauvegarde
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE folderBackup
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de tester si la taille du dossier de
# backup est supérieure à la sauvegarde précedente du même jour.
# Cela permet de conserver une bonne sauvegarde dans un même
# jour, dans le cas où la sauvegarde courante serait incorrecte
###############################################################################
Test_DblBackup()
{
if [ $# -gt 0 ]
then
folderBackup=$1
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier de la sauvegarde existe bien
#...............................................................................
if [ ! -d ${folderBackup} ]
then
echo "Erreur: Le dossier ${folderBackup} n'existe pas"
return 1
fi
unset tailleBackup
tailleBackup=`du -sk ${folderBackup} | awk '{print $1}'`
unset tailleMinor
tailleMinor=`expr ${tailleBackup} / 4`
#...............................................................................
# On vient tester s'il existe une même sauvegarde pour ce jour
#...............................................................................
if [ -d ${folderBackup}.old ]
then
unset tailleOldBackup
tailleOldBackup=`du -sk ${folderBackup}.old | awk '{print $1}'`
tailleOldBackup=`expr ${tailleOldBackup} - ${tailleMinor}`
#...............................................................................
# Si la taille de l'ancien dossier de sauvegarde minoré du quart de la taille
# de la sauvegarde actuelle est > 0 ET
# que la taille de l'actuel dossier de sauvegarde est supérieur ou égal à
# cette valeur, alors on supprime l'ancien dossier de sauvegarde
#...............................................................................
if ([ ${tailleBackup} -ge ${tailleOldBackup} ] && [ ${tailleOldBackup} -gt 0 ])
then
rm -rf ${folderBackup}.old
else
echo "Pas de suppression de ${folderBackup}.old."
echo "Valeur de tailleBackup=>${tailleBackup}"
echo "Valeur de tailleOldBackup=>${tailleOldBackup}"
fi
fi
}
###############################################################################
# FONCTION Remove_Backup
# LIBELLE Fonction de suppression des anciennes sauvegardes
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE nbBakToKeep
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de tester le nombre de sauvegardes
# présentes dans le dossier de backup, et de supprimer toutes
# les plus anciennes sauvegardes
###############################################################################
Remove_Backup()
{
if [ $# -gt 1 ]
then
folderBackup=$1
nbBakToKeep=$2
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier de la sauvegarde existe bien
#...............................................................................
if [ ! -d ${folderBackup} ]
then
echo "Erreur: Le dossier ${folderBackup} n'existe pas"
return 1
fi
#...............................................................................
# On récupère la liste des 8 dernières sauvegardes
#...............................................................................
unset ListeToKeep
ListeToKeep=`ls -1t ${folderBackup} | grep -v 'histo_dech' | head -8`
if [ -z "${ListeToKeep}" ]
then
echo "Erreur: Le dossier ${folderBackup} est vide"
return 1
fi
#...............................................................................
# On vient lire la liste de tous les dossiers
#...............................................................................
listeAll=`ls -1t ${folderBackup} | grep -v 'histo_dech'`
#...............................................................................
# On supprime de la liste des dossiers les éléments à conserver
#...............................................................................
for Dossier in ${ListeToKeep}
do
listeAll=`echo ${listeAll} | sed -e 's,'${Dossier}',,g'`
done
#...............................................................................
# Pour chaque élément de la nouvelle liste, on supprime le dossier
#...............................................................................
unset Dossier
if [ ! -z "${listeAll}" ]
then
for Dossier in ${listeAll}
do
echo "suppression de ${Dossier} (rm -rf ${folderBackup}/${Dossier})"
rm -rf ${folderBackup}/${Dossier}
done
fi
}
###############################################################################
# FONCTION backup_mysql
# LIBELLE Fonction de sauvegarde
# TYPE NORMAL
# ARGUMENTS NON
# ENTREE AUCUN
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de déclencher une sauvegarde des bases
# de données MySQL
###############################################################################
backup_mysql()
{
unset DateNow
export DateNow=`date`
echo "DEBUT BACKUP MYSQL du: ${DateNow}" >${LogBakMysql}
echo "" >>${LogBakMysql}
################################################################################
# BOUCLE des bases de données
################################################################################
unset DATABASE
for DATABASE in `mysql --user="root" --password="" --batch --exec="USE mysql; SHOW DATABASES;" --silent --raw`
do
export DATABASE
echo "###############################################################################" \
>>${LogBakMysql}
echo "# Base actuelle: ${DATABASE}" >>${LogBakMysql}
echo "###############################################################################" \
>>${LogBakMysql}
#...............................................................................
# Création du dossier de sauvegarde
#...............................................................................
if [ -d ${DirBakMysql}/${DATABASE} ]
then
if [ -d ${DirBakMysql}/${DATABASE}.old ]
then
rm -rf ${DirBakMysql}/${DATABASE}.old
fi
mv ${DirBakMysql}/${DATABASE} ${DirBakMysql}/${DATABASE}.old
fi
mkdir ${DirBakMysql}/${DATABASE}
chown mysql:backup ${DirBakMysql}/${DATABASE}
################################################################################
# BOUCLE des tables de la base de données courante
################################################################################
unset TABLE
for TABLE in `mysql --user="root" --password="" --batch --exec="USE ${DATABASE}; SHOW TABLES;" --silent --raw`
do
export TABLE
#...............................................................................
# Dump de la base Mysql courante dans le dossier nouvellement créé
#...............................................................................
mysqldump --all --add-drop-table --add-locks --complete-insert --default-character-set=latin1 --extended-insert --flush-logs --hex-blob --lock-tables --quick --tab=${DirBakMysql}/${DATABASE} --tables --user="root" --fields-terminated-by='|' --fields-escaped-by='\\' --lines-terminated-by='\n' ${DATABASE} ${TABLE} 1>/dev/null 2>>${LogBakMysql}
#...............................................................................
# Compression de la sauvegarde courante
#...............................................................................
Compress_MysqlTable >>${LogBakMysql}
done
Test_DblBackup ${DirBakMysql}/${DATABASE} >>${LogBakMysql}
done
#...............................................................................
# Suppression des n sauvegardes précedentes
#...............................................................................
Remove_Backup ${DirBak}/mysql 8 >>${LogBakMysql}
#...............................................................................
# Historisation de la sauvegarde courante
#...............................................................................
Histo_Dech ${DirBak}/mysql >>${LogBakMysql}
unset DateNow
export DateNow=`date`
echo "FIN BACKUP MYSQL du: ${DateNow}" >>${LogBakMysql}
}
###############################################################################
# FONCTION MAIN
# LIBELLE Fonction principale
# TYPE NORMAL
# ARGUMENTS NON
# ENTREE AUCUN
# RETOUR AUCUN
# DESCRIPTION entree du programme
###############################################################################
#...............................................................................
# Export des fonctions du script
#...............................................................................
export -f Compress_MysqlTable
export -f Histo_Dech
export -f Test_DblBackup
export -f backup_mysql
#...............................................................................
# Definition des variables de scripts
#...............................................................................
unset BakDate
export BakDate=`date --iso-8601`
unset DirBak
export DirBak=/home/backup
unset DirBakMysql
export DirBakMysql=${DirBak}/mysql/${BakDate}
unset DirLog
export DirLog=/var/log/backup
unset LogBakMysql
export LogBakMysql=${DirLog}/mysql/${BakDate}.log
#...............................................................................
# Vérification des variables de scripts
#...............................................................................
if [ -z "${BakDate}" ]
then
exit 1
fi
if [ ! -d ${DirBak} ]
then
mkdir ${DirBak}
chown root:backup ${DirBak}
mkdir ${DirBak}/mysql
chown mysql:backup ${DirBak}/mysql
fi
if [ ! -d ${DirBak}/mysql ]
then
mkdir ${DirBak}/mysql
chown mysql:backup ${DirBak}/mysql
fi
if [ ! -d ${DirBakMysql} ]
then
mkdir ${DirBakMysql}
chown mysql:backup ${DirBakMysql}
fi
if [ ! -d ${DirLog} ]
then
mkdir ${DirLog}
chown root:backup ${DirLog}
mkdir ${DirLog}/mysql
chown mysql:backup ${DirLog}/mysql
fi
if [ ! -d ${DirLog}/mysql ]
then
mkdir ${DirLog}/mysql
chown mysql:backup ${DirLog}/mysql
fi
#...............................................................................
# On passe en tant qu'utilisateur mysql sans son environnement
#...............................................................................
su mysql -p -c backup_mysql
Voilà, vous aurez au final un dossier par jour dans /home/backup/mysql, contenant un sous dossier par base de données, lui-même contenant un fichier .sql représentant le schéma de la table et le fichier .txt qui lui est associé et contenant les données BRUT en texte prêtes à être rechargées en base (fichier gzip).