Перевірте, чи 2 каталоги розміщені в одному розділі в Linux


9

Як я можу перевірити, чи /my/dirє на тому ж розділі, що і /?

Це для інтеграції в сценарій. Кріплення кріплення слід поводитись правильно. Рішення, сумісні з POSIX, вітаються.


"Зв'язаними кріпленнями слід керуватися правильно." Але що ви вважаєте правильним? Ваше запитання можна трактувати будь-яким способом.
Жиль "ТАК - перестань бути злим"

@Gilles У первісному заголовку я написав "розміщений" замість "встановлений", хтось редагував додаючи плутанину IMHO. І все ж у моєму питанні зрозуміло: "на одному і тому ж розділі", тобто на одному фізичному розділі, незалежно від шляху чи точки монтажу, що використовувався для доступу до двох файлів / каталогів.
Тотор

Відповіді:


6

Ви можете перевірити це за допомогою stat:

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

Показує номер пристрою та місце монтажу вашого каталогу.


1
Добре, але команда statоболонки не POSIX ...
Totor

Ні? Звідки ти знаєш?


Ой, моя погана. Але наступного разу покажіть це посилання заздалегідь.

5

Наступна команда дає унікальне ім'я для точки монтування, що містить файл $file:

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

Це працює в будь-якій системі POSIX . -PВаріант передбачає передбачуваний формат; перше поле другого рядка - "ім'я файлової системи". Таким чином, для перевірки два файли знаходяться в одній точці монтажу:

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

Або зберегти пару викликів процесу:

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

Кілька операційних систем можуть мати пробіли в назвах томів. У dfцьому випадку немає повністю надійного способу розбору результатів.

Під капотом ви можете ідентифікувати файлову систему, що містить файл, по st_devповерненому полі stat. Немає портативного способу зробити це із скрипту оболонки. Деякі системи мають statутиліту, але її синтаксис змінюється:

  • У невбудованих Linux, Cygwin або інших системах з GNU coreutils statповідомляє st_devполе, коли викликається як stat -c %D -- "$file".
  • Деякі установки BusyBox включають statсумісний з основними програмами GNU. Інші - statбез %cвибору; Ви можете використовувати, stat -t -- "$file" | awk '{print $8}'але це працює лише в тому випадку, якщо ім'я файлу не містить пробілів, або stat -t -- "$file" | awk 'END {print $(NF-8)}'яке справляється з довільними іменами файлів, але не з майбутніми доповненнями полів до statвиводу.
  • Системи BSD мають іншу statкорисність, яка вимагає stat -f %d -- "$file".
  • Solaris, AIX та інші не мають statкорисності.

Якщо Perl доступний, ви можете використовувати

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

і зробити порівняння:

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

Зауважте, що є деякі кутові випадки, коли бажаний результат не зрозумілий. Наприклад, з прив'язкою кріплень Linux після mount --bind /foo /bar, /fooі /barвважаються тією ж файловою системою. Завжди можливо, що два файли фактично розташовані на одному пристрої, але ви ніколи не дізнаєтесь: наприклад, якщо файли знаходяться на двох різних мережевих кріпленнях, клієнт не може знати, чи сервер експортує різні файлові системи.

Якщо файли - це каталоги, і ви можете писати в них, інший спосіб - це створити тимчасовий файл і спробувати зробити жорстке посилання. Цей звіт повідомляє про негативний результат у всіх кріпленнях Linux.

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не завжди дає ім’я пристрою, але колись це посилання на нього, як /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4зробити dfне надійним. Єдиним надійним варіантом поки що є використання statбазованого рішення.
Тотор

@Totor Це не має значення: незалежно від того, яке ім’я dfповідомляється для пристрою, воно відповідає двом викликам, тому для порівняння це нормально.
Жил "ТАК - перестань бути злим"

Ні, це не працює, я перевірив це. На Debian Wheezy тут представлено одиночний dfзвіт /dev/sda6і /dev/disk/by-uuid/ca09b...обидва посилання на один і той же пристрій, але різні точки монтажу. Тест порівняння рядків, очевидно, не вдається при спробі з файлами з кожної точки монтажу.
Тотор

@Totor Зазвичай ви не можете встановити один і той же блок пристроїв двічі. Як я вказую у своїй відповіді, є кутові випадки, такі як кріплення кріплення, які можуть бути або не можуть бути повідомлені як окремі.
Жил "ТАК - перестань бути злим"

Але це прекрасно працює на Debian Squeeze та Wheezy: mount /dev/sda6 /mnt1слідом за mount /dev/sda6 /mnt2роботами, як зачарування. cat /proc/mountsдобре з цим. Однак це лише з Wheezy, що /dev/disk/by-uuid/ca09b...показано в dfякості пристрою для кореневої файлової системи. Подальші спроби встановити його за допомогою цього simlink або UUID=ca09b...синтаксису mount не закінчуються показанням нічого іншого, ніж /dev/sda6у df(я не знаю, як відтворити те, що було зроблено під час завантажувального процесу, але це тут не викликає занепокоєння).
Тотор

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

Працює з будь-якою кількістю шляхів.


Синтаксичний висновок dfє не завжди хорошою ідеєю .
Джозеф Р.

1
@Totor Я перевіряю точку монтажу ( $6), а не назву пристрою ( $1), так що це не повинно бути проблемою.
n.st

1
@JosephR Це найкраще в POSIX. n.st: чому б не перевірити перше поле? Не має значення, який шлях використовувався для доступу до пристрою, якщо це одна і та сама точка монтування, то вихід буде узгоджений.
Жил "ТАК - перестань бути злим"

Це не працює із прив'язними кріпленнями.
Тотор

0

Найкраще безпроблемне рішення, доступне в POSIX, - це порівняння ідентифікаторів пристрою файлів, наданих функцією stat (2) .

Perl має аналогічну функцію стат , як Жиль зазначив :

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

але "спосіб POSIX" полягає у використанні програми на зразок C:

./checksamedev file1 file2

який вихідний код такий:

#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;
}

Якщо ідентифікатори обох файлів рівні, вони розміщуються в одній файловій системі, і в цьому випадку команди вище повертають 0 (інше значення - інакше). Перевірте echo $?.

Це добре працює з прив'язними кріпленнями, але, ймовірно, не буде з мережевими кріпленнями.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.