Поиск только дисков с помощью pyudev

Я ищу перечислить все жесткие диски на компьютере, используя udev и, в частности, pyudev для перечисления всего:

import pyudev

context = pyudev.Context()

for device in context.list_devices(subsystem='block', DEVTYPE='disk'):
    print "{}, ({})".format(device.device_node, device.device_type)

Это распечатывает следующее:

/dev/sdb (disk)
/dev/sdc (disk)
/dev/sda (disk)
/dev/sr0 (disk)
/dev/loop0 (disk)
/dev/loop1 (disk)
/dev/loop2 (disk)
/dev/loop3 (disk)
/dev/loop4 (disk)
/dev/loop5 (disk)
/dev/loop6 (disk)
/dev/loop7 (disk)
/dev/ram0 (disk)
/dev/ram1 (disk)
/dev/ram10 (disk)
/dev/ram11 (disk)
/dev/ram12 (disk)
/dev/ram13 (disk)
/dev/ram14 (disk)
/dev/ram15 (disk)
/dev/ram2 (disk)
/dev/ram3 (disk)
/dev/ram4 (disk)
/dev/ram5 (disk)
/dev/ram6 (disk)
/dev/ram7 (disk)
/dev/ram8 (disk)
/dev/ram9 (disk)

Поскольку я в основном занимаюсь реальными приводами, а не оптическими дисками, шлейфовыми или оперативными устройствами, как я могу отфильтровать результаты, чтобы получить только реальные физические носители?

2 ответа

Решение

Поскольку udev работает только на ядре Linux (по крайней мере, на данный момент), вы можете отфильтровать MAJOR number 8 который представляет все устройства на основе драйвера диска SCSI/SATA.

for device in context.list_devices(MAJOR='8'):
    if (device.device_type == 'disk'):
        print "{}, ({})".format(device.device_node, device.device_type)

На моей системе ваш код выводит следующее:

/dev/sda, (disk)
/dev/sdf, (disk)
/dev/sdb, (disk)
/dev/sdc, (disk)
/dev/sdd, (disk)
/dev/sde, (disk)
/dev/sr0, (disk)
/dev/loop0, (disk)
/dev/loop1, (disk)
/dev/loop2, (disk)
/dev/loop3, (disk)
/dev/loop4, (disk)
/dev/loop5, (disk)
/dev/loop6, (disk)
/dev/loop7, (disk)

После фильтрации по мажорному номеру 8 я вижу следующий вывод:

/dev/sda, (disk)
/dev/sdf, (disk)
/dev/sdb, (disk)
/dev/sdc, (disk)
/dev/sdd, (disk)
/dev/sde, (disk)

Обратите внимание, что вы также получите в списке жесткие диски USB и USB-накопители, поскольку они также используют один и тот же драйвер диска SCSI.

Я не совсем уверен, отображаются ли жесткие диски IDE как sdX или же hdX с последними ядрами 2.6 или 3.x У меня нет жесткого диска IDE для проверки, и я давно его уже имел.: D

ОБНОВЛЕНИЕ: те же номера страниц списка устройств /dev/hdX быть тем, который используется жесткими дисками IDE (а также могут быть диски IDE?). Если вы хотите отфильтровать их, я думаю, вы могли бы сделать что-то вроде этого:

for device in context.list_devices(DEVTYPE='disk'):
    major = device['MAJOR']
    if major == '8' or major == '3':
        print "{}, ({})".format(device.device_node, device.device_type)

Поскольку управление устройством в udev очень гибкое, оно может зависеть от правил udev, установленных в /lib/udev/rules.d или же /etc/udev/rules.d которые определяют, по каким ключам вы можете фильтровать.

Ты можешь использовать udevadm получить список устройств и связанных с ними ключей udev.

sudo udevadm info --export-db

Точно так же ваш скрипт может быть изменен для вывода этой информации следующим образом:

#!/usr/bin/env python
import pyudev

context = pyudev.Context()

for device in context.list_devices(subsystem='block', DEVTYPE='disk'):
    for key, value in device.iteritems():
        print '{key}={value}'.format(key=key, value=value)
    print

Это позволит вам определить, какие ключи доступны для фильтрации. В моей системе Debian некоторые записи выглядят так:

# Loop device
UDEV_LOG=3
DEVPATH=/devices/virtual/block/loop0
MAJOR=7
MINOR=0
DEVNAME=/dev/loop0
DEVTYPE=disk
SUBSYSTEM=block
UDISKS_PRESENTATION_NOPOLICY=1
DEVLINKS=/dev/block/7:0

#cdrom
UDEV_LOG=3
DEVPATH=/devices/pci0000:00/0000:00:01.1/host1/target1:0:0/1:0:0:0/block/sr0
MAJOR=11
MINOR=0
DEVNAME=/dev/sr0
DEVTYPE=disk
SUBSYSTEM=block
ID_CDROM=1
ID_CDROM_DVD=1
ID_CDROM_MRW=1
ID_CDROM_MRW_W=1
ID_SCSI=1
ID_VENDOR=VBOX
ID_VENDOR_ENC=VBOX\x20\x20\x20\x20
ID_MODEL=CD-ROM
ID_MODEL_ENC=CD-ROM\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
ID_REVISION=1.0
ID_TYPE=cd
ID_BUS=scsi
ID_PATH=pci-0000:00:01.1-scsi-1:0:0:0
GENERATED=1
UDISKS_PRESENTATION_NOPOLICY=0
DEVLINKS=/dev/block/11:0 /dev/scd0 /dev/disk/by-path/pci-0000:00:01.1-scsi-1:0:0:0 /dev/cdrom /dev/dvd
TAGS=:udev-acl:

# hard disk
UDEV_LOG=3
DEVPATH=/devices/pci0000:00/0000:00:0d.0/host2/target2:0:0/2:0:0:0/block/sda
MAJOR=8
MINOR=0
DEVNAME=/dev/sda
DEVTYPE=disk
SUBSYSTEM=block
ID_ATA=1
ID_TYPE=disk
ID_BUS=ata

Было бы возможно отфильтровать по этим парам ключ / значение, чтобы вернуть только те диски, которые являются реальными. UDISKS_PRESENTATION_NOPOLICY Например, запись может быть использована для фильтрации петлевых устройств. Вы можете просмотреть правила udev, чтобы определить, как он пытается различить реальные / виртуальные диски.

Примерно так будет отфильтровываться диски и устройства петли:

devices = []
for device in context.list_devices(subsystem='block', DEVTYPE='disk'):
    # Filter out cd drives, loop devices.
    if device.get('ID_TYPE', '') == 'cd':
        continue
    if device.get('UDISKS_PRESENTATION_NOPOLICY', '0') == '1':
        continue
    devices.append(device)

print "HARD DISKS:"
Другие вопросы по тегам