Визначте, на якому пристрої знаходиться каталог


49

Якщо я це роблю

# cd /
# ln -s /home test
# cd test
# mount --bind $PWD /mnt

вхід в /proc/mountsце

/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0

що є пристроєм, на який встановлений /homeі який легко вивести з $PWDякого /test. Як я можу визначити, який пристрій (тобто / dev / sda2) взагалі відображатиметься, /proc/mountsвраховуючи, що кріплення прив’язки може бути до каталогу / файлу, який потенційно "затушований" символьними посиланнями, іншими кріпленнями прив’язки тощо?

Відповіді:


49

Якщо я розумію ваше запитання, ви хочете знати, який пристрій використовувався для даного кріплення. Для цього можна використовувати dfкоманду:

$ df -h 
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/fedora_greeneggs-root   50G   21G   27G  44% /
devtmpfs                           3.8G     0  3.8G   0% /dev
tmpfs                              3.8G   14M  3.8G   1% /dev/shm
tmpfs                              3.8G  984K  3.8G   1% /run
tmpfs                              3.8G     0  3.8G   0% /sys/fs/cgroup
tmpfs                              3.8G  3.4M  3.8G   1% /tmp
/dev/sda1                          477M   99M  349M  23% /boot
/dev/mapper/fedora_greeneggs-home  402G  184G  198G  49% /home

Щоб знайти, на якому пристрої знаходиться певний файл / каталог, дайте файл як аргумент df. Використовуючи свій приклад:

$ df -h /mnt
Filesystem                         Size  Used Avail Use% Mounted on
/dev/sda1                          477M   99M  349M  23% /

Ви також можете скористатися mountкомандою:

$ mount | grep '^/dev'
/dev/mapper/fedora_greeneggs-root on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/sda1 on /boot type ext4 (rw,relatime,seclabel,data=ordered)
/dev/mapper/fedora_greeneggs-home on /home type ext4 (rw,relatime,seclabel,data=ordered)

Каталог, встановлений для кожного пристрою, є третім аргументом у вихідному тексті. Так для пристрою /dev/sda1було б /boot. Інші пристрої використовують LVM (Logical Volume Management) і їх потрібно буде додатково запитувати, щоб знати, який саме пристрій використовується LVM.


Якщо $PWD(це те, що я монтую) похований у серії символьних посилань, прив’язування кріплень тощо, тоді мені потрібно буде рекурсивно вивчити шлях на точки монтажу.
StrongBad

Незважаючи на те, що прив'язує кріплення, незважаючи на те, що відображається в /proc/mounts"річ", яка монтується, принаймні, на мій погляд, це не пристрій, це каталог / файл.
StrongBad

@StrongBad - що readlink -f /mntпоказує?
slm

2
@StrongBad Якщо вам доведеться мати справу з визначенням точки монтажу / пристрою, коли затемнюються символьними посиланнями, ви повинні поставити це у своєму питанні. Це набагато полегшить отримання правильної відповіді.
Патрік

readlink -f /mntдає/mnt
StrongBad

29

У Linux ми findmntз util-linuxточно зробили для цього

findmnt -n -o SOURCE --target /path/to/FILE

Перевага інших рішень полягає в тому, що воно все ще працює, якщо шляхи затемнюються символьними посиланнями або дублюючими прив'язуючими кріпленнями.


Це не працює для мене. Він показує джерело кожного кріплення в системі. findmnt від util-linux 2.23.2
bwduncan

@bwduncan для мене працює з 2.23.2. Може, помилка? Чи можете ви спробувати останню версію 2.29.2?
rudimeier

2,29 на Ubuntu робить свою справу. Не помилка як така, більше функція :)
bwduncan

1
Дякую! Саме це мені і було потрібно для системного сценарію.
вог

11

