====== Sauvegarde de Base de Donnée MySQL en bash avec mysqldump ======
Le but du script est de faire une sauvegarde de vos base de données proprement pour pouvoir les ré-importer facilement.
===== Déroulement du script =====
- Création d'un répertoire temporaire de travail où stocker votre export des base de données
- Connexion à MySQL pour récupérer la liste des bases de données à sauvegarder
- Dump de la structures des tables des bases de données
- Dump du contenu des tables des bases de données
- Compression de la sauvegarde en l'archivant dans un fichier .tar.gz
- Suppression du répertoire temporaire de travail
- Suppression des archives trop anciennes
- Création d'un fichier de logs concernant la sauvegarde
- Mail du fichier de logs+liens ou télécharger la sauvegarde
===== Prérequis =====
* Serveur Linux
* Serveur MySQL
* Serveur Apache (optionnel)
* Serveur de mail (optionnel) --> si besoin utiliser [[SSMTP|https://doc.ubuntu-fr.org/ssmtp]]
* CRON pour exécuter automatiquement la sauvegarde
===== Installation =====
Le script nécessite un utilisateur pour accéder à la base de données. Ici on va créer un utilisateur "backup". Pensez à remplacer :
* **localhost** par l'ip de votre serveur MySQL si il n'est pas local
* **VOTRE_MOT_DE_PASSE** par le mot de passe que vous voulez donner à l'utilisateur "backup"
mysql -u root -p -e "CREATE USER 'backup'@'localhost' IDENTIFIED BY 'VOTRE_MOT_DE_PASSE';"
Ensuite on donne à l'utilisateur "backup" plusieurs droits pour effectuer des dump
mysql -u root -p -e "GRANT SELECT , SHOW DATABASES , LOCK TABLES , SHOW VIEW ON * . * TO 'backup'@'localhost' IDENTIFIED BY 'VOTRE_MOT_DE_PASSE' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;"
Pour ne pas avoir le mot de passe en clair dans le script (utiliser le mdp de "backup" quand c'est demandé)
mysql_config_editor set --login-path=backup --host=localhost --user=backup --password
===== Le script =====
#!/bin/bash
########################################################################
#
# Génération d'une sauvegarde des base de données
# Il faudra exécuter le script automatiquement grâce à un cron
#
# Le script nécessite un utilisateur pour accéder à la base de données:
# mysql -u root -p -e "CREATE USER 'backup'@'localhost' IDENTIFIED BY 'VOTRE_MOT_DE_PASSE';"
# mysql -u root -p -e "GRANT SELECT , SHOW DATABASES , LOCK TABLES , SHOW VIEW ON * . * TO 'backup'@'localhost' IDENTIFIED BY 'VOTRE_MOT_DE_PASSE' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;"
#
# Pour ne pas avoir le mot de passe en clair dans le script (utilisé le mdp de backup quand c'est demandé) :
# mysql_config_editor set --login-path=backup --host=localhost --user=backup --password
#
# Pensez à rendre exécutable le script de sauvegarde: chmod +x backup.sh
#
# Ajouter le script à votre cron (exécution tous les jours à 3h33) : crontab -e
# 33 3 * * * /home/yourhome/yourbackupfolderpath/backup.sh
#
########################################################################
# login path utilisé lors de la commande mysql_config_editor
DB_LOGIN_PATH="backup"
# email du rapport
MAIL_REPORT="email@fournisseur.fr"
#sujet du mail
MAIL_SUBJECT="[MySQL] [backup] $(hostname -s) $(date +%Y.%m.%d@%Hh%M)"
# Répertoire de stockage des sauvegardes
FOLDER_BACKUP="$HOME/yourbackupfolderpath"
# URL d'accès aux sauvegardes
FOLDER_WWW="http://votresite.fr/backup/"
# Fichiers de log et infos
FILE_LOG="${FOLDER_BACKUP}/backup.log"
FILE_INFO="${FOLDER_BACKUP}/backup.txt"
# Nom de la sauvegarde
BACKUP_NAME="backup"
# Base de données à ignorer lors de la sauvegarde (vous pouvez en ajouter)
BACKUP_IGNORE_DATABASES=(
"mysql"
"performance_schema"
"phpmyadmin"
"test"
"sys"
)
# Contenu des tables à ignorer lors de la sauvegarde (ignore uniquement le contenu, la structure sera bien sauvegardée)
# Ex. "DATABASE1.TABLE1" "DATABASE1.TABLE2" "DATABASE2.TABLE1"
BACKUP_IGNORE_TABLES_DATA=(
"DATABASE1.oc_filecache" # Exemple pour Nextcloud on ne sauvegarde pas les données de cache
)
# Nombre de jours max de rétention des sauvegardes
BACKUP_RETENTION=300
########################################################################
#
# NE PAS TOUCHER AU RESTE DU CODE SAUF SI VOUS SAVEZ CE QUE VOUS FAITE !
#
########################################################################
# Format de nommage du fichier de sauvegarde (ne pas changer au risque de casser les rotations)
BACKUP_DATE="$(date +%Y.%m.%d-%Hh%M)"
BACKUP_FILE="${BACKUP_NAME}-${BACKUP_DATE}"
BACKUP_PATH="${FOLDER_BACKUP}/${BACKUP_FILE}"
########################################################################
#
# Fonctions du script
#
########################################################################
tmp_folder_create() {
echo "- Création du répertoire de sauvegarde temporaire: ${BACKUP_PATH}" | tee -a "$FILE_LOG"
mkdir "${BACKUP_PATH}" 2>> "$FILE_LOG"
}
tmp_folder_delete() {
echo "- Suppression du répertoire de sauvegarde temporaire: ${BACKUP_PATH}" | tee -a "$FILE_LOG"
rm -rf "${BACKUP_PATH}" 2>> "$FILE_LOG"
}
mysql_connect() {
echo "- Connexion à mysql pour lister toutes les BDD du serveur." | tee -a "$FILE_LOG"
DATABASES="$(mysql --login-path=$DB_LOGIN_PATH -Bse 'show databases' 2>> $FILE_LOG | grep -v information_schema)"
}
mysql_dump() {
echo "- Dump des bases de données" | tee -a "$FILE_LOG"
BACKUP_IGNORE_TABLES_ARG=""
for TABLE in "${BACKUP_IGNORE_TABLES_DATA[@]}"
do
BACKUP_IGNORE_TABLES_ARG+=" --ignore-table=${TABLE}"
done
for DATABASE in ${DATABASES[@]}
do
if [[ ! " ${BACKUP_IGNORE_DATABASES[@]} " =~ " ${DATABASE} " ]]; then
echo " - Sauvegarde: $DATABASE.sql" | tee -a "$FILE_LOG"
mysqldump --login-path=$DB_LOGIN_PATH --quick --add-locks --lock-tables --extended-insert --no-data $DATABASE > "${BACKUP_PATH}/${DATABASE}-structure.sql" 2>> $FILE_LOG
mysqldump --login-path=$DB_LOGIN_PATH --quick --add-locks --lock-tables --extended-insert --no-create-info $BACKUP_IGNORE_TABLES_ARG $DATABASE > "${BACKUP_PATH}/${DATABASE}-data.sql" 2>> $FILE_LOG
fi
done
}
compress_dump() {
echo "- Archivage de la sauvegarde: ${BACKUP_FILE}.tar.gz" | tee -a "$FILE_LOG"
cd "${FOLDER_BACKUP}"
tar -czf "${BACKUP_FILE}.tar.gz" "${BACKUP_FILE}" 2>> "$FILE_LOG"
chmod 600 "${BACKUP_FILE}.tar.gz" 2>> "$FILE_LOG"
}
archive_link_latest() {
echo "- Création du lien symbolique vers la dernière version: ${BACKUP_NAME}-latest.tar.gz" | tee -a "$FILE_LOG"
unlink "${BACKUP_NAME}-latest.tar.gz"
ln -s "${BACKUP_FILE}.tar.gz" "${BACKUP_NAME}-latest.tar.gz"
}
archive_remove_oldest() {
echo "- Suppression des anciennes sauvegardes obsolètes" | tee -a "$FILE_LOG"
find "${FOLDER_BACKUP}" -name "*.tar.gz" -mtime +$BACKUP_RETENTION -print -exec rm {} \;
}
file_info() {
echo "- Génération du nouveau fichier d'informations sur les sauvegardes: ${FILE_INFO}"
rm "${FILE_INFO}"
find "${FOLDER_BACKUP}" -name "*.tar.gz" -exec basename {} \; | sort -r | while read file; do echo "${FOLDER_WWW}$file" >> "${FILE_INFO}"; done
}
mail_report_success() {
echo "- Email du rapport des sauvegardes"
cat $FILE_LOG $FILE_INFO | mail -s "$MAIL_SUBJECT" $MAIL_REPORT
}
mail_report_error() {
echo "- Email de log des erreurs"
cat $FILE_LOG | mail -s "[ERROR :(] $MAIL_SUBJECT" $MAIL_REPORT
}
########################################################################
#
# Déroulement du script
#
########################################################################
echo "############################################################################### SAUVEGARDE"
echo "########################################################################" > "${FILE_LOG}"
echo "# NOUVELLE SAUVEGARDE $(hostname -s) ${BACKUP_DATE}" >> "${FILE_LOG}"
echo "" >> "${FILE_LOG}"
tmp_folder_create
mysql_connect
mysql_dump
# le répertoire temporaire des dump est vide !
if [ -z "$(ls -A $BACKUP_PATH)" ]; then
echo "Aucun mysql_dump n'a été trouvé !" >> "${FILE_LOG}"
else
compress_dump
fi
tmp_folder_delete
# succès, une archive a été créé
if [ -f "${BACKUP_FILE}.tar.gz" ]; then
archive_link_latest
archive_remove_oldest
echo "" >> "${FILE_LOG}"
echo "# SUCCÈS :)" >> "${FILE_LOG}"
echo "########################################################################" >> "${FILE_LOG}"
echo "" >> "${FILE_LOG}"
echo "" >> "${FILE_LOG}"
file_info
mail_report_success
echo "############################################################################### SUCCÈS :)"
exit 0;
# erreur, aucune archive n'a été créé
else
echo "" >> "${FILE_LOG}"
echo "# ERREUR :(" >> "${FILE_LOG}"
echo "########################################################################" >> "${FILE_LOG}"
echo "" >> "${FILE_LOG}"
echo "" >> "${FILE_LOG}"
file_info
mail_report_error
echo "############################################################################### ERREUR :("
exit 1;
fi
**Pensez à rendre exécutable le script de sauvegarde: chmod +x backup.sh**
===== Sauvegarde automatique avec CRON =====
Ajouter le script à votre cron : crontab -e
Copiez la ligne si dessous qui va exécuter votre script ici tous les jours à 3h33
33 3 * * * /home/yourhome/yourbackupfolderpath/backup.sh