#!/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