Как определить, на каком разделе смонтирована файловая система в Linux, если в выводе раздел напрямую не указан df
?
Например, fdisk
вывод нашей системы:
Device Boot Start End Blocks Id System
/dev/sda1 * 1 2550 20478976 83 Linux
/dev/sda2 2550 60736 467378176 83 Linux
/dev/sda3 60736 60801 523264 82 Linux swap / Solaris
И вывод df
:
Filesystem Size Used Avail Use% Mounted on
rootfs 20G 881M 18G 5% /
/dev/root 20G 881M 18G 5% /
devtmpfs 989M 216K 989M 1% /dev
/dev/sda2 443G 199M 420G 1% /home
tmpfs 990M 0 990M 0% /dev/shm
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/named
/dev/root 20G 881M 18G 5% /var/named/chroot/var/named
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/named.conf
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/named.rfc1912.zones
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/rndc.key
/dev/root 20G 881M 18G 5% /var/named/chroot/usr/lib64/bind
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/named.iscdlv.key
/dev/root 20G 881M 18G 5% /var/named/chroot/etc/named.root.key
Из этого списка единственным очевидным разделом является /dev/sda2
; для остальных мы не можем видеть, на каком разделе они находятся (мы хотим сделать это с помощью скрипта bash).
Например, мы знаем, что /dev/root
смонтировано, /dev/sda1
поскольку они оба имеют одинаковый размер 20 ГБ, но как мы можем определить это с помощью скрипта?
Вывод из ls -l /dev/root /dev/sda1
:
[root@server etc]# ls -l /dev/root /dev/sda1
ls: cannot access /dev/root: No such file or directory
brw-rw---- 1 root disk 8, 1 May 7 14:16 /dev/sda1
решение1
Этот вывод вводит в заблуждение.
На самом деле у вас 2 разные файловые системы, смонтированные в /
.
rootfs
это файловая система, созданная initramfs. Когда загрузчик загружает ядро, он может загрузить initramfs, который распаковывается в файловую систему tmpfs. Эту файловую систему нельзя размонтировать. Когда initramfs завершает свою работу, он просто монтирует настоящую корневую файловую систему поверх нее.
Причина, по которой df
он отображается как 20 ГБ, заключается в том, что он не может добраться до этой файловой системы tmpfs. Когда df
он переходит к отображению файловых систем, он сначала получает список текущих монтирований из /etc/mtab
. Это дает ему 2 монтирования с использованием /
. Затем он делает statfs()
системный вызов на каждой точке монтирования. Но поскольку текущая корневая файловая система находится поверх tmpfs initramfs, он в конечном итоге дважды stats текущей корневой файловой системы.
Дополнительно /dev/root
на самом деле является символической ссылкой. Чтобы узнать, куда она на самом деле указывает, используя скрипт оболочки, можно использовать readlink -f /dev/root
.
Обновление: Хорошо, в этом случае readlink -f /dev/root
не работает, так как /dev/root
больше не существует. Потому что initramfs — это то, что смонтировало вашу настоящую корневую файловую систему, и /dev/root
там бы существовало. Но поскольку initramfs похоронен, /dev/root
больше не существует.
В этом случае все становится намного сложнее.
Что вы можете сделать, так это использовать stat
, чтобы получить номер устройства для точки монтирования, а затем выполнить поиск /dev
по нему.
Например, в моей системе это даст:
$ stat --format '%D' /
fd00
$ stat --format '%02t%02T' /dev/mapper/sys-root
fd00
$ for device in $(blkid -o device); do
> [ "$(stat --format '%04D' /)" = "$(stat --format '%02t%02T' "$device")" ] && \
> echo "$device" && \
> break
> done
/dev/mapper/sys-root
В основном это делает, использует stat
для получения старшего и младшего номера устройства /
. Затем мы перебираем все известные блочные устройства, ища одно с тем же старшим и младшим номером устройства. Это некрасиво, но по сути запись /dev
имеет другое имя, и поэтому нам нужно ее искать.
Это можно было бы сделать эффективнее, но я хотел сохранить простоту кода.
решение2
/dev/root — это символическая ссылка на реальное устройство. Вы должны иметь возможность получить местоположение с помощью ls /dev/root, realink или поиска root= в /proc/cmdline.