Jak mogę sprawdzić, czy /my/dir
jest na tej samej partycji co /
?
Ma to na celu integrację ze skryptem. Mocowania do wiązania powinny być obsługiwane poprawnie. Rozwiązania zgodne z POSIX są mile widziane.
Jak mogę sprawdzić, czy /my/dir
jest na tej samej partycji co /
?
Ma to na celu integrację ze skryptem. Mocowania do wiązania powinny być obsługiwane poprawnie. Rozwiązania zgodne z POSIX są mile widziane.
Odpowiedzi:
Możesz to sprawdzić za pomocą statystyki:
$ stat -c '%d %m' /proc/sys/
3 /proc
Wyświetla numer urządzenia i miejsce zamontowania katalogu.
stat
polecenie powłoki nie jest POSIX ...
Następujące polecenie podaje unikalną nazwę punktu podłączenia zawierającego plik $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Działa to na każdym systemie POSIX . -P
Opcja nakłada przewidywalnego formatu; pierwsze pole drugiego wiersza to „nazwa systemu plików”. Tak więc, aby sprawdzić, czy dwa pliki znajdują się w tym samym punkcie montowania:
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
Lub, aby zapisać kilka wywołań procesów:
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
Kilka systemów operacyjnych może mieć spacje w nazwach woluminów. W df
tym przypadku nie ma całkowicie niezawodnego sposobu analizowania danych wyjściowych.
Pod maską możesz zidentyfikować system plików zawierający plik po st_dev
polu zwróconym przez stat
. Nie ma przenośnego sposobu na zrobienie tego ze skryptu powłoki. Niektóre systemy mają stat
narzędzie, ale jego składnia jest różna:
stat
zgłasza st_dev
pole po wywołaniu jako stat -c %D -- "$file"
.stat
które są kompatybilne z coreutils GNU. Inni mają stat
bez %c
opcji; możesz użyć, stat -t -- "$file" | awk '{print $8}'
ale działa to tylko wtedy, gdy nazwa pliku nie zawiera spacji lub stat -t -- "$file" | awk 'END {print $(NF-8)}'
która kopiuje z dowolnymi nazwami plików, ale nie z przyszłymi dodatkami pól do danych stat
wyjściowych.stat
narzędzie, które wymaga stat -f %d -- "$file"
.stat
narzędzia.Jeśli Perl jest dostępny, możesz użyć
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
i do porównania:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Należy pamiętać, że istnieją przypadki narożne, w których pożądany wynik nie jest jasny. Na przykład, z powiązań wierzchowców Linuksa, po mount --bind /foo /bar
, /foo
i /bar
są uważane za tym samym systemie plików. Zawsze jest możliwe, że oba pliki znajdują się na tym samym urządzeniu, ale nigdy się nie dowiesz: na przykład, jeśli pliki znajdują się na dwóch różnych podłączeniach sieciowych, klient nie ma możliwości sprawdzenia, czy serwer eksportuje różne systemy plików.
Jeśli pliki są katalogami i można do nich pisać, inną metodą jest utworzenie pliku tymczasowego i próba utworzenia twardego łącza. Ten raport podaje negatywny wynik w przypadku podłączeń do linuksa.
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
nie zawsze podać nazwę urządzenia, ale kiedyś się dowiązania do niego jakby /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
co df
nie są wiarygodne. Jedyną dotychczas niezawodną opcją jest zastosowanie stat
rozwiązania opartego na bazie .
df
urządzenia, jest ono spójne między dwoma wywołaniami, więc można je porównać.
df
raport /dev/sda6
i /dev/disk/by-uuid/ca09b...
oba odnoszą się do tego samego urządzenia, ale różne punkty montowania. Test porównania ciągów oczywiście kończy się niepowodzeniem podczas próby z plikami z każdego punktu montowania.
mount /dev/sda6 /mnt1
a następnie mount /dev/sda6 /mnt2
działa jak urok. cat /proc/mounts
jest z tym w porządku. Jednak dopiero od czasu, gdy Wheezy /dev/disk/by-uuid/ca09b...
jest pokazany df
jako urządzenie dla głównego systemu plików. Dalsze próby montowania go za pomocą tego linku prostego lub UUID=ca09b...
składni montowania nie kończą się pokazywaniem niczego innego niż /dev/sda6
w df
(nie wiem, jak odtworzyć to, co zrobiono podczas procesu rozruchu, ale nie o to tu chodzi).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Działa z dowolną liczbą ścieżek.
df
to nie zawsze jest dobrym pomysłem .
$6
), a nie nazwę urządzenia ( $1
), więc nie powinno to stanowić problemu.
Najlepszym niezawodnym rozwiązaniem dostępnym w POSIX jest porównanie identyfikatorów urządzeń plików dostarczonych przez funkcję stat (2) .
Perl ma podobną funkcję statystyczną, jak zauważył Gilles :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
ale „sposobem POSIX” jest użycie programu C, takiego jak:
./checksamedev file1 file2
który kod źródłowy jest następujący:
#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;
}
Jeśli identyfikatory urządzeń obu plików są równe, są one hostowane w tym samym systemie plików, w którym to przypadku powyższe polecenia zwracają 0 (w przeciwnym razie inna wartość). Sprawdź za pomocą echo $?
.
Działa to dobrze z mocowaniami łączenia, ale prawdopodobnie nie będzie z mocowaniami sieciowymi.