Найти тему

Udev, правила rules и какие ошибки возможно допустить при написании правил.

Оглавление

Введение:

Философия Unix гласит что все есть файл. Таким образом, файлы в Unix это не только информация хранимая на жестком диске, но и устройства. Да, в Linux жесткий диск, мышь, клавиатура, флешка, сетевой адаптер и другие устройства имеют свои файлы с помощью которых с ними и взаимодействуют различные системные программы.

Все файлы устройств хранятся в каталоге /dev. Этот каталог генерируется во время загрузки специальным сервисом - udev, на основе подключенных к компьютеру устройств и определенных правил. По умолчанию в udev уже заложены все необходимые для нормальной работы устройств правила. Но некоторые пользователи хотят иметь возможность самим настраивать устройства и выбирать им имена и права доступа. Кроме того, понимание процесса генерации файлов устройств, дает возможность глубже понять работу операционной системы.

Правила udev могут:

  • Переименовать устройство, например, жесткий диск или сетевую карту;
  • Создать дополнительное имя для устройства;
  • Поменять права доступа к устройству;
  • Установить владельца и группу;
  • Выполнить скрипт при подключении или отключении устройства.

Основная информация:

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

touch /etc/udev/rules.d/10-local.rules

Правило Udev состоит из нескольких пар "ключ - значение" разделенных запятой. Одни ключи используются для проверки соответствия устройства определенному правилу, в таких ключах используется знак == для разделения пары, например: SUBSYSTEM=="block" - т е правило будет применено только если значения ключа SUBSYSTEM для этого устройства равно block. Другие ключи используются для указания действия если все условия соответствия выполняются. Для разделения пар в таких ключах используется знак равно "=", Например, NAME="mydisk". Ну и полностью правило:

SUBSYSTEM=="block", ATTR(size)=="1343153213", NAME="mydisk"

Это правило выполниться только для устройства подсистемы block и с размером 1343153213 байт. Откуда брать эти значения мы рассмотрим ниже, а пока разберемся что же значат те или иные ключи. Сначала ключи соответствия:

  • SUBSYSTEM - подсистема устройства;
  • KERNEL - имя выдаваемое устройству ядром;
  • DRIVER - драйвер обслуживающий устройство;
  • ATTR - sysfs атрибут устройства;
  • SUBSYSTEMS - подсистема родительского устройства;

Устройство может иметь родительские устройства, например жесткий диск имеет родительское устройство SSCI, которое в свою очередь имеет родительское устройство шину BUS. Иногда необходимо получить информацию из родительского устройства, для этого используются ключи SUBSYSTEMS, KERNELS, DRIVERS, ATTRS соответственно.

Для действий используются ключи:

  • NAME - установить имя файла устройства
  • SYMLINK - альтернативное имя устройства
  • RUN - выполнить скрипт при подключении устройства
  • GROUP - группа у которой есть доступ к файлу
  • OWNER - владелец файла устройства
  • MODE - маска прав доступа

Рассмотрим подробнее ключ ATTR. Он позволяет получить информацию об устройстве, доступную в sysfs. Например, ATTR{size}=13413423124 если размер устройства равен 13413423124. Посмотреть все возможные sysfs параметры для устройства можно непосредственно в файловой системе /sys. Например, для диска /dev/sda есть каталог /sys/block/sda/ в котором можно найти файлы size, stat, ro, range и т д. Также посмотреть все возможные Udev параметры для устройства можно с помощью утилиты udevadm. Например, для диска /dev/sda:

udevadm info -a -n sda1

looking at device '/devices/pci0000:00/0000:00:11.0/ata1/host0/target0:0:0/0:0:0:0/block/sda':

KERNEL=="sda"

SUBSYSTEM=="block"

DRIVER==""

ATTR{ro}=="0"

ATTR{size}=="976773168"

ATTR{stat}==" 205 0 3408 339 0 0 0 0 0 234 339"

ATTR{range}=="16"

ATTR{discard_alignment}=="0"

ATTR{events}==""

ATTR{ext_range}=="256"

ATTR{events_poll_msecs}=="-1"

ATTR{alignment_offset}=="0"

ATTR{inflight}==" 0 0"

ATTR{removable}=="0"

ATTR{capability}=="50"

ATTR{events_async}==""

...

Опция -n задает имя устройства, -p путь в sysfs. Например, то же самое получим если выполнить:

