Überprüfen Sie, ob unter Linux zwei Verzeichnisse auf derselben Partition gehostet werden


9

Wie kann ich überprüfen, ob /my/dirsich auf derselben Partition befindet wie /?

Dies dient zur Integration in ein Skript. Bindungshalterungen sollten korrekt gehandhabt werden. POSIX-kompatible Lösungen sind willkommen.


"Bindungshalterungen sollten korrekt gehandhabt werden." Aber was halten Sie für richtig? Ihre Frage kann so oder so interpretiert werden.
Gilles 'SO - hör auf böse zu sein'

@ Gilles Im Originaltitel habe ich "gehostet" statt "gemountet" geschrieben, jemand hat meiner Meinung nach Verwirrung hinzugefügt. Mein Fragetext ist jedoch klar: "Auf derselben Partition", dh auf derselben physischen Partition, unabhängig vom Pfad oder Mountpunkt, der für den Zugriff auf die beiden Dateien / Verzeichnisse verwendet wird.
Totor

Antworten:


6

Sie können dies mit stat überprüfen:

$ stat -c '%d %m' /proc/sys/
3 /proc

Zeigt Ihnen die Gerätenummer und den Ort an, an dem Ihr Verzeichnis bereitgestellt wurde.


1
Schön, aber der statShell-Befehl ist nicht POSIX ...
Totor

Nein? Woher weißt du das?

Nicht in dieser Liste .
Totor

Oh mein schlechtes. Aber das nächste Mal diesen Link im Voraus zeigen.

5

Der folgende Befehl gibt einen eindeutigen Namen für den Einhängepunkt an, der die Datei enthält $file:

df -P -- "$file" | awk 'NR==2 {print $1}'

Dies funktioniert auf jedem POSIX- System. Die -POption legt ein vorhersehbares Format fest. Das erste Feld der zweiten Zeile ist der "Dateisystemname". Um zu überprüfen, ob sich zwei Dateien unter demselben Einhängepunkt befinden:

if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
     "$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

Oder, um einige Prozessaufrufe zu speichern:

if df -P -- "$file1" "$file2" |
   awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

Einige Betriebssysteme können Leerzeichen in Datenträgernamen enthalten. dfIn diesem Fall gibt es keine absolut zuverlässige Methode zum Parsen der Ausgabe.

Unter der Haube können Sie das Dateisystem, das eine Datei enthält, anhand des von zurückgegebenen st_devFelds identifizieren stat. Es gibt keine tragbare Möglichkeit, dies über ein Shell-Skript zu tun. Einige Systeme haben ein statDienstprogramm, aber die Syntax variiert:

  • Unter nicht eingebettetem Linux statmeldet Cygwin oder andere Systeme mit GNU-Coreutils das st_devFeld beim Aufrufen als stat -c %D -- "$file".
  • Einige BusyBox-Installationen enthalten eine, statdie mit GNU-Coreutils kompatibel ist. Andere haben statohne die %cOption; Sie können verwenden stat -t -- "$file" | awk '{print $8}', dies funktioniert jedoch nur, wenn der Dateiname kein Leerzeichen enthält oder stat -t -- "$file" | awk 'END {print $(NF-8)}'mit beliebigen Dateinamen, jedoch nicht mit zukünftigen Hinzufügungen von Feldern zur statAusgabe zurechtkommt.
  • BSD-Systeme haben einen anderen statNutzen, der dies erfordert stat -f %d -- "$file".
  • Solaris, AIX und andere haben kein statDienstprogramm.

Wenn Perl verfügbar ist, können Sie verwenden

perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"

und um den Vergleich zu machen:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"

Beachten Sie, dass es einige Eckfälle gibt, in denen das gewünschte Ergebnis nicht klar ist. Zum Beispiel mit Linux Bind Mounts, nach mount --bind /foo /bar, /foound /barwerden als das gleiche Dateisystem sein. Es ist immer möglich, dass sich die beiden Dateien tatsächlich auf demselben Gerät befinden, aber Sie werden es nie erfahren: Wenn sich die Dateien beispielsweise auf zwei verschiedenen Netzwerk-Mounts befinden, kann der Client nicht feststellen, ob der Server unterschiedliche Dateisysteme exportiert.

