Backup mysql

Ce wiki a été archivé en 2018.

Le nouveau wiki se trouve à: ressources.labomedia.org

Les fonctionnalités sont désactivées: vous pouvez faire une recherche sur Google site:https://wiki.labomedia.org et découvrir La Labomedia.

De Centre de Ressources Numériques - Labomedia
Aller à : navigation, rechercher

Petit Script perso de sauvegarde d'une base de données mysql en bash (par JO) :

Déroulement du script

  1. dump mysql qui génère 2 fichiers .sql par base de donnée (un pour la structure, et un pour les données)
  2. création d'une archivage .tar.gz
  3. enregistrement de l'archive dans un dossier prédéfini
  4. suppression des archives trop anciennes
  5. envois d'un email de listing des backups disponibles (ou d'un log d'erreur si il y en a une)

Configurations disponibles

  • DB_LOGIN_PATH login path utilisé lors du mysql_config_editor pour vous connecter à mysql
  • MAIL_REPORT email du rapport
  • MAIL_SUBJECT sujet du mail
  • FOLDER_BACKUP répertoire de stockage des sauvegardes
  • FOLDER_WWW URL d'accès aux sauvegardes
  • FILE_LOG fichier de log
  • FILE_INFO fichier de listing des sauvegardes
  • BACKUP_NAME nom de l'archive de chaque sauvegarde
  • BACKUP_IGNORE_DATABASES base de données à ignorer lors de la sauvegarde
  • BACKUP_IGNORE_TABLES_DATA contenu des tables à ignorer lors de la sauvegarde (ignore uniquement le contenu, la structure sera bien sauvegardée)
  • BACKUP_RETENTION nombre de jours max de rétention des sauvegardes avant suppression

Installation du script

Le script necessite un utilisateur (ici backup) pour accéder à votre 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:

mysql_config_editor set --login-path=backup --host=localhost --user=backup --password
Pensez à rendre executable le script de sauvegarde:
chmod +x backup.sh

Le Script en question pour backup vos bases de données MySQL

#!/bin/bash

########################################################################
#
# Génération d'une sauvegarde des base de données
# Il faudra éxecuter le script automatiquement grâce à un cron
#
# Le script necessite 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:
# mysql_config_editor set --login-path=backup --host=localhost --user=backup --password
#
# Pensez à rendre executable le script de sauvegarde: chmod +x backup.sh
#
########################################################################

# login path utilisé lors du mysql_config_editor
DB_LOGIN_PATH="backup"

# email du rapport
MAIL_REPORT="email@domain.com"
#sujet du mail
MAIL_SUBJECT="Mon super Backup Backup $(date +%Y.%m.%d@%Hh%M)"

# Répertoire de stockage des sauvegardes
FOLDER_BACKUP="$HOME/Mes_Backups"
# URL d'accès aux sauvegardes
FOLDER_WWW="https://monsite.com/Mes_Backups/"

# 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
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. "DATABASE.TABLE1" "DATABASE.TABLE2" "DATABASE2.TABLE1"
BACKUP_IGNORE_TABLES_DATA=(
	"database.table1"
)
# Nombre de jours max de rétention des sauvegardes
BACKUP_RETENTION=30 

########################################################################
#
# 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}"
	mkdir "${BACKUP_PATH}" 2>> "$FILE_LOG"
}

tmp_folder_delete() {
	echo "- Suppression du répertoire de sauvegarde temporaire: ${BACKUP_PATH}"
	rm -rf "${BACKUP_PATH}" 2>> "$FILE_LOG"
}

mysql_connect() {
	echo "- Connexion à mysql pour lister toutes les BDD du serveur."
	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"

	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"
			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"
	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"
	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"
	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_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 "############################################################################### BACKUP"

echo "########################################################################" > "${FILE_LOG}"
echo "# NEW BACKUP ${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 "No mysql dump found" >> "${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 "# SUCCESS :)" >> "${FILE_LOG}"
	echo "########################################################################" >> "${FILE_LOG}"
	echo "" >> "${FILE_LOG}"
	echo "" >> "${FILE_LOG}"

	file_info

	mail_report_success

	echo "############################################################################### SUCCESS :)"

	exit 0;

# erreur, aucune archive n'a été créé
else

	echo "" >> "${FILE_LOG}"
	echo "# ERROR :(" >> "${FILE_LOG}"
	echo "########################################################################" >> "${FILE_LOG}"
	echo "" >> "${FILE_LOG}"
	echo "" >> "${FILE_LOG}"

	file_info
	
	mail_report_error

	echo "############################################################################### ERROR :("

	exit 1;
fi