So finden Sie heraus, ob zwei Verzeichnisse auf denselben Speicherort verweisen

8

Zeigen die folgenden Pfade auf denselben Speicherort?

/home/username
/app/home/username
Mykhaylo Adamovych
quelle
Es gibt keine universelle Antwort; Dies hängt davon ab, wie Ihr System konfiguriert ist.
G-Man sagt 'Reinstate Monica'
@ G-Man - Unix wurde auf seinen fs aufgebaut, und das wurde auf Seriennummern aufgebaut - oder auf Inodes . (Wikipedia zitiert sogar Dennis Ritchie zu seiner Etymologie ) . Während Inodes sind gerätespezifisch, bekommen genau diese Geräte ihre eigene Obermenge von Seriennummern in Gerätenummern. Selbst auf Systemen, auf denen Sie Verzeichnisse fest verknüpfen können, sind alle Links immer noch dasselbe Verzeichnis, da sie denselben Inode auf demselben Gerät verwenden. Sie sollten dies problemlos auf jedem Unix-System testen können.
Mikeserv
Verwandte: stackoverflow.com/questions/33980224/…
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功

Antworten:

7

Wechseln Sie nacheinander in jedes Verzeichnis und sehen Sie sich die Ausgabe von an pwd -P. Mit dem -PFlag pwdwird das physische aktuelle Arbeitsverzeichnis mit allen aufgelösten symbolischen Links angezeigt.

Kusalananda
quelle
Obwohl dies wahr ist (obwohl Sie nur cd -Pden aufgelösten Verzeichnisnamen verwenden könnten $PWD) , wird das Problem separater Geräte nicht behandelt .
Mikesserv
Was ist das Problem von separaten Geräten?
Kusalananda
3
sd(){       set '' "$1" '' "${2?sd() requires two arguments!}"
            while [ "$#" -gt 2 ]
            do    [  "${1:--L}" "${2:--L}" ${3:+"$4"} ] &&
                  [  "${1:--L}" ${3:+"-L"} "${3:-$4}" ] &&
                  [  "${2:-$3}" -ef "$4"/. ] && return  || ${1:+"return"}
                  set "$@" "$2";shift 2;set ! "$@"
            done  3>/dev/null 2>&"$((${#DBG}?2:3))"
    }

sd()Zuerst wird geprüft, ob beide Argumente Symlinks sind, und in diesem Fall wird geprüft, ob beide mit Verzeichnissen mit identischen Inode- und Gerätenummern verknüpft sind. Wenn ja, ist es sd() returnwahr

Andernfalls wird überprüft, ob beide keine Symlinks sind und ob beide Verzeichnisse mit gleichen Geräte- und Inode-Nummern sind. Andernfalls wird false zurückgegeben.

Damit...

ln -s dir1 ln3; ln -s dir1 ln4; ln -s dir2 ln5

sd dir1 dir2; echo $?
1
sd dir1 ln3;  echo $?
1
sd ln4 ln3;   echo $?
0
sd ln4 ln5;   echo $?
1
mount --bind dir1 dir2
sd dir1 dir2; echo $?
0

Es kann wünschenswert sein, auf die Linkprüfung zu verzichten - zum Beispiel, wenn Sie wissen möchten, ob das Ziel eines Links mit einem Verzeichnis identisch ist oder ob es sich überhaupt nicht um einen Link handelt. In diesem Fall benötigen Sie nur einen [ fname1 -ef fname2 ]Test.

Oh, ich denke, ich sollte auch erwähnen, dass dies Suchberechtigungen für alle Argumente voraussetzt. Es schlägt fehl, wenn der aufrufende Benutzer nicht über die zum Ausführen des Tests erforderlichen Berechtigungen verfügt.

mikeserv
quelle
1

Sie können nie sicher sein, welcher Mechanismus oder welche virtuellen Dateisysteme oder Overlay-Dateisysteme vorhanden sind, um diese Ordner zu synchronisieren oder miteinander zu verknüpfen. Wenn es sich um eine einfache symbolische Verknüpfung handelt, unterscheiden sich die Inodes. Um 100% sicher zu stellen, dass es sich um denselben Speicherort handelt, können Sie eine Datei erstellen in /home/username:

touch /home/username/.testfile

