Annexe : Automatisation de l'exploitation iLinux v1

Script d'automatisation de la sauvegarde serveur (distant) web & databases

./sauvegarde_srv_web-db.sh

#!/bin/bash
###############################################################################
#                                                                             #
# PGM     : Script de sauvegarde serveur (distant) web & databases            #
#                                                                             #
# AUTEUR  : Stephane  (iLinux)                                                #
# VERSION : 1.0.0                                                             #
#                                                                             #
# DATE    : 03/06/2019                                                        #
#                                                                             #
# PARAM.  : N/A                                                               #
#           OUT > logger + mail                                               #
#                                                                             #
###############################################################################
# EN PREMIER LIEU
# On inclus les fonctions et variables communes:
. ~/Prod/Scripts/fonctions_variables.sh
# Variables de travail ...
# ... LOCALES
# ... DISTANTES
# N/A
# Au commencement il n'y a jamais d'erreur ... dans un script
G_ERREUR=0
# Serveur à sauvegarder :
SERVEUR=$1
# Surcharge var. fichier log (en attendant serveur mail !)
#G_FICHIER_LOG="/root/Prod/Journaux/Sauvegardes/$SERVEUR.log"
# Script actuellement en cours d'execution
echo "SCRIPT    : $G_APPLI"
echo "" >> $G_FICHIER_LOG
echo ">>>> $G_APPLI sur serveur : \"$SERVEUR\", executé le $G_JOUR $G_DATE">> $G_FICHIER_LOG
echo "" >> $G_FICHIER_LOG
# 1 seul paramétre attendu
#if [ $# = 1 ] || [ -z "$1"]
#then
#       G_ERREUR='Donnez 1 nom de serveur svp ...'
#       # On sort du script avec $G_ERREUR
#       g_log_message "ERROR" $G_MSG_FIN_SCRIPT
#       exit $G_ERREUR
#fi
# DEBUT DU SCRIPT
g_log_message "INFO" $G_MSG_DEBUT_SCRIPT
g_log_message "INFO" "Parametres : \"$*\""
# Préparation sauvegarde
#
# On stoppe le serveur web distant ...
gestionServiceServeur $SERVEUR "stop" "nginx"
# On fait les "dump" Mysql et PostgreSQL des bases sur le serveur distant sous "/root/Prod/Sauvegardes/Bases" ...
# Rappel : sauvegardeBasesServeur server dbType dbDumpDir
sauvegardeBasesServeur  $SERVEUR "mysql" "/root/Prod/Sauvegardes/Bases"
sauvegardeBasesServeur  $SERVEUR "postgresql" "/root/Prod/Sauvegardes/Bases"
# On lance la sauvegarde du système de fichiers ... (localement via le montage sshFS)
depotBorgBackup="/Sauvegardes/Prod/$SERVEUR"
mountDist="/root/Prod/mnt/BorgBackup/$SERVEUR"
# ATTENTION : /root/Prod/mnt/BorgBackup/ ... (via sshFS)
repertoiresAsauvegarder="$mountDist/etc $mountDist/root $mountDist/home $mountDist/var"
sauvegardeBorgBackupServeur $SERVEUR "$depotBorgBackup" "$repertoiresAsauvegarder"
# On relance le serveur Web distant
gestionServiceServeur $SERVEUR "start" "nginx"
# On audit le système de fichier distant (volumétrie etc)
statutSFServeur $SERVEUR
# On audit le système de sauvegarde
statutBorgBackup "$depotBorgBackup"
# On sort du script avec $G_ERREUR
g_log_message "INFO" $G_MSG_FIN_SCRIPT
exit $G_ERREUR
# FIN DU SCRIPT

Boîte à outils : script de fonctions et variables réutilisables

./fonctions_variables.sh

#!/bin/bash
###############################################################################
#                                                                             #
# PGM     : Script de fonctions et variables réutilisables                    #
#                                                                             #
# AUTEUR  : Stephane                                                          #
# VERSION : 1.0.0                                                             #
#                                                                             #                                                                                                       
# DATE    : 02/06/2019                                                        #                                                                                                       
#                                                                             #                                                                                                       
# PARAM.  : IN  < N/A                                                         #                                                                                                       
#           OUT > N/A                                                         #                                                                                                       
#                                                                             #                                                                                                       
###############################################################################                                                                                                       
                                                                                                                                                                                      
# Variables de travail ...                                                                                                                                                            
# ... LOCALES                                                                                                                                                                         
                                                                                                                                                                                      
# ... DISTANTES                                                                                                                                                                                              
# N/A                                                                                                                                                                                                        
                                                                                                                                                                                                             
# Chemin complet des outils utilises A GARDER POUR PORTABILITE MULTI-PLATEFORME etc ...                                                                                                                      
                                                                                                                                                                                                             
# Ce fichier, amene a evoluer, contient en ensemble de fonctions et variables                                                                                                                                
# globales courament utilisees.                                                                                                                                                                              
                                                                                                                                                                                                             
