Forum Linux.général Taille d'un dossier contenant des hardlink

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes : aucune
4
5
juin
2014

Bonjour,

J'ai un répertoire où je stock mes fichiers sauvegardés copiés avec rsync. La structure est la suivante :

    - backup
      \_ 2014-06-03
      \_ 2014-06-04
      \_ 2014-06-05
      \_ current

Les dossiers 2014-06-* correspondent aux sauvegardes des jours précédent et current à la dernière sauvegarde. Afin de mettre en place une sorte de déduplication, si un fichier dans current est identique avec celui d'une précédente sauvegarde alors un hardlink est créé, c'est rsync qui gère ça avec l'option link-dest.

Maintenant j'ai besoin d'évaluer la place prise par le dossier current et un dossier d'une précédente sauvegarde. Si j'utilise

$ du -hs current
332 Go

$ du -hs 2014-06-05
332 Go

J'ai comme l'impression qu'il y a un truc qui va pas, est-ce qu'il y a un moyen d'exclure pour 2014-06-05 le hardlink de façon à ne pas les prendre en compte dans le calcul ?

  • # Il n'y a pas moyen de le savoir

    Posté par  (site web personnel) . Évalué à 7.

    Un lien physique entre deux fichiers est fondamentalement différent d'un lien symbolique et ses caractéristiques rend ton opération impossible.

    En effet, un lien physique partage le même inode dans le système de fichier que sur le fichier qu'il point. Ce fichier référencera bien le fait qu'il y a 2 pointeurs (de chemins différents) vers cet inode. Mais comme c'est le même inode, à partir du moment où le lien physique est crée, le lien physique est strictement identique que celui à l'origine, car comme ils ont le même inode, ils partagent tous les points en commun. Sauf le nom d'accès au fichier, car le nom n'est pas stocké dans l'inode.

    D'ailleurs pour t'en convaincre, tu fais un lien physique avec un autre fichier dans le même dossier, avec un ls -l tu verras bien que les 2 noms pour ce fichier ont tous les 2 le compteurs à 2 (voire plus) de références d'accès, et aucun des d'eux n'aura une mention spéciale de type s (contrairement au lien symbolique qui est un fichier plus spécial).

    Bref, ta requête est fondamentalement impossible à satisfaire à cause du lien physique. La meilleure solution pour toi serait presque de faire un système différentiel avec rsync ce qui n'utilise pas de liens physiques, permet de visualiser ce que tu veux, ne prends pas plus d'espace sur le disque, etc.

    • [^] # Re: Il n'y a pas moyen de le savoir… quoique

      Posté par  . Évalué à 7.

      J'aurais eu tendance à dire la même chose que Renault, puis j'ai testé.
      J'ai deux répertoires dir1 et dir2. Dans dir1, je mets un fichier file1 de quelques gigaoctets.
      Dans dir2, je crée un lien hard vers le fichier dir1/file1 :

      $ ls -lhi dir1/
      total 4,9G
      531142 -rw-r--r-- 2 user user 4,9G juin   5 16:11 file1
      
      $ ls -lhi dir2/
      total 4,9G
      531142 -rw-r--r-- 2 user user 4,9G juin   5 16:11 file2
      
      $ du -sh dir1/
      4,9G    dir1/
      $ du -sh dir2
      4,9G    dir2
      
      $ du -sh dir1/ dir2/
      4,9G    dir1/
      4,0K    dir2/
      
      $ du -sh dir2/ dir1/
      4,9G    dir2/
      4,0K    dir1/
      

      Je suis sur le cul vachement surpris.
      Pour info, j'ai un noyau 3.14 et les GNU coreutils en version 8.21.
      Il semblerait donc que du dédoublonne.

      D'ailleurs, du a une option "-l" ou "--count-links" pour «comptabiliser les tailles plusieurs fois dans le cas des liens directs» (extrait du man et en anglais ça donne «count sizes many times if hard linked») et l'option est déjà présente dans la version 5.97.

      Donc, pour répondre à Philippe, il suffit d'exécuter la commande du une seule fois pour les deux répertoires :

      du -hs current 2014-06-05
      
      • [^] # Re: Il n'y a pas moyen de le savoir… quoique

        Posté par  (site web personnel) . Évalué à 2. Dernière modification le 05 juin 2014 à 16:47.

        ah bah vi étonnant je viens de tester sur mon serveur et ça marche :

        du -hs 2014-06-04 current/
        332G 2014-06-04
        263G current/
        

        Moi qui m'étais lancé dans des trucs compliqué à coups de find et autre sed… Ce qui est encore plus perturbant c'est quand j'ajoute un 3eme répertoire :

        du -hs 2014-06-03 2014-06-04 current/
        331G 2014-06-03
        27G 2014-06-04
        263G current/

        Born to Kill EndUser !

      • [^] # Re: Il n'y a pas moyen de le savoir… quoique

        Posté par  (site web personnel) . Évalué à 2.

        Cela ne contredit pas ce que je dis, apparemment les fichiers avec le compteurs de lien à 2 ou plus, il compare les inodes et si c'est le même il remplace l'un des deux chemins par une taille d'un block car ils sont identiques.
        Mais comme tu le vois, selon l'ordre de l'appel, ce n'est pas le même dossier qui est accrédité comme "celui qui possède véritablement le fichier", ce qui rend bien indiscernable le chemin de fichier d'origine et le nouveau.

        Mais c'est vrai qu'en comparer les inodes, il est possible de faire quelque chose comme ça, je n'y avais pas pensé. Cela ne change pas la réalité sous jacente pour le système de fichier.

        • [^] # Re: Il n'y a pas moyen de le savoir… quoique

          Posté par  (site web personnel) . Évalué à 1.

          Dans mon cas peut importe la "source" réelle puisque c'est la taille qui m'importe.

          D'un autre côté puisque c'est un lien la notion de fichier source n'est pas vraiment nécessaire et particulièrement dans le cas des hardlink.

          Born to Kill EndUser !

    • [^] # Re: Il n'y a pas moyen de le savoir

      Posté par  (site web personnel) . Évalué à 2. Dernière modification le 05 juin 2014 à 16:43.

      Merci pour l'explication clair et précise.

      Born to Kill EndUser !

  • # du find links

    Posté par  . Évalué à 3.

    du ne compte les blocks qu'un seule fois.

    si tu as deux fichiers qui pointent sur les mêmes blocks, il ne compte que le premier :

    mkdir dir
    mkdir dir/dir1
    mkdir dir/dir2
    cp c dir/dir1/a
    ln dir/dir1/a dir/dir2/b
    
    du -sh dir/dir1 
    356K dir/dir1
    
    du -sh dir/dir2 
    356K dir/dir2
    
    du -sh dir
    365K dir
    
    du -sh dir/*
    356K    dir/dir1
    4.0K    dir/dir2
    

    tu peux utiliser find pour avoir les blocks pointés par un seul fichier :

    find dir -links 1
    
    find dir -links 2
    dir/dir1
    dir/dir1/b
    dir/dir2
    dir/dir2/b
    

    combiné à du, tu aura ta réponse.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.