Vergleichen Sie dann die Inode-Nummern dieser Datei an beiden Speicherorten:

diff <(stat -c "%i" /home/username/.testfile) <(stat -c "%i" /app/home/username/.testfile)

Wenn sie gleich sind, handelt es sich um dieselbe Datei, daher verweisen sie auf denselben Speicherort.

Trotzdem können Sie nicht 100% sicher sein. Natürlich können sie zufällig die gleiche Inode-Nummer haben, denn in beiden Dateisystemen hatte die nächste freie Inode die gleiche Nummer ...

Chaos
quelle
2
Sie müssen die Gerätenummer neben der Inode-Nummer überprüfen. Die Inode-Nummer allein ist in der Tat unzureichend.
Gilles 'SO - hör auf böse zu sein'
1

Es gibt zwei grundlegende Möglichkeiten, um zu überprüfen, ob zwei Dateien identisch sind. Der erste besteht darin, zu überprüfen, ob ihre Pfade gleich sind . Dies hat keine falsch positiven, aber viele falsch negative Ergebnisse. Ein offensichtlicher Fall von falsch negativen Ergebnissen ist, wenn symbolische Verknüpfungen beteiligt sind. Sie können diesen Fall behandeln, indem Sie die symbolischen Links auflösen. Für vorhandene Verzeichnisse, in die Sie wechseln dürfen, ist dies möglich pwd -P.

absolute_path1="$(cd -- "$path1" && pwd -P; echo .)" &&
absolute_path2="$(cd -- "$path2" && pwd -P; echo .)" &&
[ "$absolute_path1" = "$absolute_path2" ]

Das Extra echo .kümmert sich um den seltenen Fall, dass eines der Ziele einen Dateinamen hat, der mit einer neuen Zeile endet: Wenn die neue Zeile das letzte Zeichen der Befehlsersetzung wäre, würde sie entfernt, sodass das Snippet fälschlicherweise meldet, dass dies foo␤dasselbe ist wie foo.

Es gibt immer noch mögliche falsche Negative. Bei Verzeichnissen spielen feste Verknüpfungen keine Rolle, da die meisten Betriebssysteme und Dateisysteme das Verknüpfen von Verzeichnissen verbieten. Was passieren kann ist, dass dasselbe Verzeichnis irgendwie an verschiedenen Orten verfügbar gemacht wird, wie zum Beispiel:

  • Mounten des gleichen Remote-Dateisystems an zwei verschiedenen Orten, z

    mount server:/some/where /mnt1
    mount server:/some/where /mnt2
    compare /mnt1 /mnt2
    
  • Ein Bind Mount

  • Jedes stapelbare Dateisystem, dh eine Möglichkeit, ein Dateisystem auf eine andere Art und Weise darzustellen, wobei Sie die Ansicht des Verzeichnisses als ausreichend unverändert gegenüber dem Original betrachten, sodass es praktisch dasselbe Verzeichnis ist. Beispiel: Ein stapelbares Dateisystem, das Dateinamen konvertiert, und der Name des Verzeichnisses ist bei der Konvertierung unveränderlich.

In diesen Beispielen ist fraglich, ob die Verzeichnisse wirklich gleich sind. Dies zeigt die Grenze des Begriffs "gleiche Datei" in Randfällen.

Die zweite grundlegende Möglichkeit besteht darin , die vom Kernel bereitgestellte Identifikation zu überprüfen: Gerät und Inode . Der statSystemaufruf meldet zwei Attribute für jede Datei:

  • die Gerätenummer ( st_dev), die traditionell eine Identifikation des Blockgeräts (Festplattenpartition) ist, das das Dateisystem enthält, auf dem sich die Datei befindet;
  • die inode number ( st_ino), die traditionell eine eindeutige Nummer ist, die die Datei innerhalb desselben Dateisystems identifiziert.

Normalerweise sind zwei Dateien genau dann identisch, wenn sie die gleichen Geräte- und Inode-Nummern haben. Dash, ksh, bash, zsh und zumindest einige BusyBox-Builds (aber nicht einfache POSIX sh) haben einen -efOperator für das testeingebaute System, der Folgendes testet:

[ "$path1" -ef "$path2" ]

Dies behandelt Hardlinks und symbolische Links korrekt (symbolische Links werden befolgt, dh ein symbolischer Link zu einer Datei wird als derselbe wie die Zieldatei angesehen).