########################### NOMENCLATURE (rajouter ici vos régles de nommage)                                                                                                                                
#                                                                                                                                                                                                            
# Variable GLOBALE (doit etre reutilisee dans plusieurs script)                                                                                                                                              
# Elle est prefixee d'un "G_" comme "G_lobale"                                                                                                                                                                                                                                                                                
# G_<nom_variable>                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                              
# Variable LOCALE (utilisable dans un script particulier)                                                                                                                                                                                                                                                                     
# a Elle n'est pas prefixee, et n'a donc pas lieu d'etre dans ce fichier                                                                                                                                                                                                                                                      
# ormis leur présence dans les fonctions                                                                                                                                                                                                                                                                                      
# <nom_variable>                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                              
# IDEM pour les fonctions : g_<nom_fonction>                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                              
# Par defaut quand nous definissons un chemin (PATH) nous ne mettrons jamais de "/"                                                                                                                                                                                                                                           
# en fin de chemin (cf. code ci-dessous)                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                              
# Ce fichier contient une section GLOBALE et une section APPLI (specifique a certains scripts)                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                              
###############################################################################                                                                                                                                                                                                                                               
#                                                                             #                                                                                                                                                                                                                                               
#                                    GLOBALE                                  #                                                                                                                                                                                                                                               
#                                                                             #                                                                                                                                                                                                                                               
###############################################################################                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                              
#                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                              
####### VARIABLES GLOBALES #####################################################                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                              
# ELLES SONT OBLIGATOIRES POUR TOUT SCRIPT ECRIT 
export LANG=fr_FR.UTF-8 # NE PAS MODIFIER => sinon les jours ci-dessous seront en anglais.
# MERCI
G_DATE=`date +%d\ %b\ %T`
G_JOUR=`date "+%A"`
#G_NOM_MACHINE=`hostname`
G_NOM_MACHINE=$1
G_APPLI=`basename $0`
G_PID_APPLI=$$
G_FICHIER_LOG="/root/Prod/Journaux/Sauvegardes/$G_APPLI.log" 
G_COURRIEL_TXT="/root/Prod/Journaux/Sauvegardes/$G_APPLI-COURRIEL.txt"
G_CONTACTS_MAIL="yourMonitoringMail@domain.tld"
G_SUJET_MAIL="$G_APPLI sur $G_NOM_MACHINE"
# Message de debut et fin de script
G_MSG_DEBUT_SCRIPT="DEBUT-SCRIPT"
G_MSG_FIN_SCRIPT="FIN-SCRIPT"
# Il faudra mettre G_ERREUR=1 en cas de soucis et
# bien sure ne jamais remettre a "0" cette variable !!!
# Chemin complet des outils utilises A GARDER POUR PORTABILITE MULTI-PLATEFORME etc ...
SSH="/usr/bin/ssh"
#TAR="/bin/tar"
MKDIR="/bin/mkdir"
#LN="/bin/ln"
#CHOWN="/bin/chown"
#CHMOD="/bin/chmod"
#CP="/bin/cp"
#USERMOD="/usr/sbin/usermod"
LOGGER="/usr/bin/logger"
#MAIL="/usr/bin/mail"
MSMTP="/usr/bin/msmtp"
RM="/bin/rm"
CAT="/bin/cat"
DU="/usr/bin/du"
DF="/bin/df"
TEE="/usr/bin/tee"
SYSTEMCTL='/bin/systemctl'
SLEEP='/bin/sleep'
SYNC='/bin/sync'
UMOUNT='/bin/umount'
MOUNT='/bin/mount'
GREP='/bin/grep'
GZIP='/bin/gzip'
HOSTNAME='/bin/hostname'
SMARTCTL='/usr/sbin/smartctl'
CEPH='/usr/bin/ceph'
WHICH='/usr/bin/which'
# -> NE PAS ENLEVER MERCI.
# Fonction qui permet de loger les messages d'erreurs, d'informations, de warning etc ...
# Param IN      $1 = TYPE du Message, gravité( INFO ou ERROR)voir doc. facility syslog
#                               $2 = MESSAGE a loger
# ex: g_log_message "INFO" "script arrêté"
function g_log_message ()
{
        local TYPE=$1
        local MESSAGE=$2
        #Mise à jour de la date et de l'heure
        G_DATE=`date +%d\ %b\ %T`
        G_JOUR=`date "+%A"`
        # On prépare le formatage du type d'erreur pour le systeme SYSLOG (utilisation des priorités de logger : les "facilities" de syslog)
        case $TYPE in
                INFO)           LOG_FACILITY=local3.info
                                ;;
                ERROR)          LOG_FACILITY=local3.error
                                ;;
                WARNING)        LOG_FACILITY=local3.warning
                                ;;
                # AUTRE_TYPE) LOG_FACILITY=prefix.type
                #       ;;
                *)              #TODO codage type inconnu : on ne fait rien
                                ;;
        esac
        # Mise en forme des informations pour affichage :
        local INFOS_APPLI="$G_NOM_MACHINE $G_APPLI[$G_PID_APPLI]:"
        # ... sur sortie standard
        echo $G_JOUR $G_DATE $INFOS_APPLI [$TYPE] $MESSAGE
        # ... dans le fichier log
        echo $G_JOUR $G_DATE $INFOS_APPLI [$TYPE] $MESSAGE >> $G_FICHIER_LOG
        # ... dans les log du système d'exploitation
        local DETAIL_APPLI="$G_APPLI[$G_PID_APPLI]"
        $LOGGER -t $DETAIL_APPLI -p $LOG_FACILITY $MESSAGE
        # Si c'est la fin du script on envoie un mail avec le fichier de log complet
        if [ "$MESSAGE" == "$G_MSG_FIN_SCRIPT" ]
        then
                if [ $G_ERREUR -eq 0 ]
                then
                        G_SUJET_MAIL="SUCCES : $G_SUJET_MAIL"
                else
                        G_SUJET_MAIL="ECHEC : $G_SUJET_MAIL"
                fi
                # On log la tache en cours ...
                echo $G_JOUR $G_DATE $INFOS_APPLI [$TYPE] "Courriel de notification" >> $G_FICHIER_LOG
                # Puis on prépare le fichier du courriel ($G_COURRIEL_TXT) et on lui ajoute le contenu du log ($G_FICHIER_LOG)
                echo -e "Subject: "$G_SUJET_MAIL"\r\n""Content-Type: text/plain; charset=UTF-8""\r\n" > $G_COURRIEL_TXT
                $CAT $G_FICHIER_LOG >> $G_COURRIEL_TXT
                # On envoie le courriel
                $CAT $G_COURRIEL_TXT | $MSMTP $G_CONTACTS_MAIL
                # ... et on les supprime (option -v disparue)
                $RM -f $G_FICHIER_LOG
                $RM -f $G_COURRIEL_TXT
        fi
}
function statutSF ()
{
        # Statistiques diverses 
        echo "" >> $G_FICHIER_LOG
        echo " >>>> Statistiques du système de fichiers ..." >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
        $DF -Hl >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
}
function statutSFServeur ()
{
        local server=$1
        # Statistiques diverses
        echo "" >> $G_FICHIER_LOG
        echo " >>>> Statistiques du système de fichiers distant de \""$server\"" ..." >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
        local   command="$DF -Hl"
        $SSH $server $command >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
}
function statusSmartServeur ()
{
        local server=$1
        shift # On enlève le premier arguments ($SERVEUR), pour traiter les devices (/dev/sdx)
        while [ $# -ge 1 ]; do #on sort après avoir traiter tous les arguments $#=0) => LOOP pas top a virer !!! ASAP
                # Récupération état SMART du périphérique passé en paramètre ...
                echo "" >> $G_FICHIER_LOG
                echo " >>>> Etat SMART du périphérique \""$1\"" de \""$server\"" ..." >> $G_FICHIER_LOG
                echo "" >> $G_FICHIER_LOG
                local   command="$SMARTCTL -H -i $1"
                $SSH $server $command >> $G_FICHIER_LOG
                echo "" >> $G_FICHIER_LOG
                shift
        done
}
function statusCephServeur ()
{
        local server=$1
        # Récupération état SMART du périphérique passé en paramètre ...
        echo "" >> $G_FICHIER_LOG
        echo " >>>> Etat du système de fichiers distribué CEPH de \""$server\"" ..." >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
        local   command="$CEPH health"
        $SSH $server $command >> $G_FICHIER_LOG
        local   command2="$CEPH df"
        $SSH $server $command2 >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
}
function statusRaidServeur ()
{
        local server=$1
        # Récupération état système RAID ...
        echo "" >> $G_FICHIER_LOG
        echo " >>>> Etat du système RAID de \""$server\"" ..." >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
        local   command="$CAT /proc/mdstat"
        $SSH $server $command >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
}
function statutBorgBackup ()
{
        local borgBackupRepository=$1
        # Chemin complet des outils utilises A GARDER POUR PORTABILITÉ MULTI-PLATEFORME etc ...
        local BORG='/usr/bin/borg'
        echo "" >> $G_FICHIER_LOG
        echo " >>>> Statistiques du système de sauvegarde ..." >> $G_FICHIER_LOG
        $BORG list $borgBackupRepository >> $G_FICHIER_LOG
        echo "" >> $G_FICHIER_LOG
}
function serveurJoignable ()
{
         local server=$1
         $SSH $server $HOSTNAME > /dev/null
         ret=$?
         if [ $ret -ne 0 ];then # ... erreur  pour récupérer le nom d'hote du serveur distant 
                G_ERREUR=$ret
                g_log_message "ERROR" "Serveur \"$server\" injoignable, ssh: \"$G_ERREUR\""
                return $G_ERREUR
         else
                g_log_message "INFO" "Serveur \"$server\" en ligne"
                return 0
         fi
}
function gestionService ()
{
        local action=$1
        local service=$2
        $SYSTEMCTL $action $service
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur à l'arrêt/démarrage du service
                G_ERREUR=$ret
                g_log_message "ERROR" "$action \"$service\" impossible \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "$action \"$service\""
                return 0
        fi
}
function gestionServiceServeur ()
{
        local server=$1
        local action=$2
        local service=$3
        # Serveur en ligne ?
        serveurJoignable $server
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur serveur injoignable, on sort avec le code erreur.
                return $ret
        fi
        local   command="$SYSTEMCTL $action $service"
        $SSH $server $command > /dev/null
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur à l'arrêt/démarrage du service
                G_ERREUR=$ret
                g_log_message "ERROR" "Serveur \"$server\" : \"$action\" \"$service\"  impossible \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Serveur \"$server\" : \"$action\" \"$service\""
                return 0
        fi
}
function demontage ()
{
        local   pointMontage=$1
        $UMOUNT $pointMontage
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur au démmontage
                G_ERREUR=$ret
                g_log_message "ERROR" "Impossible de démonter \"$pointMontage\" erreur \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Démontage de \"$pointMontage\""
                return 0
        fi
}
function montageHdd ()
{
        local   pointMontage=$1
        $MOUNT $pointMontage
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur au montage
                G_ERREUR=$ret
                g_log_message "ERROR" "Impossible de monter \"$pointMontage\" erreur \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Montage de \"$pointMontage\""
                return 0
        fi
}
function montageSshFS ()
{
        local SSHFS='/usr/bin/sshfs'
        #local SSHFS='/usr/bin/sshfs -oCiphers=arcfour'
        local server=$1
        local pointMontage=$2
        $SSHFS $server:/ $pointMontage &>> $G_FICHIER_LOG
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur au montage
                G_ERREUR=$ret
                g_log_message "ERROR" "Impossible de monter \"$pointMontage\" de \"$server\" erreur \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Montage \"$pointMontage\"  de \"$server\""
                return 0
        fi
}
#function sauvegardeBase () # SI utilisé : CODE à RELIRE !!!
#{
#
#}
function sauvegardeBasesServeur ()
{
        local server=$1 #serveur cible
        local dbType=$2 #mysql ou postgresql
        local dbDumpDir=$3 #répertoire ou sera placé le dump sur le $server distant
        # Chemin complet des outils utilises A GARDER POUR PORTABILITÉ MULTI-PLATEFORME etc ...
        local MYSQLDUMP='/usr/bin/mysqldump'
        local POSTGRESQLDUMP='/usr/bin/pg_dump'
        local POSTGRESQLDUMPALL='/usr/bin/pg_dumpall'
        local SYNC='/bin/sync'
        local dbUser=''
        local dbName=''
        local dbPwd=''
        # Preparation env. dump sur serveur distant  
        # Note : Il n'y a théoriquement plus de transaction sur la base de données car les services susceptibles de provoquer des update etc sont arrêtés, les FS SYNC
        local command="$SSH $server [ -d $dbDumpDir]"
        if [ command ];then # Si le repertoire ou sera déposé le dump n'est pas présent  ...
                local   command="$MKDIR -p $dbDumpDir" # ... alors nous le créons.
                $SSH $server $command > /dev/null
                ret=$?
                if [ $ret -ne 0 ];then # ... erreur à la création du répertoire contenant le dump des bases de données
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Impossible d'acceder au repertoire de dump \"$dbDumpDir\" erreur \"$G_ERREUR\""
                        return $G_ERREUR
                fi
        fi
        case $dbType in
                mysql)
                        # On test si MySQL est présent ... sinon on sort
                        command="$WHICH mysql"
                        $SSH $server $command > /dev/null
                        ret=$? # On stocke le code retour de la commande
                        if [ $ret -ne 0 ];then # ... erreur
                                g_log_message "WARNING" "\"$dbType\" non disponible"
                                return 0
                        fi
                        # ... mysql présent , on continue !
                        dbName='--all-databases' # Toutes les bases (option Mysql, donc ne pas changer SVP!!!!!)
                        dbUser='root'
                        dbPwd=$pwd_cache
                        # Préparation de la commande pour MySql
                        #local  command="$MYSQLDUMP -u$dbUser -p$dbPwd -h localhost --single-transaction --opt $dbName  > $dbDumpDir/$server-$dbType-$dbName.sql"
                        local  command="$MYSQLDUMP -u$dbUser -p$dbPwd -h localhost --opt $dbName  > $dbDumpDir/$server-$dbType-$dbName.sql"
                        ;;
                postgresql)
                        # On test si PostgreSQL est présent ... sinon on sort
                        command="$WHICH psql"
                        $SSH $server $command > /dev/null
                        ret=$? # On stocke le code retour de la commande
                        if [ $ret -ne 0 ];then # ... erreur
                                g_log_message "WARNING" "\"$dbType\" non disponible"
                                return 0
                        fi
                        # ... postgresql présent , on continue !
                        dbName='--full' # Toutes les bases (nommage ilinux)
                        dbUser='postgres' # fonctionne avec le fichier /root/.pgpass, en chmod 0600, et un password à postgres  (psql : \password)
                        # Préparation de la commande pour PostgreSQL
                        local  command="$POSTGRESQLDUMPALL -U $dbUser -h localhost > $dbDumpDir/$server-$dbType-$dbName.sql"
                        ;;
                *)      # Base de donnée inconnue : ERREUR
                        G_ERREUR=1
                        g_log_message "ERROR" "Impossible de sauvegarder le type de base \"$dbType\""
                        return $G_ERREUR
                        ;;
        esac
        # On lance l'export des bases de données :
        $SSH $server $command > /dev/null
        ret=$? # On stocke le code retour de la commande
        # on  teste le resultat de l'export des bases de données :
        if [ $ret -ne 0 ];then # ... erreur durant le dump(export)
                G_ERREUR=$ret
                g_log_message "ERROR" "Export impossible des bases \"$dbType\" erreur \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Export des bases \"$dbType\" sous \"$dbDumpDir\""
        fi
        # Compression de l'export des bases de données, avec SYNC du systéme de fichiers préalable :
        command="$SYNC ; $GZIP -f $dbDumpDir/$server-$dbType-$dbName.sql"
        $SSH $server $command > /dev/null
        ret=$? # On test le resultat de la compression ...
        if [ $ret -ne 0 ];then # ... erreur durant la compression de l'export
                G_ERREUR=$ret
                g_log_message "ERROR" "Compression impossible du fichier \"$dbDumpDir/$server-$dbType-$dbName.sql\" erreur \"$G_ERREUR\""
                return $G_ERREUR
        else
                g_log_message "INFO" "Compression du fichier \"$dbDumpDir/$server-$dbType-$dbName.sql\" sous \"$dbDumpDir\""
                return 0
        fi
        
        # On synchronise les I/O (entrée sorties du système de fichiers en vue de la sauvegarde BorgBackup)
        $SYNC
}
######### FONCTION ######################################################
#
# Sauvegarde une liste de répertoire vers une destination avec BorgBackup
# Param IN      $1 = Serveur à sauvegarder
#               $2 = dépot BorgBackup à utiliser
#               $3 = Répertoires à sauvegarder
#
# Ex. appel : sauvegardeBorgBackup $SERVER "$depotBorgBackup" "$repertoiresAsauvegarder"
#
# Note la politique de rétention de données est : --keep-within=15d --keep-weekly=4 --keep-monthly=12 --keep-yearly=5
#                                               - 5 ans,
#                                               - 12 mois,
#                                               - 4 semaines,
#                                               - 15 jours consécutifs,
function sauvegardeBorgBackupServeur () # sauvegarde serveur distant avec sshFS
{
        local server=$1
        local borgBackupRepo=$2
        local dirsToBackup=$3
        local borgMntPoint="/root/Prod/mnt/BorgBackup/$server" # Point de montage du système de fichiers du serveur distant (/, racine)
        # Chemin complet des outils utilises A GARDER POUR PORTABILITÉ MULTI-PLATEFORME etc ...
        local BORG='/usr/bin/borg'
        local SYNC='/bin/sync'
        # Serveur en ligne ?
        serveurJoignable $server
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur serveur injoignable, on sort avec le  code erreur.
                return $ret
        fi
        # Verification du répertoire du point de montage pour sshFS
        if [ ! -d $borgMntPoint ];then # Si le repertoire pour le pt de montage de sshFS n'est pas présent  ...
                $MKDIR -p $borgMntPoint # ... alors nous le créons.
                ret=$?
                if [ $ret -ne 0 ];then # ... erreur à la création du repertoire (sshFS)
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Impossible de creer le repertoire pour sshFS \"$borgMntPoint\" erreur \"$G_ERREUR\""
                        return $G_ERREUR
                fi
        fi
        # Montage du système de fichier / (root/racine)  distant sur $borgMntPoint (répertoire temporaire pour la sauvegarde)
        montageSshFS $server $borgMntPoint
        ret=$?
        if [ $ret -ne 0 ];then # ... erreur pour le montage du systéme de fichiers distant, on sort avec le code erreur.
                return $ret
        fi
        # Verification du dépot BorgBackup $borgBackupRepo 
        if [ ! -d $borgBackupRepo ];then # Si le dépôt BorgBackup n'est pas présent  ...
                $BORG init --encryption=none $borgBackupRepo # ... alors nous le créons, sans cryptage (CPU eater...).
                ret=$?
                if [ $ret -ne 0 ];then # ... erreur à la création du dépôt BorgBackup
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Impossible d'initialiser le dépôt BorgBackup \"$borgBackupRepo\" erreur \"$G_ERREUR\""
                        # ARRET de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
                        $SYNC #synchro des IO disques (pour laisser un FS distant propre)
                        demontage $borgMntPoint
                        return $G_ERREUR
                fi
        fi
        # On lance la sauvegarde ...
        g_log_message "INFO" "Sauvegarde de \"$dirsToBackup\" en cours"
        # ... on corrige le bug
        export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
        $BORG create -v --stats $borgBackupRepo::$server-{now:%d_%m_%Y:%M} $dirsToBackup &>> $G_FICHIER_LOG
        # On vérifie que la sauvegarde s'est bien déroulée ...
        ret=$?
        if [ $ret -eq 2 ];then # ... erreur durant la sauvegarde, on sort en erreur.
                G_ERREUR=$ret
                g_log_message "ERROR" "Borg backup erreur \"$G_ERREUR\""
                # ARRET de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
                $SYNC #synchro des IO disques
                demontage $borgMntPoint
                return $G_ERREUR
        else
                #Rétention, 15 jours, 4 semaines, 1 par mois, sur 5 ans ...
                $BORG prune --error --keep-within=15d --keep-weekly=4 --keep-monthly=12 --keep-yearly=5 $borgBackupRepo &>> $G_FICHIER_LOG
                # On vérifie que la rétention a bien fonctionné ... (nettoyage des anciennes sauvegardes)
                ret=$?
                if [ $ret -eq 2 ];then # ... erreur durant la rétention, on sort en erreur.
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Borg prune erreur \"$G_ERREUR\""
                        # ARRET de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
                        $SYNC #synchro des IO disques
                        demontage $borgMntPoint
                        return $G_ERREUR
                fi
        fi
        # Fin de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
        $SYNC #synchro des IO disques
        demontage $borgMntPoint
}
function sauvegardeBorgBackup () # Sauvegarde locale
{
        local server=$1
        local borgBackupRepo=$2
        local dirsToBackup=$3
        # Chemin complet des outils utilises A GARDER POUR PORTABILITÉ MULTI-PLATEFORME etc ...
        local BORG='/usr/bin/borg'
        local SYNC='/bin/sync'
        # Verification du dépot BorgBackup $borgBackupRepo 
        if [ ! -d $borgBackupRepo ];then # Si le dépôt BorgBackup n'est pas présent  ...
                $BORG init --encryption=none $borgBackupRepo # ... alors nous le créons, sans cryptage.
                ret=$?
                if [ $ret -ne 0 ];then # ... erreur à la création du dépôt BorgBackup
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Impossible d'initialiser le dépôt BorgBackup \"$borgBackupRepo\" erreur \"$G_ERREUR\""
                        # ARRET de la sauvegarde
                        $SYNC #synchro des IO disques
                        return $G_ERREUR
                fi
        fi
        # On lance la sauvegarde ...
        g_log_message "INFO" "Sauvegarde de \"$dirsToBackup\" en cours"
        # ... on corrige le bug
        export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
        $BORG create -v --stats $borgBackupRepo::$server-{now:%d_%m_%Y:%M} $dirsToBackup &>> $G_FICHIER_LOG
        # On vérifie que la sauvegarde s'est bien déroulée ...
        ret=$?
        if [ $ret -eq 2 ];then # ... erreur durant la sauvegarde, on sort en erreur.
                G_ERREUR=$ret
                g_log_message "ERROR" "Borg backup erreur \"$G_ERREUR\""
                # ARRET de la sauvegarde
                $SYNC #synchro des IO disques
                return $G_ERREUR
        else
                #Rétention, 10 jours, 4 semaines, 1 par mois, sur 5 ans ...
                $BORG prune --error --keep-within=15d --keep-weekly=4 --keep-monthly=12 --keep-yearly=5 $borgBackupRepo &>> $G_FICHIER_LOG
                # On vérifie que la rétention a bien fonctionné ... (nettoyage des anciennes sauvegardes)
                ret=$?
                if [ $ret -eq 2 ];then # ... erreur durant la rétention, on sort en erreur.
                        G_ERREUR=$ret
                        g_log_message "ERROR" "Borg prune erreur \"$G_ERREUR\""
                        # ARRET de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
                        $SYNC #synchro des IO disques
                        demontage $borgMntPoint
                        return $G_ERREUR
                fi
        fi
        # Fin de la sauvegarde (on synchronise les i/O et demonte le système de ficher racine distant)
        $SYNC #synchro des IO disques
}

