Script d'archivage incrémental et transfert sftp automatique

Script d’archivage incrémental et transfert sftp automatique

Pré-requis pour que le script suivant fonctionne :

1 - Paramétrer sur le poste à sauvegarder un accès ssh au serveur de sauvegarde via un système d’authentification par clé privée / publique.

Tout est expliqué ici : Connexion à une machine distante (ssh, scp, sftp) sans saisir le mot de passe | Mon pense-bête

2 - Le programme bzip2 doit être installé sur le poste à sauvegarder.

$ apt-get install bzip2

3 - Rendre les scripts exécutables

$ chmod +x uploadBackup.sh && chmod +x fonctions.inc.sh

Script d’archivage incrémental et transfert sftp automatique

Ce script permet d’effectuer une sauvegarde incrémentale d’un répertoire vers un serveur de sauvegarde.
Il utilise un système de niveau correspondant au jour du mois - 1.
Tous les 1er de chaque mois, une sauvegarde totale (niveau 0) est effectuée.
Une sauvegarde incrémentale est effectuée les jours suivants.

Le script est composé de 2 fichiers.
Un fichier comportant le script principal (uploadBackup.sh) et un fichier comportant les fonctions personnalisées utiles au script principal (fonctions.inc.sh).

Les fichiers à sauvegarder (variable DATADIR) sont enregistrés dans une archive CPIO compressée avec BZIP2 et stockée dans un répertoire local sur le poste à sauvegarder (variable ARCHIVEDIR).
Avant chaque sauvegarde, un fichier de niveau est créé dans le répertoire local.
Toutes les logs sont enregistrées dans un fichier stocké également dans le répertoire local.
La sauvegarde incrémentale utilise le fichier niveau précédent afin de sauvegarder tous les fichiers modifiés depuis la sauvegarde précédente grâce à la commande find et l’option -newer.
Enfin, l’archive CPIO est envoyée sur le serveur de sauvegarde (variable serveur_sauvegarde) via SFTP et stockée dans des sous-répertoires correspondant à l’année et au mois de la sauvegarde dans le dossier de sauvegarde (variable dossier_distant) .

Détail du fichier uploadBackup.sh