Wenn es sich bei den Dateien um Verzeichnisse handelt und Sie darauf schreiben können, besteht eine andere Methode darin, eine temporäre Datei zu erstellen und zu versuchen, eine feste Verknüpfung herzustellen. Dieser meldet ein negatives Ergebnis für alle Linux-Bindungs-Mounts.

tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
  echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"

Problem: dfnicht gibt immer die Gerätenamen, aber irgendwann einen symbolischen Link , um es wie /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4macht dfnicht zuverlässig. Die einzige zuverlässige Option ist bisher die Verwendung einer statLösung auf Basis.
Totor

@Totor Das spielt keine Rolle: Unabhängig vom Namen dfdes Geräts ist die Übereinstimmung zwischen den beiden Aufrufen konsistent, sodass ein Vergleich in Ordnung ist.
Gilles 'SO - hör auf böse zu sein'

Nein, es funktioniert nicht, ich habe es getestet. Auf Debian Wheezy hier ein einziger dfBericht /dev/sda6und /dev/disk/by-uuid/ca09b...beide beziehen sich auf dasselbe Gerät, aber unterschiedliche Mountpunkte. Der Zeichenfolgenvergleichstest schlägt offensichtlich fehl, wenn versucht wird, Dateien von jedem Einhängepunkt zu verwenden.
Totor

@Totor Normalerweise kann nicht dasselbe Blockgerät zweimal montiert werden. Wie ich in meiner Antwort angedeutet habe, gibt es Eckfälle wie Bindungshalterungen, die als unterschiedlich gemeldet werden können oder nicht.
Gilles 'SO - hör auf böse zu sein'

Dennoch funktioniert es perfekt bei Debian Squeeze und Wheezy: mount /dev/sda6 /mnt1gefolgt von mount /dev/sda6 /mnt2Arbeiten wie ein Zauber. cat /proc/mountsist gut damit. Jedoch ist es , da nur Wheezy , die /dev/disk/by-uuid/ca09b...in gezeigt wird , dfwie die Vorrichtung für das Root - Dateisystem. Weitere Versuche, es über diesen Simlink oder die UUID=ca09b...Mount-Syntax zu mounten, zeigen nichts anderes als /dev/sda6in df(Ich weiß nicht, wie ich reproduzieren soll, was es während des Startvorgangs getan hat, aber das ist hier nicht das Problem).
Totor

4
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1

Funktioniert mit einer beliebigen Anzahl von Pfaden.


Das Analysieren der Ausgabe von dfist nicht immer eine gute Idee .
Joseph R.

1
@Totor Ich überprüfe den Mountpoint ( $6), nicht den Gerätenamen ( $1), also sollte das kein Problem sein.
21.

1
@ JosephR Es ist das Beste, was es in POSIX gibt. n.st: warum nicht das erste Feld ankreuzen? Es spielt keine Rolle, welcher Pfad für den Zugriff auf das Gerät verwendet wurde. Wenn es sich um denselben Einhängepunkt handelt, ist die Ausgabe konsistent.
Gilles 'SO - hör auf böse zu sein'

Dies funktioniert nicht mit Bindungs-Mounts.
Totor

0

Die beste narrensichere Lösung in POSIX ist der Vergleich der Geräte-IDs der Dateien, die von der Funktion stat (2) bereitgestellt werden .

Perl hat eine ähnliche Stat Funktion wie Gilles wies darauf hin :

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2

Der "POSIX-Weg" besteht jedoch darin, ein C-Programm wie das folgende zu verwenden:

./checksamedev file1 file2

Welcher Quellcode lautet wie folgt:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    struct stat s1, s2;
    if( argc==3 && lstat(argv[1], &s1)==0 && lstat(argv[2], &s2)==0 )
        return !(s1.st_dev == s2.st_dev);
    return 2;
}

Wenn die Geräte-IDs beider Dateien gleich sind, werden sie auf demselben Dateisystem gehostet. In diesem Fall geben die obigen Befehle 0 zurück (ansonsten ein anderer Wert). Überprüfen Sie mit echo $?.

Dies funktioniert gut mit Bindungs-Mounts, aber wahrscheinlich nicht mit Netzwerk-Mounts.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.