Accueil > Informatique > Un script de sauvegarde en Python, sous GNU/Linux avec rsync

Un script de sauvegarde en Python, sous GNU/Linux avec rsync

Il y a quelques temps, j’avais écrit un article expliquant comment réaliser une sauvegarde différencielle avec rsync sous GNU/Linux. J’ai récemment décidé de le réécrire en Python pour plusieurs raisons…

  • J’aime ce langage 🙂 et ça me permet de progresser.
  • Je ne suis pas un expert en script bash et le script Python m’autorise plus de souplesse ainsi qu’une maintenance plus aisée.

L’idée principale, outre l’utilisation de la sauvegarde différentielle (et donc la notion de snapshots pour pouvoir « remonter dans le temps ») est de pouvoir utiliser plusieurs media. Ainsi en passant un argument en ligne de commande, il est possible de choisir le medium à utiliser. Il peut être de deux types : local (autre disque dur, appareil USB…) ou sur une machine distante via ssh.

Vous pouvez télécharger le script complet. Pensez à changer l’extension .txt en .py !

Quelques explications sur les constantes du début du programme :

  • La variable NICE_LEVEL permet simplement d’indiquer la priorité avec laquelle la copie des données via rsync va être effectuée.
  • On définit ensuite la variable DIR_TO_BACKUP qui va préciser quels sont les répertoires à sauvegarder et ceux à éventuellement exclure.
  • BACKUP_DEST indique les paramètres de la destination vers laquelle les données seront copiées. Il s’agit d’un dictionnaire contenant un autre dictionnaire Python. Le premier identifie les différents media et le second les paramètres relatifs à ce dernier, qui sont :
    • dir : obligatoire indique le répertoire destination (qui doit exister).
    • server : optionnel, adresse du serveur en cas de copie par ssh.
    • port : optionnel, port du serveur en cas de copie par ssh.
    • login : optionnel, login utilisé pour se connecter au serveur en cas de copie par ssh.

    A noter qu’en cas de copie par ssh, je fais l’hypothèse qu’on utilise une clé ssh pour se connecter et qu’il n’y a donc pas besoin de mot de passe.

  • ARCHIVE_NB précise le nombre de sauvegarde à conserver.

Ensuite il y a la fonction backup qui effectue comme son nom l’indique la sauvegarde :

Je n’expliquerai pas ici le détail de la programmation, car il n’y a en principe rien à toucher à ce niveau. Voici les grandes étapes :

  • On commence par supprimer l’archive la plus ancienne.
  • On effectue un décalage des archives : la 1 devient 2, la 2 devient 3 etc.
  • On effectue une copie par hardlink de l’archive 0 vers l’archive 1. Cette technique permet d’éviter une duplication des données et économise beaucoup d’espace. Seules les données inexistantes sont copiées les autres sont des simples liens.
  • Enfin on effectue une synchronisation par rsync entre le(s) répertoire(s) à sauvegarder et l’archive 0.

A noter que pour les opérations sur disque (copie, déplacement…), je n’ai pas utilisé les commandes « natives » Python, car dans le cas d’un serveur distant elles ne sont pas utilisables.

L’analyse des paramètres passées en ligne de commande :

Si vous souhaitez ajouter / supprimer des media, il faudra effectuer des modifications dans la partie __main__ du programme ainsi que dans la traditionnelle fonction usage qui indique les arguments qui peuvent être passés à l’application. Je pense que le code parle de lui-même à ce niveau. A noter simplement que j’ai imposé d’être root pour pouvoir exécuter le programme et ainsi copier des dossiers système, mais il n’y a évidemment pas d’obligation…

Ce script peut très certainement être amélioré, n’hésitez pas à me faire part de vos commentaires.