Ordonnancement de l'automatisation de l'exploitation d'iLinux v1

/var/spool/cron/crontabs/root

crontab -l
MAILTO=""
###############################"##
# Sauvegarde serveurs Prod (LAN20)
# 
20 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh nsmaster > /dev/null
30 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh ns > /dev/null
40 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh nsbackup > /dev/null
20 1 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_fd.sh ldap1 > /dev/null
# Grosse volumetrie (courriels, nuages, sites ...)
00 2 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh mx1 > /dev/null
30 2 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_web-db.sh web1 > /dev/null
00 3 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_web-db.sh web2 > /dev/null
30 3 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_web-db.sh web3 > /dev/null
##################################
# Sauvegarde serveurs Prod (DMZ10)
#
50 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh ns1 > /dev/null
00 1 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh ns2 > /dev/null
10 1 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh rpx1 > /dev/null
30 1 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh rpx2 > /dev/null
00 5 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_web-db.sh web666 > /dev/null
00 6 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh proxy1 > /dev/null
00 4 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh rmx1 > /dev/null
20 4 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh rmx2 > /dev/null
#################################
# Sauvegarde serveurs Prod (ADMIN)
#
10 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_srv_std.sh bastion > /dev/null
00 0 * * * /root/Prod/Scripts/Sauvegardes/sauvegarde_local_std.sh orion > /dev/null

