#!/bin/bash # -------------------------------------------------------------------------------------- # Didier # # Script de sauvegarde avec BorgBackup # la commande de creation du dépot est : borg init --encryption=repokey /mnt/backup-nas1/BorgRepo # la conf de borg est dans /root/.config/borg # Le repository peut etre distant: BORG_REPO='ssh://user@host:port/path/to/repo' # la clé ssh devra être copiée sur le site distant et l' init se fera sous la forme # borg init --encryption=repokey ssh://user@host:port/path/to/repo # la clé est modifiable avec la commande borg key change-passphrase # toutes les variables sont dans la config générale de KAZ # scripts PRE et Post # les script pre et post doivent s' appelle pre_xxxxx.sh ou post_xxxx.sh # La variable BORGSCRIPTS est le chemin du repertoire des scripts dans la config générale de Kaz ##################################################### #KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd) KAZ_ROOT=/kaz . $KAZ_ROOT/bin/.commonFunctions.sh setKazVars . $DOCKERS_ENV . $KAZ_ROOT/secret/SetAllPass.sh VERSION="V-3-11-2024" PRG=$(basename $0) RACINE=$(echo $PRG | awk '{print $1}') #IFS=' ' ##################################################### # Variables générales ##################################################### # le volume monté ou sera le repo # impérativement laisser vide dans le cas d' un repo distant VOLUME_SAUVEGARDES=${borg_VOLUME_SAUVEGARDES} # le repo Borg export BORG_REPO=${borg_BORG_REPO} # Le mot de passe du repo export BORG_PASSPHRASE=${borg_BORG_PASSPHRASE} # les personnes qui recevront le rapport de sauvegarde MAIL_RAPPORT=${borg_MAIL_RAPPORT} # Recevoir un mail quand la sauvegarde est OK ? MAILOK=${borg_MAILOK} MAILWARNING=${borg_MAILWARNING} MAILDETAIL=${borg_MAILDETAIL} # repertoire de montage des sauvegardes pour les restaurations BORGMOUNT=${borg_BORGMOUNT} # - la liste des repertoires à sauver séparés par un espace LISTREPSAUV=${borg_LISTREPSAUV} # - Les sauvegardes à garder jour, semaines, mois # - ou si renseigné c' est la variable borg_BACKUPS_KEEP qui prend le dessus BACKUPS_KEEP=${borg_BACKUPS_KEEP} NB_BACKUPS_JOUR=${borg_NB_BACKUPS_JOUR} NB_BACKUPS_SEM=${borg_NB_BACKUPS_SEM} NB_BACKUPS_MOIS=${borg_NB_BACKUPS_MOIS} # Le Repertoire ou sont les pré traitement BORGSCRIPTS=${borg_BORGSCRIPTS} BORGLOG="${borg_BORGLOG}/BorgBackup-$(date +%d-%m-%Y-%H-%M-%S).log" DEBUG=false #Fichier des sauvegardes a supprimer BORG_FIC_DEL=${borg_BORG_FIC_DEL} BORG_EXCLUDE_BACKUP=${borg_BORG_EXCLUDE_BACKUP} ##################################################### # FICLOG="/var/log/${PRG}.log" ##################################################### trap 'LogFic "script stoppé sur un SIGTERM ou SIGINT" >&2; exit 2' INT TERM LogFic() { [ ! -w ${FICLOG} ] && { echo "Probleme d' ecriture dans $FICLOG" ; exit 1 ;} echo "$(date +%d-%m-%Y-%H-%M-%S) : $1" >> ${FICLOG} } # ExpMail() { MAIL_SOURCE=$1 MAIL_SUJET=$2 MAIL_DEST=$3 MAIL_TEXTE=$4 # a mettre ailleurs mailexp=${borg_MAILEXP} mailpassword=${borg_MAILPASSWORD} mailserveur=${borg_MAILSERVEUR} # #sendemail -t ${MAIL_DEST} -u ${MAIL_SUJET} -m ${MAIL_TEXTE} -f $mailexp -s $mailserveur:587 -xu $mailexp -xp $mailpassword -o tls=yes >/dev/null 2>&1 printf "Subject:${MAIL_SUJET}\n${MAIL_TEXTE}" | msmtp ${MAIL_DEST} #docker exec -i mailServ mailx -a 'Content-Type: text/plain; charset="UTF-8"' -r ${MAIL_SOURCE} -s "${MAIL_SUJET}" ${MAIL_DEST} << EOF #${MAIL_TEXTE} #EOF } Pre_Sauvegarde() { if [ -d ${BORGSCRIPTS} ] then cd ${BORGSCRIPTS} for FicPre in $(ls ) do if [ -x ${FicPre} ] && [ $(echo ${FicPre} | grep -i ^pre_) ] then LogFic " - Pré traitement de la sauvegarde : ${FicPre}" [ "$DEBUG" = true ] && echo " - Pré traitement de la sauvegarde : ${FicPre}" ./${FicPre} fi done fi } Post_Sauvegarde() { if [ -d ${BORGSCRIPTS} ] then cd ${BORGSCRIPTS} for FicPre in $(ls ) do if [ -x ${FicPre} ] && [ $(echo ${FicPre} | grep -i ^post_) ] then LogFic " - Post traitement de la sauvegarde : ${FicPre}" [ "$DEBUG" = true ] && echo " - Post traitement de la sauvegarde : ${FicPre}" ./${FicPre} fi done fi } Sauvegarde() { [ -f "${BORG_EXCLUDE_BACKUP}" ] && S_EXCU="--exclude-from ${BORG_EXCLUDE_BACKUP}" || S_EXCU="" Pre_Sauvegarde BACKUP_PRE=$? borg create \ --filter AME \ --exclude-caches \ --stats \ --show-rc \ --exclude 'home/*/.cache/*' \ --exclude 'var/tmp/*' \ ${S_EXCU} \ ::$(date +%Y-%m-%d-%H-%M-%S-%A)-{hostname} \ ${LISTREPSAUV} >>${BORGLOG} 2>>${BORGLOG} BACKUP_EXIT=$? Post_Sauvegarde BACKUP_POST=$? } Purge() { if [ ! -z ${BACKUPS_KEEP} ] then borg prune --keep-within=${BACKUPS_KEEP} PRUNE_EXIT=$? else borg prune --keep-daily ${NB_BACKUPS_JOUR} --keep-weekly ${NB_BACKUPS_SEM} --keep-monthly ${NB_BACKUPS_MOIS} PRUNE_EXIT=$? fi } Compact() { borg compact --progress ${BORG_REPO} } usage() { echo "-h : Usage" echo "-c : Permet de compacter ${BORG_REPO}" echo "-d : Permet de verifier les variables de sauvegarde" echo "-delbackup : Permet la suppression de backups renseignés dans un fichier ${BORG_FIC_DEL} " echo "-i : Mode interractif" echo "-info" echo "-l : Liste les sauvegardes sans monter ${BORG_REPO}" echo "-m : Monte le REPO (${BORG_REPO} sur ${BORGMOUNT})" echo "-p : Permet de lancer la phase de purge des backups" echo "-s : Lance la sauvegarde" echo "-u : Demonte le REPO (${BORG_REPO} de ${BORGMOUNT})" echo "-v : Version" exit } Borgvariables() { echo "-----------------------------------------------------------" echo " Variables applicatives pour le site ${site}" echo "-----------------------------------------------------------" for borgvar in $(set | grep borg_ | sed -e 's/borg_//' -e 's/=.*$//' | grep ^[A-Z]) do echo "$borgvar=${!borgvar}" done if grep borgfs /etc/mtab >/dev/null 2>&1 then echo -e "${RED}WARNING${NC}: ${BORG_REPO} est monté sur ${BORGMOUNT}" fi } BorgDelBackups() { [ -z ${BORG_FIC_DEL} ] && { echo "Le fichier n'est pas renseigné" ; exit 1; } [ ! -r ${BORG_FIC_DEL} ] && { echo "Le fichier ${BORG_FIC_DEL} est inexistant" ; exit 1 ; } for Backups in $(cat ${BORG_FIC_DEL}) do echo "suppression de la sauvegarde ${Backups}" borg delete ${BORG_REPO}::${Backups} done } Borgmount() { LogFic "Montage du repo ${BORG_REPO} sur ${BORGMOUNT} .. " echo -en "Montage du repo ${BORG_REPO} sur ${BORGMOUNT} .. " borg mount ${BORG_REPO} ${BORGMOUNT} >/dev/null 2>&1 if [ $? = 0 ] then LogFic "Ok" echo -e "${GREEN}Ok${NC}" else LogFic "Error" echo -e "${RED}Error $?${NC}" fi exit } Borgumount() { LogFic "Demontage du repo ${BORG_REPO} sur ${BORGMOUNT} .. " echo -en "Demontage du repo ${BORG_REPO} sur ${BORGMOUNT} .. " borg umount ${BORGMOUNT} >/dev/null 2>&1 if [ $? = 0 ] then LogFic "Ok" echo -e "${GREEN}Ok${NC}" else LogFic "Error" echo -e "${RED}Error $?${NC}" fi exit } Borglist() { BORG_LIST_BACKUPS=/tmp/borglistbackups.txt LogFic "Borg list demandé" borg list --short ${BORG_REPO} >${BORG_LIST_BACKUPS} cat ${BORG_LIST_BACKUPS} echo " --- Nombre de backups" cat ${BORG_LIST_BACKUPS} | wc -l rm ${BORG_LIST_BACKUPS} exit } Borginfo() { LogFic "Borg info demandé" borg info ${BORG_REPO} exit } ################################################################################################################################# # on teste tout le temps le message si le repo est monté ################################################################################################################################# # Test si le REPO est monté if grep borgfs /etc/mtab >/dev/null 2>&1 then REPO_MOUNT_ACTIVE=true else REPO_MOUNT_ACTIVE=false fi # on affiche tout le temps le message si le repo est monté if [ "${REPO_MOUNT_ACTIVE}" = "true" ] then echo "*****************************************************************************************" echo -e "${RED} WARNING : ${NC} Le repo ${BORG_REPO} est monté" echo "*****************************************************************************************" fi ################################################################################################################################# main() { # ****************************************************** Main ******************************************************************* # Création du fichier de log touch ${FICLOG} # LogFic "#########################################################################################################################" LogFic " *************** ${PRG} Version ${VERSION} ***************" LogFic "#########################################################################################################################" # test si les variables importantes sont renseignées et sortie si tel n' est pas le cas if [ -z "${VOLUME_SAUVEGARDES}" ] && [ -z "${BORG_REPO}" ] || [ -z "${BORG_REPO}" ] || [ -z "${BORG_PASSPHRASE}" ] || [ -z "${MAIL_RAPPORT}" ] then echo "Les variables VOLUME_SAUVEGARDES, BORG_REPO, BORG_PASSPHRASE, MAIL_RAPPORT sont à verifier" LogFic "Les variables VOLUME_SAUVEGARDES, BORG_REPO, BORG_PASSPHRASE, MAIL_RAPPORT sont à verifier" LogFic "Sortie du script" exit 1 fi # test si le volume de sauvegarde est ok if [ ! -z ${VOLUME_SAUVEGARDES} ] then [ !$(grep "${VOLUME_SAUVEGARDES}" /etc/mtab >/dev/null 2>&1) ] || { echo "le volume de sauvegarde ${VOLUME_SAUVEGARDES} n' est pas monté"; LogFic "Erreur de montage du volume ${VOLUME_SAUVEGARDES} de sauvegarde" ; exit 1;} else [ ! $(echo ${BORG_REPO} | grep -i ssh 2>/dev/null) ] && { echo "Problème avec le repo distant ";exit 1;} fi #Test si le REPO est monté : on sort if [ "${REPO_MOUNT_ACTIVE}" = "true" ] then echo "le REPO : ${BORG_REPO} est monté , je sors" LogFic "le REPO : ${BORG_REPO} est monté , je sors" ExpMail borg@${domain} "${site} : Sauvegarde en erreur" ${MAIL_RAPPORT} "le REPO : ${BORG_REPO} est monté, sauvegarde impossible" exit 1 fi # Tout se passe bien on continue LogFic " - Repertoire a sauver : ${LISTREPSAUV}" LogFic " - Volume Nfs monté : ${VOLUME_SAUVEGARDES}" LogFic " - Repertoire des sauvegardes : ${BORG_REPO}" [ ! -d ${BORGSCRIPTS} ] && LogFic "Pas de repertoire de PRE et POST" || LogFic " - Repertoire des scripts Post/Pré : ${BORGSCRIPTS}" [ -e ${BORG_EXCLUDE_BACKUP} ] && LogFic " - Fichier des exclusions : ${BORG_EXCLUDE_BACKUP}" [ "${DEBUG}" = true ] && [ -d ${BORGSCRIPTS} ] && echo "Rep des scripts PRE/POST :${BORGSCRIPTS}" LogFic " - Rapport par Mail : ${MAIL_RAPPORT}" if [ ! -z ${BACKUPS_KEEP} ] then LogFic " - Backups à garder : ${BACKUPS_KEEP}" else LogFic " - Backups jour : ${NB_BACKUPS_JOUR} , Backups semaines : ${NB_BACKUPS_SEM} , Backups mois : ${NB_BACKUPS_MOIS}" fi [ "${DEBUG}" = true ] && echo "${LISTREPSAUV} sauvé dans ${BORG_REPO}, Rapport vers : ${MAIL_RAPPORT}" LogFic "#########################################################################################################################" LogFic " - Démarrage de la sauvegarde" [ "$DEBUG" = true ] && echo "Demarrage de la sauvegarde : " LogFic " - Log dans ${BORGLOG}" Sauvegarde [ "$DEBUG" = true ] && echo "code de retour de backup : ${BACKUP_EXIT}" LogFic " - Code de retour de la commande sauvegarde : ${BACKUP_EXIT}" LogFic " - Démarrage du nettoyage des sauvegardes" [ "$DEBUG" = true ] && echo "Nettoyage des sauvegardes: " Purge LogFic " - Code retour du Nettoyage des sauvegardes (0=OK; 1=WARNING, 2=ERROR) : ${PRUNE_EXIT}" [ "$DEBUG" = true ] && echo "code de retour prune : ${PRUNE_EXIT}" # ######################################################################################## # si la variable MAILDETAIL est true alors on affecte le contenu du log sinon LOGDATA est VIDE LOGDATA="" [ "$MAILDETAIL" = true ] && LOGDATA=$(cat ${BORGLOG}) [ "$DEBUG" = true ] && [ "$MAILDETAIL" = true ] && echo "Envoi du mail à ${MAIL_RAPPORT}" # On teste le code retour de la sauvegarde, on log et on envoie des mails case "${BACKUP_EXIT}" in '0' ) IFS='' MESS_SAUVE_OK=" Salut La sauvegarde est ok, ce message peut être enlevé avec la variable MAILOK=false Que la force soit avec toi BorgBackup " LogFic " - la sauvegarde est OK" [ "$MAILOK" = true ] && ExpMail borg@${domain} "${site} : Sauvegarde Ok" ${MAIL_RAPPORT} ${MESS_SAUVE_OK}${LOGDATA} IFS=' ' ;; '1' ) IFS='' MESS_SAUVE_ERR=" Salut La sauvegarde est en warning Code de retour de la commande sauvegarde : ${BACKUP_EXIT} Le log contenant les infos est ${BORGLOG} BorgBackup " LogFic " - Sauvegarde en Warning: ${BACKUP_EXIT}" [ "$MAILWARNING" = true ] && ExpMail borg@${domain} "${site} : Sauvegarde en Warning: ${BACKUP_EXIT}" ${MAIL_RAPPORT} ${MESS_SAUVE_ERR}${LOGDATA} IFS=' ' ;; * ) IFS='' MESS_SAUVE_ERR=" Salut La sauvegarde est en Erreur Code de retour de la commande sauvegarde : ${BACKUP_EXIT} Le log à consulter est ${BORGLOG} BorgBackup " LogFic " - !!!!! Sauvegarde en Erreur !!!!! : ${BACKUP_EXIT}" ExpMail borg@${domain} "${site} : Sauvegarde en Erreur !!!! : ${BACKUP_EXIT}" ${MAIL_RAPPORT} ${MESS_SAUVE_ERR}${LOGDATA} IFS=' ' ;; esac LogFic " - Fin de la sauvegarde" exit } [ ! "$#" -eq "0" ] || usage # On teste les arguments pour le script for ARG in $@; do case "${ARG}" in '-h' | '-help' ) usage ;; '-m' ) shift Borgmount ;; '-u' ) shift Borgumount ;; '-l' ) shift Borglist ;; '-i' ) shift DEBUG=true ;; '-v' ) shift echo "Version : ${VERSION}" exit ;; '-d' ) shift Borgvariables exit ;; '-c' ) shift Compact exit ;; '-s' ) main ;; '-p' ) shift if [ ! -z ${BACKUPS_KEEP} ] then PURGE_MESS="Ok pour lancer la purge en fonction de ces valeurs : BACKUPS_KEEP=${BACKUPS_KEEP} ? O/N :" else PURGE_MESS="Ok pour lancer la purge en fonction de ces valeurs :jour=${NB_BACKUPS_JOUR},semaine=${NB_BACKUPS_SEM},mois=${NB_BACKUPS_MOIS} ? O/N :" fi read -p "${PURGE_MESS}" READPURGE [[ ${READPURGE} =~ ^[oO]$ ]] && Purge || echo "pas de purge" exit ;; '-info' ) shift Borginfo exit ;; '-delbackup' ) shift BorgDelBackups exit ;; * | ' ' ) usage ;; esac done