Найбільш точний мені відомий метод - це використовувати вихід системного виклику lstat (). Зокрема, поле st_dev. Існує утиліта командного рядка stat (1), за допомогою якої можна переглянути цю інформацію. Наприклад, вихід "stat / etc / issue" на моєму ноутбуці:

File: ‘/etc/issue’
  Size: 65          Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1610916043  Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

Помітьте третій рядок, перше поле, "Пристрій". Тут перелічено 801 год. Це значення можна розділити на два байти, 8 і 1. Перший байт відомий як основне число, другий байт - другорядне число. Отже, наступний крок - з’ясувати, який пристрій є основним 8, другорядним - 1.

Я вважаю, що консалтинг / proc / розділи є найшвидшим. У моєму випадку / proc / розділи містить вміст:

major minor  #blocks  name

   8       16  234431064 sdb
   8       17   33554432 sdb1
   8       18  200875608 sdb2
   8        0  500107608 sda
   8        1  500106584 sda1

З цього результату досить зрозуміло, що основний 8, мінор 1 - sda1. Ми можемо підтвердити це за допомогою ls -l / dev / sda1

brw-rw---- 1 root disk 8, 1 May  8 05:33 /dev/sda1

Помітьте 8, 1 перед позначкою дати.

Важливо розуміти / пам’ятати, що ім’я такого пристрою, як / dev / sda1, є лише міткою. Основні та незначні числа - це значущі, важливі значення файлу пристрою. Якщо вам цікаво, перегляньте утиліту mknod (1), яка використовується для створення файлів пристроїв. Я можу створити новий / dev запис під назвою aardvark з основним 8, другорядним 18 із таким синтаксисом:

mknod /dev/aardvark b 8 18

Тоді я міг би легко встановити його:

mount /dev/aardvark /mnt

і, якщо ми подивимось на результат команди mount або вміст / proc / mounts і побачимо:

/dev/aardvark on /mnt type xfs (rw,relatime,attr2,inode64,noquota)

df -h показує:

/dev/aardvark   192G  154G   38G  81% /mnt

... У будь-якому разі, суть у всьому цьому полягає в тому, щоб проілюструвати, що важливими деталями для ідентифікації блокового пристрою є основні та незначні номери - не ярлик файлу пристрою - і що найкращим способом використання системного виклику lstat () є запитувати ці значення.

Як останній коментар, я просто перечитав ваше запитання, щоб переконатися, що я відповів на нього, і зрозумів, що ви запитуєте, яка мітка пристрою-джерела відображатиметься в / proc / mounts для прив’язки. Це була би та сама мітка пристрою джерела, що була використана в початковому виклику кріплення (2) для джерела точки кріплення файлової системи для прив'язки. Можливо, приклад допоможе:

У мене є / dev / sdb2 та / dev / aardvark (те саме, що вище). Вони обидва основні 8, другорядні 18. Зверніть увагу, я буду монтувати одну і ту ж файлову систему двічі. Я роблю наступне:

mkdir /mnt1 /mnt2 /foo

mount /dev/aardvark /mnt1
mount /dev/sdb2 /mnt2

Зауважте, що я роблю каталог somedir в / mnt1. Але оскільки / mnt1 та / mnt2 мають однакову файлову систему, встановлений, somedir також буде доступний через / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

mount -o bind /mnt1/somedir /foo/left
mount -o bind /mnt2/somedir /foo/right

Тепер, якщо ми перевіряємо / proc / mounts, ми бачимо:

/dev/aardvark /mnt1 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /mnt2 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/aardvark /foo/left xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /foo/right xfs rw,relatime,attr2,inode64,noquota 0 0

Мітка пристрою-джерела на кріпленнях / foo / ... є такою ж, як і значення, спочатку надане у виклику кріплення (2) файлової системи. Пам'ятайте, / dev / aardvark та / dev / sdb2 у моєму прикладі - це той самий пристрій.