udevadm info -a -p /sys/block/sda/sda1

Как переименовать устройство в Linux:

Теперь на основе полученной из udevadm информации можем составить udev rules для добавления альтернативного имени диска:

nano /etc/udev/rules.d/10-local.rules

SUBSYSTEM=="block", ATTR{size}=="976773168", SYMLINK+="root"

Или смены названия:

SUBSYSTEM=="block", ATTR{size}=="976773168", name="root"

Получим устройство /dev/root, которое будет указывать на корневой раздел (sda1), то же самое можно сделать для привода оптических дисков:

udevadm info -a -p /sys/block/sr0

...

ATTRS{model}=="DVDRAM GH22NS70 "

...

SUBSYSTEM=="block", ATTRS{model}=="DVDRAM GH22NS70 ", SYMLINK+="cdrom"

После перезагрузки появиться файл устройства /dev/cdrom. Хотя, конечно, это можно сделать без udev, прописав в автозагрузку команду создания символической ссылки:

ln -s /dev/sr0 /dev/cdrom

Как переименовать сетевую карту:

Настройка udev linux на этом не заканчивается. Сетевая карта, тоже устройство и тоже управляется udev. Файлы сетевых устройств хранятся в /sys/class/net. Поэтому получаем информацию о ней с помощью udevadm:

udevadm info -a -p /sys/class/net/enp2s0

И создаем правило например на основе mac адреса:

SUBSYSTEM=="net", ATTR{address}=="bc:ae:c5:be:8b:b7", NAME="eth0"

Перезагружаем компьютер и теперь устройство называется eth0.

Как запустить скрипт при подключении устройства:

Например, мы хотим автоматически скопировать все данные с флешки при ее подключении к компьютеру. Мы знаем что флешка будет называться /dev/sdb, тогда можно создать правило udev такого вида:

KERNEL=="sdb", RUN+="/usr/bin/my_script"

При подключении флешки выполниться скрипт /usr/bin/my_script, и сделает необходимые действия. Нужно заметить что скрипт не должен выполняться слишком долго, так как udev остановиться и будет ожидать завершения его работы.

Отладка правил:

Если вы не уверенны правильно ли составлено правило можно воспользоваться командой udevadm test для проверки. В единственном параметре нужно передать путь sysfs устройства. Например проверим наше правило для жесткого диска:

 $ udevadm test /sys/block/sda

Среди многочисленного вывода видим строчку:

creating link '/dev/root' to '/dev/sda'

Значит все работает, настройка udev выполнена успешно.

Если же в правиле допустить синтаксическую ошибку, например, UBSYSTEM вместо SUBSYSTEM, udevadm test выдаст что то подобное:

read rules file: /etc/udev/rules.d/10-local.rules

unknown key 'UBSYSTEM' in /etc/udev/rules.d/10-local.rules:2

invalid rule '/etc/udev/rules.d/10-local.rules:2'

Здесь мы видим саму причину ошибки, неверный ключ, а также файл и строку в которой допущена ошибка.

Вывод:

С блочными и сетевыми устройствами данная система работает без отказно, но стоит нам попробовать применить данные примеры к клавиатуре и мышке, то начинается веселье. И так, используя правила, для данных устройств мы можем:

  • Разрешить
  • Запретить
  • Выполнить действие ( запустить скрипт или команду)

Но единственное условие это работает на конкретно прописанное устройство.

Если же мы делаем правило запрета всех устройств кроме тех, которые описаны в правиле, то получаем рабочее правило ровно до того момента, пока не будет подключено не описанное устройство. Например мы указали атрибуты со знаком отрицания " != " и в конце строки добавили " ATTR{autorezet}=0, то система должна читать его так:

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

Но на практике, система блокирует полностью всю шину usb и больше не подключает ни какое устройство ( приходилось править правило через rdp и перезагружать систему). И не дай вам бог вместо параметра:

ATTR{autorezet}=0

Добавить действие например:

RUN+="/bin/sh -c 'sudo reboot' "

Получите циклическую, постоянную перезагрузку системы с последующим лечением только через режим "востановление системы" или удалением правила путём подключения жёсткого диска к другу ПК.

Данную проблему я всё же попробую решить и если получится, то обязательно поделюсь. Надеюсь данная статейка была Вам полезна.