$ nl uploadBackup.sh
     1  #!/bin/bash
     2  # set -x
     3  # Répertoire des scripts shell
     4  SCRIPTDIR="/root/script_archivage_incremental"
     5  # Répertoire des fichiers à sauvegarder
     6  DATADIR="/root/dossier_a_sauvegarder"
     7  # Répertoire local des archives
     8  ARCHIVEDIR="/root/local_backup"
     9  # Inclure les fonctions
    10  . $SCRIPTDIR/fonctions.inc.sh
    11  # Fichier de log
    12  LOG=$ARCHIVEDIR/`getDate`.log
    13  # Redirection de toutes les sorties du script vers le fichier de log
    14  exec 1>$LOG 2>&1
    15  # Déterminer le niveau de sauvegarde
    16  # Le 1er du mois => niveau 0
    17  jourDuMois=`getDayForCalcul`
    18  ((niveau=$jourDuMois-1))
    19  case $niveau in
    20          0) # Sauvegarde totale
    21                  # Nettoyage du répertoire d'archive
    22                  rm -i $ARCHIVEDIR/*.bz2 $ARCHIVEDIR/niveau*
    23                  # Création du fichier de niveau (niveau 0)
    24                  touch $ARCHIVEDIR/niveau0
    25                  archive="$ARCHIVEDIR/`getDate`_niveau0.cpio"
    26                  find $DATADIR | cpio -ocv | bzip2 -c > $archive.bz2
    27                  ;;
    28          *)
    29                  # Creation du fichier de niveau
    30                  touch $ARCHIVEDIR/niveau$niveau
    31                  archive="$ARCHIVEDIR/`getDate`_niveau${niveau}.cpio"
    32                  # Determination du niveau precedent
    33                  ((niveauPrec=$niveau-1))
    34                  # Test si le fichier de niveau precedent existe
    35                  if [[ ! -f $ARCHIVEDIR/niveau$niveauPrec ]]
    36                  then
    37                          # Si il n'existe pas, sauvegarde integrale du repertoire
    38                          echo "Fichier de niveau $niveauPrec inexistant"
    39                          echo "Execution d'une sauvegarde integrale en cours de mois"
    40                          find $DATADIR | cpio -ocv | bzip2 -c > $archive.bz2
    41                  else
    42                          # Sauvegarde incrementale
    43                          find $DATADIR -newer $ARCHIVEDIR/niveau$niveauPrec | cpio -ocv | bzip2 -c > $archive.bz2
    44                  fi
    45                  ;;
    46  esac
    47  # Vérification de la validité de l'archive
    48  if isArchiveInvalide $archive.bz2 ; then
    49          echo "Archive $archive.bz2 INVALIDE - Fichier non transfere"
    50          exit 1
    51  fi
    52  # Transfert du fichier vers le serveur de sauvegarde
    53  if transfert ${archive}.bz2 ; then
    54          echo "Transfert realise avec succes"
    55          exit 0
    56  fi
    57  # Si le transfert a echoue
    58  echo "Echec de transfert"
    59  exit 1
$

Détail du fichier fonctions.inc.sh

$ nl fonctions.inc.sh
     1  #!/bin/bash
     2  function transfert {
     3          typeset mois
     4          typeset annee
     5          # Recuperation de la valeur du premier argument passe a la fonction
     6          # Recuperation du nom de l'archive a envoyer au serveur de sauvegarde
     7          typeset ficATransferer=$1
     8          # Adresse du serveur de sauvegarde
     9          typeset serveur_sauvegarde="192.168.1.113"
    10          # Compte utilise pour se connecter au serveur de sauvegarde
    11          typeset user="root"
    12          # Chemin absolu du dossier ou sera stocke la sauvegarde
    13          typeset dossier_distant="/root/sauvegarde_dossier"
    14          mois=`getMonth`
    15          annee=`getYear`
    16          # Test si le dossier de sauvegarde existe sur le serveur de sauvegarde
    17          # Connexion au serveur avec le user root
    18          ssh $user@$serveur_sauvegarde test -d $dossier_distant/$annee/$mois
    19          # Test sur le code retour de la commande precedente
    20          case $? in
    21                  0)
    22                          ;;
    23                  255)
    24                          echo "Echec de la commande SSH"
    25                          return 1
    26                          ;;
    27                  *)
    28                          # Si code retour different de 0 et 255
    29                          # Creation du repertoire de la sauvegarde
    30                          ssh $user@$serveur_sauvegarde mkdir -p $dossier_distant/$annee/$mois
    31                          ;;
    32          esac
    33          # Connexion au serveur de sauvegarde en FTP sécurisé
    34          # Ne pas oublier les doubles chevrons << avant le mot cle FIN
    35          # Ne pas mettre d'espace entre << et FIN
    36          sftp -b - $user@$serveur_sauvegarde <<FIN
    37          # Positionnement dans le repertoire de la sauvegarde
    38          cd $dossier_distant/$annee/$mois
    39          pwd
    40          # Envoi de la sauvegarde
    41          put $ficATransferer
    42  FIN
    43  # Ne pas mettre de tabulation ou d'espace devant le mot clé FIN
    44  # Sinon celui-ci n'est pas reconnu
    45          # Test sur le code retour de la commande SFTP
    46          # Si le code retour est different de 0
    47          # Une anomalie a ete rencontree
    48          (( $? != 0 )) && return 1
    49          # Tester si archive valide sur serveur de sauvegarde
    50          ficSurMachineCible=$(basename $ficATransferer)
    51          ssh $user@$serveur_sauvegarde bzip2 -t $dossier_distant/$annee/$mois/$ficSurMachineCible
    52          case $? in
    53                  0)
    54                          ;;
    55                  255)
    56                          echo "Echec de la commande SSH"
    57                          return 1
    58                          ;;
    59                  *)
    60                          # Si code retour different de 0 et 255
    61                          # Alors l'archive est invalide
    62                          echo "Archive $dossier_distant/$annee/$mois/$ficSurMachineCible INVALIDE"
    63                          return 1
    64                          ;;
    65          esac
    66          return 0
    67  }
    68  function isArchiveInvalide {
    69          typeset archive=$1
    70          bzip2 -t $archive 2>/dev/null && return 1
    71          return 0
    72  }
    73  function getDate {
    74          date '+%Y_%m_%d'
    75  }
    76  function getYear {
    77          date '+%Y'
    78  }
    79  function getMonth {
    80          date '+%m'
    81  }
    82  function getDayForCalcul {
    83          date '+%e' | sed 's/ //'
    84  }
$