Я усвідомлюю, що щойно я набрав роман, і перша половина насправді взагалі не відповідає на ваше запитання, але видалити його видалося такою марною. Можливо, це допоможе комусь іншому.

Щасти.

PS Майте на увазі, що деякі файлові системи базуються на мережах - наприклад, NFS або CIFS - або є віртуальними, як PROFS або sysfs і не мають пристрою джерельного блоку. Я не знаю, що буде повернуто як пристрій у статистичному виході, тільки для того, що воно коштує.


1
Перша частина, безумовно, допомагає мені зрозуміти останню частину.
StrongBad

Ця відповідь не працює для tmpfs шляхів. Ви не знайдете мінор st_dev, майор на / proc / розділах.
мбелло

@mbello Як я вже згадував наприкінці своєї відповіді, цей метод не працює і не може працювати для файлових систем, які не мають резервного пристрою - як, наприклад, монтажі tmpfs.
etherfish

2

З огляду на такі типові точки кріплення:

$ df --output=target
Mounted on
/
/dev
/run
/sys/fs/cgroup
/run/lock
/run/shm
/run/user

stat --format %m <path> буде надрукувати лише точку монтування круглим способом (хоча вам потрібно перевірити код виходу, щоб однозначно виявити помилку дозволу; тут виграють підходи кріплення таблиці):

$ stat --format %m /
/
$ stat --format %m /tmp
/
$ stat --format %m /proc
/proc
$ stat --format %m /run
/run
$ stat --format %m /run/mount
/run
$ stat --format %m /run/user
/run/user
$ stat --format %m /run/user/1000/dconf
/run/user
$ stat --format %m /run/user/1000/gvfs
/run/user/1000/gvfs

Символьні посилання, як завжди, обережно:

$ ls -lh ~/.gvfs
/home/cwillu/.gvfs -> /run/user/1000/gvfs
$ stat --format %m ~/.gvfs
/run/user/1000/gvfs
$ stat --format %m ~/.gvfs
/

І звичайно пам'ятайте, щоб використовувати цитати при написанні сценаріїв. Розглянемо шлях для точки з пробілами та таким чином:

$ mkdir /tmp/Something\ Like\ This\!
$ sudo mount none /tmp/Something\ Like\ This\! -t tmpfs
$ stat --format %m /tmp/Something\ Like\ This\!
/tmp/Something Like This!
$ touch /tmp/Something\ Like\ This\!/pretend-I\'m-big
$ ls /tmp/Something\ Like\ This\!
pretend-I'm-big

Наскільки великим є це ви?

$ du $(stat --format %m /tmp/Something\ Like\ This\!/)
du: cannot access /tmp/Something: No such file or directory
du: cannot access Like: No such file or directory
du: cannot access This!: No such file or directory

$ du "$(stat --format %m /tmp/Something\ Like\ This\!/)"
0   /tmp/Something Like This!

Завершення вкладки мого дистрибутива навіть не відповідає цьому, тому ми просто підкреслимо цей приклад місця кріплення з поверненнями каретки та каналами ліній та пробілами:

$ stat --format %m /tmp/Something*
/tmp/Something   
Like   This!

$ a="$(stat --format %m /tmp/Something*)"
    # the above assignment is actually the one place you don't need quotes, 
    # but `export a=...` or similar _would_ need them, so we'll just put them in;
    # they don't change the behaviour in this form of assignment.

$ stat "$a"
  File: ‘/tmp/Something   \r\n\rLike   This!’
  Size: 40          Blocks: 0          IO Block: 4096   directory
Device: 7bh/123d    Inode: 1279171     Links: 2
Access: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-09-30 11:43:17.933467344 -0600
Modify: 2016-09-30 11:43:17.933467344 -0600
Change: 2016-09-30 11:43:17.933467344 -0600
 Birth: -

1
Розмітка <kbd> використовується для одного ключа, а не для цілої команди. На мою скромну думку це виглядає не так краще.
Томаш
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.