Введение:
Философия 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' "
Получите циклическую, постоянную перезагрузку системы с последующим лечением только через режим "востановление системы" или удалением правила путём подключения жёсткого диска к другу ПК.
Данную проблему я всё же попробую решить и если получится, то обязательно поделюсь. Надеюсь данная статейка была Вам полезна.