Categories: Informatique Tags: .: GNU/Linux .: python .: rsync
  1. G-rom
    27/08/2010 à 13:14 | #1

    ou sinon y a Grsync
    http://doc.ubuntu-fr.org/grsync

  2. Marco
    27/08/2010 à 13:33 | #2

    @G-rom
    Heu oui certes, le but de l’article étant autant didactique qu’utile. Il est clair que ce script n’a pas pour vocation d’être un logiciel intuitif pour l’utilisateur final.

  3. Félix Faure
    27/08/2010 à 14:19 | #3

    Quelle idée de faire un article présentant en français un script dont les commentaires et les variables sont en anglais ?

  4. nyquist
    27/08/2010 à 14:57 | #4

    Bravo!!

    tu viens de réinventer dirvish : http://www.dirvish.org (mais il est en perl donc forcement moins bien 😉 )

  5. Marco
    27/08/2010 à 15:26 | #5

    @Félix Faure
    C’est une habitude professionnelle 🙂 Je code toujours en anglais…
    Mais sincèrement je ne pense pas que ce soit très gênant, il n’y a que quelques commentaires.

  6. olivier
    27/08/2010 à 17:31 | #6

    C’est bien beau de ré-écrire ton programme en Python, mais si c’est pour faire appel à des commandes systèmes, autant rester sous /bin/sh.

    Python possède un grand nombre de modules et de fonctions (certes il faut chercher un peu), pour se passer largement de os.system(…)

  7. Marco
    27/08/2010 à 17:50 | #7

    @olivier
    Si tu relis l’article :
    1) Plus de souplesse : tu m’expliqueras comment faire des dictionnaires en bash
    2) Plus de lisibilité : pour moi c’est plus évident à maintenir en Python
    3) Appels systèmes car je ne vois pas comment exécuter des commandes distantes via ssh en utilisant les commandes python standards sur la manipulation des fichiers. Si tu sais je suis preneur. De plus elles n’apportent pas grand chose à part la portabilité. Merci de me dire que Python possède un grand nombre de modules et de fonctions je ne savais pas 😉

    Après je comprends qu’un expert « bash » n’y voit pas d’intérêt. Chacun ses choix.
    Je suis juste un peu irrité d’avoir ce genre de commentaire posté après avoir lu l’article à la va vite (en gros juste le code Python et pas le descriptif).

  8. olivier
    27/08/2010 à 19:42 | #8

    @Marco
    En bash tu peux créer des tableaux.

    Je suis d’accord avec toi concernant le lisibilité, la plupart de mes scripts, je les fais en Python, et je ne suis pas un expert en bash, puisque je ne l’utilise pas.

    Concernant le script en lui-même, ton dictionnaire DIR_TO_BACKUP, tu peux sans doute le remplacer par os.walk. Les tests sur les fichiers, dossiers tu peux le faire par le module os.path

    Pour des connexions à distances, il existe des modules (pas en standard), qui doivent certainement gérer ssh bien mieux, de même pour rsync
    De plus pour accéder à tes périphériques, tu pourrais utiliser le module ioctl (voir s’inspirer du module CDROM), ou pourquoi pas de dbus (là, il faudra installer py-dbus).

    Si tu préfères garder tes commandes, utilise plutôt le module subprocess.

    Je tiens à te citer « Ce script peut très certainement être amélioré, n’hésitez pas à me faire part de vos commentaires. » donc tient compte des remarques de tes lecteurs.

  9. Marco
    28/08/2010 à 06:26 | #9

    @olivier
    Tout à fait d’accord avec toi pour l’aspect critique et je tiens compte des commentaires de mes lecteurs, c’est tout l’intérêt de partager un article.
    Ce que je voulais dire c’est que au lieu de laisser un commentaire du style « Ton script est nul, autant le faire en bash », autant tout de suite proposer quelque chose de positif : « Tiens au lieu de faire des appels système tu pourrais utiliser tel ou tel module ». C’est beaucoup plus positif et on gagne du temps ;-).
    Ton commentaire est là beaucoup plus constructif et je te remercie pour les pistes que tu donnes.

  10. Yada
    20/01/2012 à 16:55 | #10

    J’étais entrain d’écrire un script du même genre. Et hop, un tour sur google search, je suis sur bonne adresse. J’ai trouvé le script très bien. Je vais l’essayer et probablement le modifier un peu. Pour moi il offre un grand avantage : ce qu’il est en python. 😉

  11. Marco
    20/01/2012 à 17:17 | #11

    Oui ceci dit, comme l’ont remarqué certaines personnes, il conviendrait de l’écrire dans un style plus « Pythonique » :-). Bon après c’est sûr qu’il marche je l’utilise régulièrement depuis des mois…

  1. Pas encore de trackbacks