Wie kann ich überprüfen, ob /my/dir
sich auf derselben Partition befindet wie /
?
Dies dient zur Integration in ein Skript. Bindungshalterungen sollten korrekt gehandhabt werden. POSIX-kompatible Lösungen sind willkommen.
Wie kann ich überprüfen, ob /my/dir
sich auf derselben Partition befindet wie /
?
Dies dient zur Integration in ein Skript. Bindungshalterungen sollten korrekt gehandhabt werden. POSIX-kompatible Lösungen sind willkommen.
Antworten:
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.
stat
Shell-Befehl ist nicht POSIX ...
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 -P
Option 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. df
In 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_dev
Felds identifizieren stat
. Es gibt keine tragbare Möglichkeit, dies über ein Shell-Skript zu tun. Einige Systeme haben ein stat
Dienstprogramm, aber die Syntax variiert:
stat
meldet Cygwin oder andere Systeme mit GNU-Coreutils das st_dev
Feld beim Aufrufen als stat -c %D -- "$file"
.stat
die mit GNU-Coreutils kompatibel ist. Andere haben stat
ohne die %c
Option; 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 stat
Ausgabe zurechtkommt.stat
Nutzen, der dies erfordert stat -f %d -- "$file"
.stat
Dienstprogramm.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
, /foo
und /bar
werden 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"
df
nicht gibt immer die Gerätenamen, aber irgendwann einen symbolischen Link , um es wie /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
macht df
nicht zuverlässig. Die einzige zuverlässige Option ist bisher die Verwendung einer stat
Lösung auf Basis.
df
des Geräts ist die Übereinstimmung zwischen den beiden Aufrufen konsistent, sodass ein Vergleich in Ordnung ist.
df
Bericht /dev/sda6
und /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.
mount /dev/sda6 /mnt1
gefolgt von mount /dev/sda6 /mnt2
Arbeiten wie ein Zauber. cat /proc/mounts
ist gut damit. Jedoch ist es , da nur Wheezy , die /dev/disk/by-uuid/ca09b...
in gezeigt wird , df
wie 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/sda6
in df
(Ich weiß nicht, wie ich reproduzieren soll, was es während des Startvorgangs getan hat, aber das ist hier nicht das Problem).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Funktioniert mit einer beliebigen Anzahl von Pfaden.
df
ist nicht immer eine gute Idee .
$6
), nicht den Gerätenamen ( $1
), also sollte das kein Problem sein.
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.