Diese Methode ist am einfachsten durchzuführen, wenn Ihre Shell (oder Ihr testDienstprogramm) dies unterstützt -ef. Beachten Sie jedoch, dass es falsch positive Ergebnisse gibt, da nicht alle Dateisysteme eindeutige Inode-Nummern melden. Bei Netzwerkdateisystemen sind Sie beispielsweise der Wahl der Inode-Nummern des Remote-Hosts ausgeliefert. Viele stapelbare Dateisysteme melden den zugrunde liegenden Inode, der nicht eindeutig ist, wenn der zugrunde liegende Verzeichnisbaum mehrere Dateisysteme umfasst.

Ein anderer Ansatz besteht darin , die beobachtbare Äquivalenz zu testen : Ändern Sie eines der Verzeichnisse und prüfen Sie, ob sich die Änderung im anderen widerspiegelt. Dieser Ansatz hat im Prinzip keine falschen Negative, erfordert jedoch die Berechtigung zum Ändern der Verzeichnisse und kann andere Teile des Systems stören, die diese Verzeichnisse verwenden. Es kann zu Fehlalarmen kommen, da die angezeigten Änderungen darauf hinweisen können, dass ein Daemon die Verzeichnisse sehr schnell synchronisiert.

Gilles 'SO - hör auf böse zu sein'
quelle
0

Unter der Annahme , /home/usernameund /app/home/usernamesind Verzeichnisse, können Sie die Inode - Nummer nicht überprüfen , um zu sehen , ob sie den gleichen Weg sind. Dies liegt daran, dass Verzeichnisse nicht fest verknüpft werden können und Softlinks einen anderen Inode aufweisen.

Sie könnten cd /home/username, um toucheine Datei, und sehen , ob es in der anderen erscheint /app/home/username. Es gibt wahrscheinlich bessere Methoden. Wenn jemand eine bessere Antwort geben kann, fahren Sie bitte fort.

DR_
quelle
1
Das ist nicht ganz richtig. Wenn Sie mount --bindein Verzeichnis haben, wird der Mount-Punkt mit demselben Inode aufgelistet. Gleiches gilt, wenn Sie ein Dateisystem an zwei Speicherorten bereitstellen. Ich habe dies gerade auf einem von Debian abgeleiteten System überprüft.
Äh? Sie können den Inode überprüfen. Wenn einer der Pfade ein Symlink ist, müssen Sie natürlich das Ziel überprüfen.
Gilles 'SO - hör auf böse zu sein'
0

Wenn Sie das erweitern, was marco gesagt hat: Unter GNU / Linux erhalten ls -li /home/username /app/home/usernameSie bereits einen guten Hinweis . Wenn beide Inodes gleich wahrscheinlich sind, zeigen sie auf denselben Ort. Überprüfen Sie mit mount. Überprüfen Sie touchdreimal, /home/usernameob eine Datei in /app/home/username und mit demselben Inode angezeigt wird . Dann kann ziemlich sicher sein, dass es das gleiche Verzeichnis ist.

Test auf einem Linux Mint-Computer, 3.11.0-12-generischer Kernel:

# ls -ldi /var
2 drwxr-xr-x 13 root root 4096 jan 13  2014 /var

# mkdir /mnt/var
# ls -ldi /mnt/var
266483 drwxr-xr-x 2 root root 4096 jun  2 10:43 /mnt/var

# mount --bind /var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 2 root root 4096 jun  2 10:43 /mnt/var

# umount /mnt/var
# mount /dev/mapper/mint--vg-var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 13 root root 4096 jan 13  2014 /mnt/var

Fazit: Ich denke, Sie können die Inodes überprüfen, um sicherzustellen, dass zwei Verzeichnisse identisch sind, vorausgesetzt, sie sind Mount-Punkte. Wenn es sich um eine symbolische Verknüpfung handelt, gilt das oben Gesagte natürlich nicht. Aber dann ist es offensichtlich, richtig:

# rmdir /mnt/var
# ln -s /var /mnt/
# ls -ldi /mnt/var
266483 lrwxrwxrwx 1 root root 4 jun  2 10:51 /mnt/var -> /var
Gemeinschaft
quelle