Courriel généré par l'exploitation quotidienne iLinux v1

Serveur Web (DMZ)

>>>> sav_srv_ilinux.sh sur serveur : "websrv", executé le lundi 14 oct. 05:00:01
 
lundi 14 oct. 05:00:01 websrv sav_srv_ilinux.sh[2838]: [INFO] DEBUT-SCRIPT
lundi 14 oct. 05:00:01 websrv sav_srv_ilinux.sh[2838]: [INFO] Parametres : "websrv"
lundi 14 oct. 05:00:01 websrv sav_srv_ilinux.sh[2838]: [INFO] Serveur "websrv" en ligne
lundi 14 oct. 05:00:01 websrv sav_srv_ilinux.sh[2838]: [INFO] Serveur "websrv" : "stop" "nginx"
lundi 14 oct. 05:00:02 websrv sav_srv_ilinux.sh[2838]: [INFO] Export des bases "mysql" sous "/root/Prod/Sauvegardes/Bases"
lundi 14 oct. 05:00:02 websrv sav_srv_ilinux.sh[2838]: [INFO] Compression du fichier "/root/Prod/Sauvegardes/Bases/websrv-mysql---all-databases.sql" sous "/root/Prod/Sauvegardes/Bases"
lundi 14 oct. 05:00:03 websrv sav_srv_ilinux.sh[2838]: [INFO] Export des bases "postgresql" sous "/root/Prod/Sauvegardes/Bases"
lundi 14 oct. 05:00:04 websrv sav_srv_ilinux.sh[2838]: [INFO] Compression du fichier "/root/Prod/Sauvegardes/Bases/websrv-postgresql---full.sql" sous "/root/Prod/Sauvegardes/Bases"
lundi 14 oct. 05:00:04 websrv sav_srv_ilinux.sh[2838]: [INFO] Serveur "websrv" en ligne
lundi 14 oct. 05:00:04 websrv sav_srv_ilinux.sh[2838]: [INFO] Montage "/root/Prod/mnt/BorgBackup/websrv" de "websrv"
lundi 14 oct. 05:00:04 websrv sav_srv_ilinux.sh[2838]: [INFO] Sauvegarde de "/root/Prod/mnt/BorgBackup/websrv/etc /root/Prod/mnt/BorgBackup/websrv/root /root/Prod/mnt/BorgBackup/websrv/home /root/Prod/mnt/BorgBackup/websrv/var" en cours
------------------------------------------------------------------------------
Archive name: websrv-14_10_2019:00
Archive fingerprint: dae2ce16ahdfh4df9hd4h94dh4h9dd14fc6fcd6fe6ff8573378a55022f5dfd1
Time (start): Mon, 2019-10-14 05:00:05
Time (end):   Mon, 2019-10-14 05:01:18
Duration: 1 minutes 13.38 seconds
Number of files: 51726
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
This archive:                1.21 GB              1.21 GB             30.24 MB
All archives:               36.33 GB             36.33 GB              2.45 GB
 
                       Unique chunks         Total chunks
