Come tracciare efficacemente hardlink in Linux?

Sep 02 2020

I softlink sono facilmente rintracciabili al file originale con readlinkecc ... ma ho difficoltà a rintracciare i collegamenti fisici al file originale.

$ ll -i /usr/bin/bash /bin/bash  
1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /bin/bash*  
1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /usr/bin/bash*
                   ^

sopra è come previsto - bello -> entrambi i file puntano allo stesso inode 1310813
(ma il numero di collegamenti, indicato da ^, risulta essere 1. Dalla risposta di Gilles si può capire il motivo)

$ find / -samefile /bin/bash 2>/dev/null
/usr/bin/bash

sopra è come previsto, quindi nessun problema.

$ find / -samefile /usr/bin/bash 2>/dev/null
/usr/bin/bash  

sopra NON è bello. Come rintraccio il file originale o ogni hardlink utilizzando il /usr/bin/bashfile come riferimento?

Strano - anche di seguito non ha aiutato.

$ find / -inum 1310813 2>/dev/null
/usr/bin/bash

Risposte

45 StephenKitt Sep 02 2020 at 13:26

Innanzitutto, non esiste un file originale nel caso di collegamenti fisici; tutti gli hard link sono uguali.

Tuttavia, i collegamenti fisici non sono coinvolti qui, come indicato dal conteggio dei collegamenti pari a 1 ls -lnell'output di:

$ ll -i /usr/bin/bash /bin/bash  
1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /bin/bash*  
1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /usr/bin/bash*

Il tuo problema sorge a causa di un collegamento simbolico, il bincollegamento simbolico a cui punta usr/bin. Per trovare tutti i percorsi in cui bashè disponibile , è necessario indicare finddi seguire i collegamenti simbolici, utilizzando l' -Lopzione:

$ find -L / -xdev -samefile /usr/bin/bash 2>/dev/null
/usr/bin/rbash
/usr/bin/bash
/bin/rbash
/bin/bash

Sto usando -xdevqui perché so che il tuo sistema è installato su un singolo file system; Ciò evita scendere in /dev, /proc, /run, /sysetc.

24 Gilles'SO-stopbeingevil' Sep 02 2020 at 14:05

come rintraccio il file originale o ogni hardlink usando il file / usr / bin / bash come riferimento

Con GNU find (o qualsiasi altra versione di findquesto ha l' -samefileopzione), e supponendo che /usr/bin/bashsi trovi sul /filesystem, questo è corretto:

find / -xdev -samefile /bin/bash

Da usare -xdevpoiché gli hard link non possono attraversare i confini del filesystem. Non reindirizzare gli errori: se non hai il permesso di attraversare una directory, potrebbe essere presente un hard link sotto quella directory e te lo perderebbe.

L'errore che stai facendo è che stai cercando un altro hard link che non esiste. Hai effettivamente le informazioni per sapere che non esiste:

1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /bin/bash*
                   ^

Il conteggio dell'hard link /bin/bashè 1.

C'è un singolo file in /cui è uguale a /usr/bin/bash. Il file /bin/bashè lo stesso /usr/bin/bashper un motivo diverso: le directory /bin e /usr/binsono lo stesso file. Dal momento che find / -samefile /bin/bashpunta a /usr/bin/bash, /binha un collegamento simbolico a /usr/bin. Più precisamente, dalle informazioni nella domanda, e supponendo che /binnon sia un hard link di directory (una caratteristica scarsamente supportata, usata raramente), sappiamo che /binè un link simbolico che si risolve in /usr/bin; potrebbe essere un collegamento simbolico a un altro collegamento simbolico e così via che alla fine si risolve in /usr/bino verso un percorso equivalente come ///////usr/bin/, ma molto probabilmente è un collegamento simbolico il cui obiettivo è /usr/bin.

La ricerca di tutti i collegamenti simbolici a un file sull'intero sistema non è particolarmente produttiva. Ad esempio, su Linux, c'è un file /proc/*/exeche è un collegamento simbolico a /usr/bin/bash(o /bin/bash) per ogni processo che esegue bash. E se cerchi collegamenti simbolici a una directory, ti ritroverai all'interno di una ricorsione infinita, ad esempio /proc/*/rootpuntando a /(ad eccezione dei processi chroot).

Se hai bisogno di sapere se due percorsi puntano allo stesso file, su Linux puoi usare uno dei due

[ /bin/bash -ef /usr/bin/bash ]
test /bin/bash -ef /usr/bin/bash

( -efnon è POSIX ma è in dash, bash, BusyBox e GNU coreutils). Se devi ottenere un percorso canonico per un file, nel senso che file distinti hanno sempre nomi canonici distinti, puoi utilizzare

readlink -f /bin/bash

(Ciò può perdere file uguali tramite directory montate, ad esempio se lo stesso percorso di rete è montato in due modi diversi.)