Dans notre série d’articles baptisés LSCI (La sauvegarde c’est important), nous vous avons déjà présenté pas mal de méthodes de sauvegarde. Ici, nous voulons vous présenter la méthode que nous utilisons pour sauvegarder ce site web. Dans ce tutoriel, nous allons donc voir comment sauvegarder son serveur web grâce à un script.
Nous passerons en revue toutes les parties de ce script pour vous donner des excplications au fur et à mesure de l’avancement du tuto.
Création du script
Dans cette première partie, nous débuter la création de notre script par la définition de nos variables. Ces variables serviront à ne pas avoir à définir certaines informations plus tard. Nous allons y définir toutes sortes de choses comme les chemins d’accès aux exécutables, le format de la date, les logins et mots de passe utilisés, le fichier de logs utilisé ainsi que les couleurs qui seront utilisées dans les fichiers de logs.
#!/bin/bash # Made by REWOP it (https://techarea.fr) # With this, you can make a backup of your websites (full) # Variables tar_bin="/bin/tar" date_day=`/bin/date +%Y%m%d` dir_backup_web="/backup/${date_day}/sites" dir_sites="/var/www" mysqldump_bin="/usr/bin/mysqldump" mysql_bin="/usr/bin/mysql" dir_backup_db="/backup/${date_day}/databases" gzip_bin="/bin/gzip" rclone_bin="/usr/sbin/rclone" date_old=`date --date='10 days ago' +%Y%m%d` dir_backup="/backup/" mysql_user="user" mysql_password="PWD" logfile="/var/log/backup/backup_${date_day}.log" ret="0" # Define the color for function showmsg() green="\\033[0;32m" stand="\\033[0;39m" red="\\033[0;31m" yellow="\\033[33m"
Nous allons maintenant créer la fonction qui permettra aux messages affichés sur l’écran et dans les logs de ressortir en couleur. Nous utiliserons une couleur différente pour chaque type de message.
# Function for show the message on screen and log file # Use this function with this example (return success message without log / return error message with log) # do_showmsg "success" "nolog" "Backup is valid" # do_showmsg "error" "log" "Config file is not found" do_showmsg() { # Local variables local usecolor="$1" local uselog="$2" local usemsg="$3" # Function logs if [ "${uselog}" == "log" ] || [ "${uselog}" == "yes" ]; then returnlog=${logfile} else returnlog="/dev/null" fi # Function colors if [ "${usecolor}" == "info" ] || [ "${usecolor}" == "warn" ]; then echo -ne "${stand}[ ${yellow}INFO ${stand}]> ${usemsg}\n" >> ${returnlog} elif [ "${usecolor}" == "error" ] || [ "${usecolor}" == "ko" ]; then echo -ne "${stand}[ ${red}ERROR ${stand}]> ${usemsg}\n" >> ${returnlog} elif [ "${usecolor}" == "success" ] || [ "${usecolor}" == "ok" ]; then echo -ne "${stand}[ ${green}SUCCESS ${stand}]> ${usemsg}\n" >> ${returnlog} else echo -ne "${stand}[ ${stand}OUTPUT ${stand}]> ${usemsg}\n" >> ${returnlog} fi }
Vérifions ensuite si tous les paquets nécessaires sont installés sur notre système. S’il ne le sont pas, le script les installera automatiquement.
# Check if needed packages are installed if [ $(dpkg-query -W -f='${Status}' lftp 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install lftp fi if [ $(dpkg-query -W -f='${Status}' tar 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install tar fi if [ $(dpkg-query -W -f='${Status}' gzip 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install gzip fi
Créons maintenant le dossier qui contiendra les logs d’exécution. Ici, le script va regarder si le dossier existe déjà. Si il n’est pas encore présent, il le créera.
# Log folder creation if [ ! -e "/var/log/backup" ] then mkdir -p "/var/log/backup" else do_showmsg "info" "log" "Folder '/var/log/backup' already exist" fi
Passons maintenant à la partie sauvegarde des dossiers contenant vos sites. Dans cette partie, nous allons d’abord créer le dossier qui contiendra les sauvegardes fichiers de nos sites webs. Ensuite, nous créons une boucle pour permettre de faire une archive par dossier se trouvant dans /var/www.
# Starting script echo -ne "Starting backup all websites at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} # Création du dossier s'il n'existe pas if [ ! -e "${dir_backup_web}" ] then mkdir -p "${dir_backup_web}" else do_showmsg "info" "log" "Folder '${dir_backup}' already exist" fi # Sauvegarde des sites dans "/datas/sites/*" cd ${dir_sites} for site_list in `ls`; do tar czf ${dir_backup_web}/backup_${site_list}.tar.gz ${site_list} 2>&1 > /dev/null if [ -e "${dir_backup_web}/backup_${site_list}.tar.gz" ] then echo -ne "[ SUCCESS ]> ${dir_backup_web}/backup_${site_list}.tar.gz\n" >> ${logfile} else echo -ne "[ ERROR ]> ${dir_backup_web}/backup_${site_list}.tar.gz\n" >> ${logfile} fi done # Stopping script echo -ne "Starting backup all websites at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile}
C’est maintenant aux bases de données d’être sauvegardées. Nous partons sur le même principe que pour les dossiers de nos sites.
# Starting script echo -ne "Starting backup MySQL Databases at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} # Création du répertoire de sauvegarde if [ ! -e "${dir_backup_db}" ] then mkdir -p "${dir_backup_db}" else echo -ne "[ INFO ]> folder '${dir_backup}' already exist\n" >> ${logfile} fi # Sauvegarde des bases de données avec compression GZIP for database_list in `${mysql_bin} -u ${mysql_user} -p${mysql_password} -ss -e "SHOW DATABASES" | egrep -vi "^(information_schema|performance_schema)$"`; do ${mysqldump_bin} -u ${mysql_user} -p${mysql_password} --events --opt -Q -B ${database_list} | ${gzip_bin} -c > ${dir_backup_db}/backup_${database_list}.sql.gz if [ -e "${dir_backup_db}/backup_${idatabase}.sql.gz" ] then echo -ne "[ SUCCESS ]> ${dir_backup_db}/backup_${database_list}.sql.gz\n" >> ${logfile} else echo -ne "[ ERROR ]> ${dir_backup_db}/backup_${database_list}.sql.gz\n" >> ${logfile} fi done # Stopping script echo -ne "Stopping backup MySQL Databases at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile}
La partie sauvegarde étant maintenant terminée, nous allons envoyer nos sauvegardes du jour vers un espace de stockage externe comme un FTP ou un stockage Cloud type Google Drive ou Amazon Drive. La première chose faire avant d’envoyer la sauvegarde est de vérifier elle sauvegarde existe. Ici, nous avons décidé les stocker sur Amazon Drive. A la fin de la copie, nous supprimons le backup du jour.
# Vérification du dossier de sauvegarde d'aujourd'hui (sinon arrêt du script) if [ ! -e "${dir_backup}/${date_day}" ]; then echo -ne "[ ERROR ]> Le dossier de sauvegarde local '${dir_backup}/${date_day}' n'existe pas.\n" >> ${logfile} exit 1 fi # Upload the backups files on Amazon Drive and return code cd ${dir_backup} ${rclone_bin} copy ${date_day} amzn:Backup/websites/${date_day} if [ "$?" -eq "0" ]; then do_showmsg "success" "log" "Uploading backup on Amazon Drive successfull" ret=$((${ret}+0)) else do_showmsg "error" "log" "Uploading backup on Amazon Drive return an error" ret=$((${ret}+1)) fi rm -rf /backup
Voilà, le script étant expliqué, nous allons maintenant vous le livrer au complet pour une copie plus facile. Si vous décidez d’utiliser ce script il vous faudra installer Rclone pour connecter votre compte de stockage cloud ou alors modifier les lignes concernant l’envois des backups.
Présentation du script complet
#!/bin/bash # Made by REWOP it (https://techarea.fr) # With this, you can make a backup of your websites (full) # Variables tar_bin="/bin/tar" date_day=`/bin/date +%Y%m%d` dir_backup_web="/backup/${date_day}/sites" dir_sites="/var/www" mysqldump_bin="/usr/bin/mysqldump" mysql_bin="/usr/bin/mysql" dir_backup_db="/backup/${date_day}/databases" gzip_bin="/bin/gzip" rclone_bin="/usr/sbin/rclone" date_old=`date --date='10 days ago' +%Y%m%d` dir_backup="/backup/" mysql_user="user" mysql_password="PWD" logfile="/var/log/backup/backup_${date_day}.log" ret="0" # Define the color for function showmsg() green="\\033[0;32m" stand="\\033[0;39m" red="\\033[0;31m" yellow="\\033[33m" # Function for show the message on screen and log file # Use this function with this example (return success message without log / return error message with log) # do_showmsg "success" "nolog" "Backup is valid" # do_showmsg "error" "log" "Config file is not found" do_showmsg() { # Local variables local usecolor="$1" local uselog="$2" local usemsg="$3" # Function logs if [ "${uselog}" == "log" ] || [ "${uselog}" == "yes" ]; then returnlog=${logfile} else returnlog="/dev/null" fi # Function colors if [ "${usecolor}" == "info" ] || [ "${usecolor}" == "warn" ]; then echo -ne "${stand}[ ${yellow}INFO ${stand}]> ${usemsg}\n" >> ${returnlog} elif [ "${usecolor}" == "error" ] || [ "${usecolor}" == "ko" ]; then echo -ne "${stand}[ ${red}ERROR ${stand}]> ${usemsg}\n" >> ${returnlog} elif [ "${usecolor}" == "success" ] || [ "${usecolor}" == "ok" ]; then echo -ne "${stand}[ ${green}SUCCESS ${stand}]> ${usemsg}\n" >> ${returnlog} else echo -ne "${stand}[ ${stand}OUTPUT ${stand}]> ${usemsg}\n" >> ${returnlog} fi } # Check if needed packages are installed if [ $(dpkg-query -W -f='${Status}' lftp 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install lftp fi if [ $(dpkg-query -W -f='${Status}' tar 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install tar fi if [ $(dpkg-query -W -f='${Status}' gzip 2>/dev/null | grep -c "ok installed") -eq 0 ] then apt-get install gzip fi # Log folder creation if [ ! -e "/var/log/backup" ] then mkdir -p "/var/log/backup" else do_showmsg "info" "log" "Folder '/var/log/backup' already exist" fi # Starting script echo -ne "Starting backup all websites at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} # Création du dossier s'il n'existe pas if [ ! -e "${dir_backup_web}" ] then mkdir -p "${dir_backup_web}" else do_showmsg "info" "log" "Folder '${dir_backup}' already exist" fi # Sauvegarde des sites dans "/datas/sites/*" cd ${dir_sites} for site_list in `ls`; do tar czf ${dir_backup_web}/backup_${site_list}.tar.gz ${site_list} 2>&1 > /dev/null if [ -e "${dir_backup_web}/backup_${site_list}.tar.gz" ] then echo -ne "[ SUCCESS ]> ${dir_backup_web}/backup_${site_list}.tar.gz\n" >> ${logfile} else echo -ne "[ ERROR ]> ${dir_backup_web}/backup_${site_list}.tar.gz\n" >> ${logfile} fi done # Stopping script echo -ne "Starting backup all websites at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} # Starting script echo -ne "Starting backup MySQL Databases at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} # Création du répertoire de sauvegarde if [ ! -e "${dir_backup_db}" ] then mkdir -p "${dir_backup_db}" else echo -ne "[ INFO ]> folder '${dir_backup}' already exist\n" >> ${logfile} fi # Sauvegarde des bases de données avec compression GZIP for database_list in `${mysql_bin} -u ${mysql_user} -p${mysql_password} -ss -e "SHOW DATABASES" | egrep -vi "^(information_schema|performance_schema)$"`; do ${mysqldump_bin} -u ${mysql_user} -p${mysql_password} --events --opt -Q -B ${database_list} | ${gzip_bin} -c > ${dir_backup_db}/backup_${database_list}.sql.gz if [ -e "${dir_backup_db}/backup_${idatabase}.sql.gz" ] then echo -ne "[ SUCCESS ]> ${dir_backup_db}/backup_${database_list}.sql.gz\n" >> ${logfile} else echo -ne "[ ERROR ]> ${dir_backup_db}/backup_${database_list}.sql.gz\n" >> ${logfile} fi done # Stopping script echo -ne "Stopping backup MySQL Databases at `/bin/date +%d/%m/%Y`, `/bin/date +%H:%M:%S`\n" >> ${logfile} ####################### ## PART FTP BACKUP ## ####################### # Vérification du dossier de sauvegarde d'aujourd'hui (sinon arrêt du script) if [ ! -e "${dir_backup}/${date_day}" ]; then echo -ne "[ ERROR ]> Le dossier de sauvegarde local '${dir_backup}/${date_day}' n'existe pas.\n" >> ${logfile} exit 1 fi # Upload the backups files on the Amazon Drive and return code cd ${dir_backup} ${rclone_bin} copy ${date_day} amzn:Backup/websites/${date_day} if [ "$?" -eq "0" ]; then do_showmsg "success" "log" "Uploading backup on Amazon Drive successfull" ret=$((${ret}+0)) else do_showmsg "error" "log" "Uploading backup on Amazon Drive return an error" ret=$((${ret}+1)) fi rm -rf /backup ######################### ## RETURN END SCRIPT ## ######################### # Add message on the log if [ "${ret}" -eq "0" ]; then do_showmsg "success" "log" "Finish execution successful" elif [ "${ret}" -eq "1" ]; then do_showmsg "warn" "log" "Finish execution with ${ret} error" else do_showmsg "error" "log" "Finish execution with ${ret} errors" fi # Exit exit ${ret}
Conclusion
Vous avez maintenant une façon de sauvegarder tous vos sites facilement avec un simple script. Nous trouvions aussi important de vous présenter la méthode que nous utilisons pour ce site.
8 comments
Merci pour cet exemple. J’ai créé de nombreux scripts dont 1 pour la sauvegarde avec les mêmes outils mais je ne connaissais pas les fonctions et je vais donc reprendre l’idée de ‘do_showmsg’ pour mettre de la couleur dans l’exécution de mes scripts. Par contre les ‘>> ${returnlog}’ dans la fonction ne renvoient forcément jamais rien dans le sdout. Je les ai remplacés par ‘| tee ${returnlog}’.
Ce remplacement est une bonne idée aussi. Je n’y avais pas pensé. Merci !
Salute,
Ne le prends pas mal mais je trouve ton script extrêmement lourd :
– Quel intérêt à toutes les variables *_bin ? En général on met directement le chemin
– Les parties « Création du dossier s’il n’existe pas » ne servent à rien hormis alourdir le script énormément mkdir -p veut justement dire tu crées le dossier si il n’existe pas et tu ne fais rien si il existe déjà bref le reste c’est alourdir inutilement
– Starting backup all websites at
/bin/date +%d/%m/%Y
,/bin/date +%H:%M:%S
n –> echo/bin/date '+%d/%m/%Y, %H:%M:%S'
– [[ -z $(which lftp) ]] && apt-get install lftp au pire pourquoi ne pas faire un bête apt-get -y install lftp gzip…
Tcho !
Salut,
Merci pour ton retour ! Je dois encore le retravailler un peu pour qu’il soit plus léger !
Juste pour tester « disqus » 🙂
Re pour tester 😉
J’ai pas le badge « Team » moi 🙁
Pas mal l’exemple pour les couleurs, je vais tester !
Voilà mon script de sauvegarde, en attendant : https://gist.github.com/ZerooCool/b06925403f94960e32c3c52f2db81b01
Je cherche des informations complémentaires, pour utiliser AES pour le chiffrement des fichiers de sauvegarde.
Vos commentaires sont les bienvenus.