Chunk index:                   42252              1554816
------------------------------------------------------------------------------
 
lundi 14 oct. 05:01:22 websrv sav_srv_ilinux.sh[2838]: [INFO] Démontage de "/root/Prod/mnt/BorgBackup/websrv"
lundi 14 oct. 05:01:22 websrv sav_srv_ilinux.sh[2838]: [INFO] Serveur "websrv" en ligne
lundi 14 oct. 05:01:22 websrv sav_srv_ilinux.sh[2838]: [INFO] Serveur "websrv" : "start" "nginx"
 
 >>>> Statistiques du système de fichiers distant de "websrv" ...
 
Sys. de fichiers                       Taille Utilisé Dispo Uti% Monté sur
/dev/mapper/Raid1Data-vm--107--disk--0   270G    2,8G  253G   2% /
none                                     504k       0  504k   0% /dev
udev                                     8,4G       0  8,4G   0% /dev/tty
tmpfs                                    8,4G    4,1k  8,4G   1% /dev/shm
tmpfs                                    8,4G     18M  8,4G   1% /run
tmpfs                                    5,3M       0  5,3M   0% /run/lock
tmpfs                                    8,4G       0  8,4G   0% /sys/fs/cgroup
tmpfs                                    1,7G       0  1,7G   0% /run/user/1000
tmpfs                                    1,7G       0  1,7G   0% /run/user/0
 
 
 >>>> Statistiques du système de sauvegarde ...
 
