Как получить имя блочного устройства из имени устройства раздела?

13

Я ищу портативный способ получить имя устройства родительского блока (например /dev/sda), учитывая имя устройства раздела (например /dev/sda1). Я знаю, что могу просто выбросить последний символ, но в некоторых случаях это не сработает:

  • Кард-ридеры MMC обычно имеют имена вроде /dev/mmcblk0, в то время как их разделы имеют имена как /dev/mmcblk0p1(обратите внимание на дополнительные p).
  • необязательно: некоторые блочные устройства вообще не имеют таблицы разделов и отформатированы как один раздел. В этом случае устройство разделения и родительское блочное устройство совпадают.

Объемы LVM - это совершенно другой котелок с рыбой. Мне не нужно сейчас их поддерживать, но если их учет требует небольших дополнительных усилий, я бы не возражал.

Дмитрий Григорьев
источник
Как портативный? На моем ноутбуке есть корневой раздел, /dev/sd0aно нет /dev/sd0устройства (есть /dev/sd0c...)
thrig
@don_crissti, /dev/sda1и /dev/mmcblk0p1, в любом случае , зависят от Linux. lsblkхотя относительно недавно.
Стефан Шазелас
lsblkтакже использует номера узлов устройства, чтобы найти правильный, вместо того, чтобы просто использовать имя. кажется, самое простое решение для Linux и util-linux, вероятно, всегда будет доступно в любом случае.
ilkkachu
1
@don_crissti lsblk -dpno pkname $devnameпрошел все мои тесты! Возможно, вам следует добавить ответ.
Дмитрий Григорьев
@ thrig Ну да, я определенно ожидаю, что сценарий вернется /dev/sd0cв этом случае. Подходят ли ответы ниже для вас?
Дмитрий Григорьев

Ответы:

15

Если вы используете Linux, вы можете использовать lsblk(который является частью util-linux):

lsblk -no pkname /dev/sda1
don_crissti
источник
2
Мой lsblk( util-linux: 2.20.1, Ubuntu 14.04) не имеет pknameстолбца, просто kname.
Heemayl
3
@heemayl - он был добавлен только четыре года назад, поэтому недоступен на дистрибутивах, использующих более старые версии ...
don_crissti
$ lsblk -no pkname /dev/nvme0n1p3возвращает 7 строк в моей системе. Да, этот раздел зашифрован и содержит LVM, это не тривиальная ситуация. Я не знаю, как вы должны надежно выбрать правильную строку из сценария.
elboulangero
16

Если устройство является разделом другого устройства, он /sys/class/block/$devбудет содержать файл с именем partition(содержимое которого является номером раздела).

Если это так, вы можете получить имя родительского устройства с помощью:

basename "$(readlink -f "/sys/class/block/$dev/..")"

Или с zsh:

echo /sys/class/block/$dev(:A:h:t)

Пример:

$ dev=sda1
$ basename "$(readlink -f "/sys/class/block/$dev/..")"
sda
$ dev=nbd0p1
$ basename "$(readlink -f "/sys/class/block/$dev/..")"
nbd0

Объемы LVM совершенно разные, они не являются разделами, за исключением особого случая, когда они являются одним непрерывным linearотображением физического PV.

Если вы в таком случае, вы можете получить название этого PV с помощью:

ls "/sys/class/block/$dev/slaves"

Где $devчто-то вроде dm-2(что вы можете получить от "$(basename "$(readlink -f /dev/VG/LV)")").

Стефан Шазелас
источник
Я принял ответ don_crissti, потому что у меня получился lsblkкороткий синтаксис, но я признаю, что ваш ответ более общий и переносимый. Благодарность!
Дмитрий Григорьев