Outils pour utilisateurs

Outils du site


mysqldump-bash-mail

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

  1. Création d'un répertoire temporaire de travail où stocker votre export des base de données
  2. Connexion à MySQL pour récupérer la liste des bases de données à sauvegarder
  3. Dump de la structures des tables des bases de données
  4. Dump du contenu des tables des bases de données
  5. Compression de la sauvegarde en l'archivant dans un fichier .tar.gz
  6. Suppression du répertoire temporaire de travail
  7. Suppression des archives trop anciennes
  8. Création d'un fichier de logs concernant la sauvegarde
  9. 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 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

backup.sh
#!/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
mysqldump-bash-mail.txt · Dernière modification: 2019/12/05 20:39 par jo