websrv-31_07_2019:00                 Wed, 2019-07-31 05:00:02
websrv-31_08_2019:00                 Sat, 2019-08-31 05:00:02
websrv-08_09_2019:00                 Sun, 2019-09-08 05:00:03
websrv-15_09_2019:00                 Sun, 2019-09-15 05:00:03
websrv-22_09_2019:00                 Sun, 2019-09-22 05:00:03
websrv-29_09_2019:00                 Sun, 2019-09-29 05:00:03
websrv-30_09_2019:00                 Mon, 2019-09-30 05:00:02
websrv-01_10_2019:00                 Tue, 2019-10-01 05:00:02
websrv-02_10_2019:00                 Wed, 2019-10-02 05:00:02
websrv-03_10_2019:00                 Thu, 2019-10-03 05:00:03
websrv-04_10_2019:00                 Fri, 2019-10-04 05:00:02
websrv-05_10_2019:00                 Sat, 2019-10-05 05:00:02
websrv-06_10_2019:00                 Sun, 2019-10-06 05:00:03
websrv-06_10_2019:45                 Sun, 2019-10-06 16:45:04
websrv-06_10_2019:50                 Sun, 2019-10-06 16:50:36
websrv-06_10_2019:52                 Sun, 2019-10-06 16:52:29
websrv-06_10_2019:56                 Sun, 2019-10-06 16:56:27
websrv-06_10_2019:12                 Sun, 2019-10-06 17:12:17
websrv-06_10_2019:15                 Sun, 2019-10-06 17:15:59
websrv-06_10_2019:18                 Sun, 2019-10-06 17:18:03
websrv-06_10_2019:22                 Sun, 2019-10-06 20:22:09
websrv-06_10_2019:16                 Sun, 2019-10-06 21:16:29
websrv-07_10_2019:00                 Mon, 2019-10-07 05:00:08
websrv-08_10_2019:00                 Tue, 2019-10-08 05:00:05
websrv-09_10_2019:00                 Wed, 2019-10-09 05:00:05
websrv-10_10_2019:00                 Thu, 2019-10-10 05:00:05
websrv-11_10_2019:00                 Fri, 2019-10-11 05:00:05
websrv-12_10_2019:00                 Sat, 2019-10-12 05:00:05
websrv-13_10_2019:00                 Sun, 2019-10-13 05:00:05
websrv-14_10_2019:00                 Mon, 2019-10-14 05:00:05
 
