Partage
  • Partager sur Facebook
  • Partager sur Twitter

Travail pratique Sauvegarde de partition

    25 mai 2019 à 17:46:16

    Bonjour à tous,

    Je viens de finir un de mes travaux pratiques sur Linux, je cherche quelqu'un qui pourrait m'aider afin de relire mon script et de m'aider à corriger les éventuelles fautes qu'il pourrait y avoir.

    Voici les consignes :

    Le travail consiste à mettre en place un script et un environnement per- mettant d’effectuer à intervalles réguliers la sauvegarde de plusieurs partitions ext4 sous Linux.

    Pour effectuer cette sauvegarde, il existe un outil très pratique: les programmes dump et restore. Ces deux commandes fonctionnent au niveau du périphérique en mode bloc mais permettent tout de même d’effectuer des restaurations de fichiers individuels.

    Depuis quelques temps, plus personne n’est responsable de leur maintenance dans le monde Linux. Ces commandes n’apparaissent donc plus dans les distri- butions. La dernière version du code source est cependant disponible et peut être installée après compilation.

    Il est aussi possible d’utiliser les archiveurs cpio (de préférence) ou tar pour effectuer les sauvegardes.

    Pour réaliser, ce projet il faut effectuer les étapes suivantes:

    1. Ajouter un deuxième disque à la machine virtuelle en suivant les instruc- tions fournies dans les exercices; il faut formater ce disque avec le système de fichiers ext4.

    2. compiler et installer (idéalement dans le répertoire /opt) les programmes dump et restore qui sont fournis avec ce document.

    Cette étape n’est pas nécessaire si vous utilisez la commande cpio, mais l’usage de cette commande ne simplifie pas réellement ce projet. Elle le rend cependant indépendant du système de fichiers ce qui peut être parfois considéré comme un avantage.

    1

    1. Il faut ensuite considérer qu’un mois est toujours composé de 4 semaines et appliquer cette stratégie de sauvegarde:

      1. (a)  Le premier jour de la première semaine de l’année ainsi que le premier jour de toutes les quatre semaines une sauvegarde complète (tous les fichiers) doit être effectuée.

      2. (b)  Les autres jours de la semaine, une sauvegarde de ce qui a été modifié depuis le début de la semaine doit être effectuée.

      3. (c)  Le premier jour d’une semaine (autre qu’une semaine qui est un mul- tiple de 4) toutes les données modifiées depuis le premier jour de la semaine précédente doivent être sauvegardées.

    2. Le nom des fichiers de sauvegardes doit permettre de déduire facilement:

      • Le nom du système de fichiers (ou partition) sauvegardé.

      • Le niveau de la sauvegarde (complète, début de semaine, ou jour de semaine).

      • Le type de programme qui a servi à effectuer la sauvegarde.

      • La date de la sauvegarde.

    3. Il est essentiel que les fichiers de sauvegarde soient copiés sur un disque externe au système et accessible seulement lors de la création de la sau- vegarde (soit une clef USB soit un troisième disque virtuel). Il faudra donc que le script de sauvegarde monte le disque de sauvegarde dans le système au moment de la sauvegarde et le démonte une fois celle-ci terminée.

    4. Il est aussi nécessaire que les anciennes sauvegardes soit régulièrement nettoyées.

    5. Avec chaque sauvegarde, il est nécessaire de produire un journal qui in- dique comment la sauvegarde s’est déroulée. Ces journaux doivent aussi être nettoyés périodiquement.

    6. Il faut ensuite installer le script de sauvegarde dans le système afin qu’il soit exécuté périodiquement (fichier crontab).

    7. Il est possible, mais de manière optionnelle, d’effectuer la sauvegarde de plusieurs partitions de manière simultanée (en parallèle). 

    Voici le code :

    #!/bin/bash
    
    
    #Pour exÈcuter le script tous les jours ‡ 23h55, Èditer le fichier crontab avec la commande
    #crontab -e
    #puis ajouter la ligne
    #55 23 * * * scriptPrincipal.sh
    
    #Il faut au prÈalable avoir exÈcutÈ le script scriptMontage.sh pour monter les partitions
    
    #Fonction de calcul du niveau de sauvegarde selon la date
    niveau()
    {
      #RÈcupÈration des repËres temporels
      #NumÈro du jour de la semaine
      typeset -i JOUR_SEMAINE=`date +%u`
      #NumÈro de la semaine dans l'annÈe (1..53)
      typeset -i SEMAINE=$((`date +%V`-1))
      #NumÈro de la semaine dans le mois (0..3)
      typeset -i NO_SEMAINE=$(( SEMAINE % 4 ))
    
      #Si c'est le premier jour de la premiËre semaine
      if [[ $JOUR_SEMAINE == 1 && $NO_SEMAINE == 0 ]]
      then
        return 0
      #Sinon, si c'est la premiËre semaine du mois
      elif [[ $NO_SEMAINE == 0 ]]
      then
        return 1
      #Sinon, si c'est la deuxiËme semaine du mois
      elif [[ $NO_SEMAINE == 1 ]]
      then
        return 2
      #Sinon, si c'est la troisiËme semaine du mois
      elif [[ $NO_SEMAINE == 2 ]]
      then
        return 3
      #Sinon, si c'est la derniËre semaine du mois
      elif [[ $NO_SEMAINE == 3 ]]
      then
        return 4
      fi
    }
    
    
    typeset -i NIVEAU
    niveau
    NIVEAU=$?
    
    #On rÈcupËre la date de la backup pour les logs
    typeset -r DATE_BACKUP=`date +%F`
    
    #Partition de sauvegarde
    typeset -r DIR_SAUVEGARDE="/mnt/sauvegarde"
    
    #RÈpertoire dans lequel le pÈriphÈrique avec la partition 
    #de sauvegarde sera montÈ
    
    #On dÈfinit les partitions ‡ sauvegarder en fournissant
    #la liste des rÈpertoires dans lesquelles elles sont
    #montÈes (en fournissant le nom du rÈpertoire
    #plutÙt que le nom du pÈriphÈrique, on s'Èvite le problËme
    #des noms de pÈriphÈriques variables). 
    #
    #En principe, la deuxiËme partition a ÈtÈ
    #montÈe dans le rÈpertoire ´/optª (voir scriptMontage.sh)
    typeset -r PART_TO_BACKUP="/ /opt"
    #On dÈfinit le chemin d'exÈcution de la commande dump
    typeset -r CMD_DUMP=/opt/dump
    
    
    
    typeset -r LOG_DIRECTORY="${DIR_SAUVEGARDE}/log/${DATE_BACKUP}"
    if [[ ! -d ${LOG_DIRECTORY} ]]
    then
      mkdir -p ${LOG_DIRECTORY}
    	cdMkdir=$?
    	if [[ ${cdMkdir} == 1 ]]
    	then
    	  echo "Le rÈpertoire des logs n'a pas pu Ítre crÈÈ"
        exit 1
    	fi
    fi
    
    typeset -r LOGFILE=${LOG_DIRECTORY}/$$.log
    
    
    #La sauvegarde doit maintenant s'effectuer avec une boucle
    for part in ${PART_TO_BACKUP}
    do
      #Attention, il faut donner un nom spÈcifique ‡ la partition ´/ª
      #(par exemple ´rootª), mais on peut utiliser directement
      #le nom des autres partitions (par exemple ´/optª
      #sera sauvÈe dans un fichier contenant la chaÓne ´optª.
    	if [[ ! -d ${DIR_SAUVEGARDE}/${DATE_BACKUP} ]]
    	then
        mkdir ${DIR_SAUVEGARDE}/${DATE_BACKUP}
    		cdMkdir=$?
    	  if [[ ${cdMkdir} == 1 ]]
    	  then
    		  echo "Le rÈpertoire de la sauvegarde du ${DATE_BACKUP} n'a pas pu Ítre crÈÈ"
          exit 1
    	  fi
    	fi
    	#touch ${LOGFILE}
      if [[ "${part}" == "/" ]]
      then
          NomPart="root"
      else
          NomPart="${part##*/}"    #Tout ce qui suit le dernier /
      fi
      "${CMD_DUMP}" -${NIVEAU} -u -b 1024 -f "${DIR_SAUVEGARDE}/${DATE_BACKUP}/${NomPart}_${NIVEAU}.dump" ${part} >> ${LOGFILE} 2>&1
    	cdDump=$?
    	if [[ ${cdDump} == 1 ]]
    	then
    	  echo "Le dump de la partition ${part} s'est cassÈ la figure"
        exit 1
    	fi
    done
    
    #Une fois la sauvegarde terminÈe, on dÈmonte la partition
    #(commentÈe ici pour pourvoir consulter les logs aprËs exÈcution du script)
    #umount ${DIR_SAUVEGARDE}
    
    #!/bin/bash
    
    
    typeset -r DIR_BACKUP="/mnt/sauvegarde/"
    
    if [[ ! -d ${DIR_BACKUP} ]]
    then
      mkdir ${DIR_BACKUP}
    	cdMkdir=$?
    	if [[ ${cdMkdir} == 1 ]]
    	then
    		echo "Le rÈpertoire de la partition de backup ${DIR_BACKUP} n'a pas pu Ítre crÈÈ"
    		exit 1
    	fi
    fi
    
    typeset -r DIR_A_SAUVER="/opt"
    if [[ ! -d ${DIR_A_SAUVER} ]]
    then
      mkdir ${DIR_A_SAUVER}
    	cdMkdir=$?
    	if [[ ${cdMkdir} == 1 ]]
    	then
    		echo "Le rÈpertoire de la partition ‡ sauvegarder ${DIR_A_SAUVER} n'a pas pu Ítre crÈÈ"
    		exit 1
    	fi
    fi
    
    #Nom des pÈriphÈriques (‡ modifier selon votre configuration)
    typeset -r PeriphBackup="/dev/sdb"
    typeset -r PeriphASauver="/dev/sdc"
    
    #formatage des pÈriphÈriques
    mkfs.ext4 -j "${PeriphBackup}"
    cdFormattage=$?
    if [[ ${cdFormattage} == 1 ]]
    then
    	echo "Le formatage du pÈriphÈrique ${PeriphBackup} s'est mal passÈ"
    	exit 1
    fi
    
    mkfs.ext4 -j "${PeriphASauver}"
    cdFormattage=$?
    if [[ ${cdFormattage} == 1 ]]
    then
    	echo "Le formatage du pÈriphÈrique ${PeriphASauver} s'est mal passÈ"
    	exit 1
    fi
    
    mount "${PeriphBackup}" "${DIR_BACKUP}"
    cdMount=$?
    if [[ ${cdMount} == 1 ]]
    then
    	echo "Le montage de la partition ${DIR_BACKUP} s'est mal passÈ"
    	exit 1
    fi
    
    mount "${PeriphASauver}" "${DIR_A_SAUVER}"
    cdMount=$?
    if [[ ${cdMount} == 1 ]]
    then
    	echo "Le montage de la partition ${DIR_A_SAUVER} s'est mal passÈ"
    	exit 1
    fi
    

    Merci d'avance pour votre aide :D




    • Partager sur Facebook
    • Partager sur Twitter
      25 mai 2019 à 18:14:35

      salut,

      attention, les noms de variables tout en majuscules sont réservés, par convention, aux variables d'environnement (HOME, PATH...)

      == est un opérateur de comparaison lexical (il compare des mots).
      pour comparer des nombres, il faut utiliser -eq, -ne, -ge...

      si tu n'utilises pas les fonctions avancées de [[, autant utiliser test.

      les développements de variables doivent toujours être entre guillemets; sauf si tu sais pourquoi, ou entre crochets doubles

      les accolades ne sont nécessaires que lorsque est accolé du texte au nom de variable :

      $ var=321
      $ echo "$var"
      321
      $ echo "$varAUTRECHOSE"
      
      $ echo "${var}AUTRECHOSE"
      321AUTRECHOSE

      sinon, ça surcharge inutilement le code.

      parts2backup devrait être un tableau.

      -
      Edité par dantonq 26 mai 2019 à 1:53:40

      • Partager sur Facebook
      • Partager sur Twitter
      « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
        27 mai 2019 à 15:14:01

        Salut,

        Pour commencer petite remarque sur l'énoncer.

        • dump, restore peuvent être remplacer par dd.
        • Il ne faut pas utiliser cpio pour sauvegarder une partition system car il ne sauvegarde pas les attribues étendue qui sont utiliser par de nombreuse distribution maintenant. Il vaut mieux utiliser tar avec l'option -xattr.
        • enfin dans la vrai vie ne réinvente surtout pas un système de backup à base de script shell. Il faut mieux utiliser des outils déjà disponible avec duplacati, duplicity ou les snapshots LVM.

        Premier script fonction niveau :

        • ligne 20 il manque un $ devant SEMAINE
        • comme le fait remarque dantonq il vaut mieux utiliser -eq, -ge et autre lorsque tu compares des nombres.

        Même remarque que dantonq avec [[ ]]

        Même si ici cela ne devrait pas poser de problème il vaut mieux encadrer les variables par des "".

        Pour regarder le résultat d'une commande tu peux le mettre directement dans le if. Par exemple ligne 76:

        if ! mkdir -p ${LOG_DIRECTORY}
        then
            echo "Le répertoire des logs n'a pas pu être crée"
            exit 1
        fi

        L'utilisation des typeset n'est pas courant et propre à bash mais cela reste correcte.

        2e script ligne 34 pourquoi l'option -j ? il n'y a pas d'avantage à avoir une partition ext3 par rapport à l'ext4.

        • Partager sur Facebook
        • Partager sur Twitter
          27 mai 2019 à 17:14:15

          Même si ici cela ne devrait pas poser de problème il vaut mieux encadrer les variables par des "".

          pour des tests arithmétiques, mettre des guillemets ne résoudra pas l'absence de valeur assignée à une variable :

          $ test 12 -eq "$nc"
          bash: test: : nombre entier attendu comme expression

          par contre, si on sait qu'une valeur risque de ne pas être définie lors d'un test, ça vaut la peine de la déclarer au début du script en tant qu'integer, et de lui assigner une valeur (même nulle):

          $ declare -i nombre=''
          $ echo $nombre
          0
          $ test 12 -eq $nombre; echo $?
          1

          on pourrait aussi "prêter" une valeur par défaut, si la variable n'est pas assignée :

          $ test 12 -eq ${emptyVar:-12}
          $ echo "$emptyVar"
          
          $

          ou lui assigner une valeur lors de son développement :

          $ test -12 -eq ${var:=12}
          $ echo "$var"
          12

          ...

          ;)

          -
          Edité par dantonq 27 mai 2019 à 17:14:44

          • Partager sur Facebook
          • Partager sur Twitter
          « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
            27 mai 2019 à 18:10:21

            dantonq a écrit:

            Même si ici cela ne devrait pas poser de problème il vaut mieux encadrer les variables par des "".

            pour des tests arithmétiques, mettre des guillemets ne résoudra pas l'absence de valeur assignée à une variable :


            Je ne pensais pas à la variable vide lorsque j'ai écris ce commentaire.

            Je l'avais écrit lorsque j'ai vu le mkdir avec une variable sans "". J'ai vu plein de script échoué à cause d'un path contenant un espace.

            • Partager sur Facebook
            • Partager sur Twitter
              27 mai 2019 à 19:10:38

              ah, d'accord.

              c'est le cas général :

              les développements de variables doivent toujours* être entre guillemets; sauf si tu sais pourquoi, ou entre crochets doubles

              * comme dans : TOUJOURS

              :)
              • Partager sur Facebook
              • Partager sur Twitter
              « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.

              Travail pratique Sauvegarde de partition

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              • Editeur
              • Markdown