lundi 14 oct. 05:01:23 websrv sav_srv_ilinux.sh[2838]: [INFO] FIN-SCRIPT
lundi 14 oct. 05:01:23 websrv sav_srv_ilinux.sh[2838]: [INFO] Courriel de notification

Script de synchronisation Rsync serveur local / distant

./rsync_srv_STD.sh

#!/bin/bash
###############################################################################
#                                                                             #
# PGM     : Script de synchronisation rsync serveur local / distant           #
#                                                                             #
# AUTEUR  : Stephane  (iLinux)                                                #
# VERSION : 1.0.0                                                             #
#                                                                             #
# DATE    : 24/10/2019                                                        #
#                                                                             #
# PARAM.  : N/A                                                               #
#           OUT > logger + mail                                               #
#                                                                             #
###############################################################################
# EN PREMIER LIEU
# On inclus les fonctions et variables communes:
. /root/Prod/Scripts/sauvegarde/outils/fonctions_variables.sh
# Variables de travail ...
# ... LOCALES
# ... DISTANTES
# N/A
# Au commencement il n'y a jamais d'erreur ... dans un script
G_ERREUR=0
# Serveur à sauvegarder :
SERVEUR=$1
# Surcharge var. fichier log (en attendant serveur mail !)
#G_FICHIER_LOG="/root/Prod/Journaux/Sauvegardes/$SERVEUR.log"
# Script actuellement en cours d'execution
echo "SCRIPT    : $G_APPLI"
echo "" >> $G_FICHIER_LOG
echo ">>>> $G_APPLI sur serveur : \"$SERVEUR\", executé le $G_JOUR $G_DATE">> $G_FICHIER_LOG
echo "" >> $G_FICHIER_LOG
# 1 seul paramétre attendu
#if [ $# = 1 ] || [ -z "$1"]
#then
#       G_ERREUR='Donnez 1 nom de serveur svp ...'
#       # On sort du script avec $G_ERREUR
#       g_log_message "ERROR" $G_MSG_FIN_SCRIPT
#       exit $G_ERREUR
#fi
# DEBUT DU SCRIPT
g_log_message "INFO" $G_MSG_DEBUT_SCRIPT
g_log_message "INFO" "Parametres : \"$*\""
# Lancement de la synchronisation avec le serveur $SERVEUR...
repertoireSourceDistant="/Sauvegardes/Prod/"
repertoireCibleLocal="/Externalisation/"
synchroServeur $SERVEUR "$repertoireSourceDistant" "$repertoireCibleLocal"
# On audit le système de fichier local (volumétrie etc)
statutSF
# On sort du script avec $G_ERREUR
g_log_message "INFO" $G_MSG_FIN_SCRIPT
exit $G_ERREUR
# FIN DU SCRIPT