udev (Русский)
udev — работающая в пространстве пользователя система, с помощью которой системный администратор может создавать обработчики событий. События, получаемые udev, обычно генерируются ядром Linux в ответ на физические события, происходящие с периферийными устройствами. Например, при обнаружении периферийных устройств или "горячем" подключении udev может выполнить определённые действия, в том числе и вернуть управление ядру, если необходима загрузка модулей или прошивок.
Подобно предшественникам, утилитам devfsd и hotplug, udev управляет файлами устройств в каталоге /dev
, добавляя их, переименовывая и создавая символические ссылки. udev полностью замещает функционал hotplug и hwdetect.
Обработка событий в udev происходит параллельно, что теоретически улучшает производительность старых систем. С другой стороны, это может усложнить администрирование. Так, при перезапуске системы порядок загрузки модулей ядра может измениться, а при наличии в машине нескольких блочных устройств могут поменяться названия их файлов. Например, для системы с двумя жёсткими дисками файл /dev/sda
после перезагрузки может превратиться в /dev/sdb
.
Установка
udev входит в состав systemd и установлен по умолчанию. Подробнее см. systemd-udevd.service(8).
Существует также отдельный от systemd форк, который можно установить с пакетом eudevAUR или eudev-gitAUR.
О правилах udev
Создаваемые системным администратором правила udev хранятся в каталоге . Названия файлов правил должны заканчиваться суффиксом .rules. Правила из пакетов программ при установке помещаются в каталог . Если в каталогах и находятся два файла правил с одинаковыми именами, то файл в будет иметь приоритет.
Правила udev подробно описаны в руководстве udev(7). Также стоит изучить статью Создание правил udev (англ.) и приведённые в ней практические примеры: Создание правил udev - Примеры (англ.).
Пример правила udev
Ниже приведён пример правила, которое создаёт символическую ссылку /dev/video-cam
, когда к компьютеру подключается веб-камера.
Предположим, мы выяснили, что для подключённой камеры создан файл устройства . Причина, по которой мы создаем это правило, заключается в том, что при следующей загрузке веб-камере может быть присвоено другое имя, например, .
Мы используем параметры веб-камеры KERNEL=="video2"
и , затем мы возьмем идентификаторы производителя и изделия родительского USB-устройства , и для сопоставления:
В примере мы создали символическую ссылку, используя параметр SYMLINK+="video-cam"
. Мы можем также легко задать владельца (), группу (), или установить права доступа к файлу ссылки ().
Если вы намереваетесь создать правило, которое делает что-нибудь при удалении устройства, имейте в виду, что атрибуты устройства могут стать недоступны. В этом случае вам необходимо использовать специальный набор переменных окружения. Чтобы отобразить эти переменные, выполните следующую команду при отсоединении устройства:
$ udevadm monitor --environment --udev
В выводе команды вы увидите значения параметров устройства, например, ID_VENDOR_ID
и , которые соответствуют использованным ранее идентификаторам производителя и изделия. Правило, которое использует переменные окружения устройства, может выглядеть следующим образом:
Список атрибутов устройства
Чтобы вывести все атрибуты устройства, которые вы можете использовать в написании правил udev, выполните:
$ udevadm info --attribute-walk --name=имя_устройства
Замените текущим именем файла устройства, например, /dev/sda
или .
Если вы не знаете имя файла устройства, вы можете также вывести все атрибуты по конкретному системному пути:
$ udevadm info --attribute-walk --path=/sys/class/backlight/acpi_video0
Чтобы сузить поле поиска, определите класс устройства и выполните:
$ ls /dev/класс/by-id
Найденную символическую ссылку (или файл, на который она указывает) можно использовать в параметре :
$ udevadm info --attribute-walk --name=/dev/input/by-id/usb-foostan_Corne-event-kbd
Проверка правил перед загрузкой
Используйте команду:
# udevadm test $(udevadm info -q path -n имя_устройства) 2>&1
Вы можете также указать прямой системный путь до устройства:
# udevadm test /sys/class/backlight/acpi_video0/
Загрузка новых правил
udev способен определять наличие изменений в файлах правил автоматически, поэтому изменения сразу вступают в силу без необходимости перезапуска udev. Однако, новые правила не будут применены сразу к уже подключенным устройствам. Устройства с возможностью горячей замены, например, устройства USB, могут быть просто переподключены для применения к ним новых правил. Также вы можете перезагрузить модули ядра ohci-hcd
и , что автоматически приведет к перезагрузке всех драйверов для каждого USB-устройства.
Если правила не перезагружаются автоматически, выполните:
# udevadm control --reload-rules
Чтобы вручную заставить udev применить ваши правила, выполните:
# udevadm trigger
udisks
См. udisks.
Советы и рекомендации
Монтирование съёмных устройств
Монтировать съёмные устройства с помощью команды в правиле udev не стоит по двум причинам: (1) systemd по умолчанию запускает с отдельным "пространством имён монтирования" (см. namespaces(7)), что означает, что данное устройство не будет видно из остальной системы. (2) Чтобы этого не происходило, можно закомментировать параметры и в файле службы, но тогда проявится другая проблема: запускаемые udev процессы система будет убивать по истечении нескольких секунд. В случае файловых систем FUSE, вроде NTFS, "монтирование" запустит в пространстве пользователя процесс для работы с файловой системой; затем процесс будет уничтожен и при попытке доступа к ФС вы получите ошибку .
Есть несколько возможных решений:
- Из правила udev запускается пользовательская служба systemd; служба запустит сценарий, который, в свою очередь, может породить любое количество долгосрочных процессов (вроде FUSE). В качестве примера можно использовать утилиту udev-media-automount, разработанную для быстрого и надёжного автоматического монтирования устройств. Другой вариант той же идеи предложен в этом сообщении.
- В правилах udev вместо команды можно использовать , как рекомендуют разработчики systemd. Пример монтирования USB-дисков в каталоге :
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media"
- Тем не менее, такой подход считается медленным и ненадёжным.
- Программы вроде udisks или udiskie. Мощные утилиты, хоть и с довольно сложной настройкой. Нужно учитывать, что они работают для одного пользовательского сеанса: доступ к некоторым файловым системам предоставляется только тому пользователю, сеанс которого активен в данный момент.
Доступ к программаторам и виртуальным COM-портам
Следующий набор правил даст возможность пользователям, входящим в группу , получить доступ к USB-программаторам микроконтроллеров AVR USBtinyISP:
Идентификаторы производителя и изделия для других устройств можно узнать с помощью утилиты lsusb.
Выполнение команд при подключении VGA-монитора
Создайте правило со следующим содержимым, чтобы запускать при каждом подключении VGA-монитора:
KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/usr/bin/arandr"
Некоторые экранные менеджеры размещают файл вне домашнего каталога пользователя. В этом случае параметр ENV{XAUTHORITY}
необходимо соответствующим образом изменить. Например, значение переменной для GNOME Display Manager:
Определение новых накопителей eSATA
Если ваш накопитель eSATA не был определен системой при подключении, вы можете перезагрузить систему, не отключая кабель устройства, либо, если перезагрузка нежелательна, выполнить:
# echo 0 0 0 | tee /sys/class/scsi_host/host*/scan
Еще один вариант заключается в использовании утилиты из AUR:
# scsiadd -s
Накопитель должен появиться в /dev
. Если это не так, попробуйте выполнить:
# udevadm monitor
до и после вышеприведенных команд и посмотреть, происходит ли что-нибудь.
Определение внутренних портов SATA как внешних
Если вы подключили eSATA-адаптер, система все еще будет распоздавать его как внутренний SATA-накопитель. GNOME и KDE будут постоянно запрашивать пароль администратора. Следующее правило помечает все указанные SATA-порты как порты eSATA, благодаря чему обычные пользователи смогут подключать свой накопитель eSATA к этому порту как USB-накопитель без запроса пароля администратора:
DEVPATH
вы можете с помощью следующих команд (вместо /dev/sdb
укажите ваше устройство):
$ udevadm info --query=path /dev/sdb
/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
$ find /sys/devices/ -name sdb
/sys/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
Установка постоянных имен устройств
Из-за асинхронного способа загрузки модулей, они инициализируются в разном порядке от загрузки к загрузке. Это приводит к случайному переименованию устройств при каждом запуске. Чтобы задать постоянные имена вашим устройствам, можно создать специальное правило udev. Смотрите также статьи Постоянные имена для блочных устройств и Настройка сети#Смена имени интерфейса.
Видеоустройства
Процедура установки веб-камеры описана в статье Webcam setup.
При загрузке веб-камерам присваиваются случайные имена вида . Рекомендуемое решение состоит в создании символических ссылок с использованием правила udev (подобно правилу в разделе #Пример правила udev):
Принтеры
Если у вас несколько принтеров, им будут случайным образом присвоены имена вида , что, например, может помешать серверу CUPS правильно настроить устройства. Вы можете создать следующее правило, которое будет создавать постоянные символические ссылки в каталогах и подобно схеме, приведенной в статье Постоянные имена для блочных устройств:
/etc/udev/rules.d/60-persistent-printer.rules
ACTION=="remove", GOTO="persistent_printer_end" # Это не должно понадобиться #KERNEL!="lp*", GOTO="persistent_printer_end" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" ENV{ID_TYPE}!="printer", GOTO="persistent_printer_end" ENV{ID_SERIAL}=="?*", SYMLINK+="lp/by-id/$env{ID_BUS}-$env{ID_SERIAL}" IMPORT{builtin}="path_id" ENV{ID_PATH}=="?*", SYMLINK+="lp/by-path/$env{ID_PATH}" LABEL="persistent_printer_end"
Определение диска по серийному номеру
Действия с дисковыми устройствами можно выполнять на основании серийного номера , который можно узнать из вывода команды . Примерное правило udev для этого случая приведено ниже. В параметре RUN
сценарию передаётся имя устройства; это сделано исключительно в иллюстративных целях:
Пробуждение при активности USB-устройства
С помощью правила udev можно настроить систему выходить из режима сна при активности USB-устройств, например, мыши или клавиатуры.
Первым делом определите идентификаторы производителя и изделия для вашего устройства:
Затем найдите, куда данное устройство подключено:
Наконец, создайте правило, которое при подключении будет изменять атрибут как для устройства, так и для USB-контроллера, к которому оно подключено:
Генерирование событий
Может быть полезно сгенерировать различные события udev. Например, вы хотите симулировать отключение USB-устройства на удалённой машине. В таких случаях, используйте udevadm trigger
:
# udevadm trigger --verbose --type=subsystems --action=remove --subsystem-match=usb --attr-match="idVendor=abcd"
Эта команда симулирует отключение всех USB-устройств с указанным идентификатором поставщика .
Уведомления на рабочем столе
Заставить правильно работать из правила udev сценарий, содержащий команду , может оказаться непростой задачей, потому что уведомления не будут выводиться на рабочий стол. Ниже показано, какие файлы, команды и переменные окружения необходимо задйствовать, чтобы работала как положено.
1) Следующее правило udev запускает сценарий, создающий графическое и звуковое уведомление, когда яркость экрана меняется в зависимости от способа питания ноутбука:
/etc/udev/rules.d/99-backlight_notification.rules
# Правило на случай переключения на работу от батареи ACTION=="change", SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/USERNAME/.Xauthority" RUN+="/usr/bin/su USERNAME_TO_RUN_SCRIPT_AS -c /usr/local/bin/brightness_notification.sh" # Правило на случай переключения на работу от кабеля ACTION=="change", SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/USERNAME/.Xauthority" RUN+="/usr/bin/su USERNAME_TO_RUN_SCRIPT_AS -c /usr/local/bin/brightness_notification.sh"
- и необходимо заменить на имя пользователя, который запустил графический сеанс;
- сценарий должен запускаться командой , чтобы его владельцем считался не root, а пользователь, который запустил графический сеанс и для которого будут выводиться уведомления.
2) Содержимое сценария, который запускается правилом udev:
- , и необходимо заменить на имя и идентификатор пользователя, запустившего графический сеанс;
- команда
/usr/bin/sudo
воспроизводит звуковое уведомление с помощью pulseaudio; - для пользователя, запустившего графический сеанс, в котором будут отображаться уведомления, необходимо определить и экспортировать три переменные окружения (, и ).
3) Загрузите/перезагрузите новое правило udev и проверьте, как оно работает, выдернув или подключив кабель питания ноутбука.
Создание долгосрочных процессов
Программы, запущенные udev, блокируют последующие события от данного устройства, а любые процессы, порождённые правилом udev, завершаются сразу после обработки события. Если вы хотите запустить долгосрочный процесс с помощью udev, то либо используйте (например, ваша_команда | at now
или ), либо создайте юнит systemd, который можно запустить из правила udev.
Решение проблем
Добавление модулей в черный список
Иногда udev может ошибочно загружать неправильные модули ядра. Чтобы избежать этого, добавьте такие модули в чёрный список. Если модуль находится в чёрном списке, udev будет игнорировать его как при загрузке, так и при более позднем "горячем" подключении внешнего устройства (например, USB-носителя).
Отладочная печать
Если задать параметр ядра , то аппаратное обеспечение будет выдавать отладочную информацию. Другой способ — задать параметр
Чтобы добавить эту опцию в initramfs, укажите файл настроек udev в строке
/etc/mkinitcpio.conf
FILES="... /etc/udev/udev.conf"
после чего сгенерируйте initramfs.
udevd вылетает при загрузке
После миграции на LDAP или обновления системы, использующей LDAP, udevd может начать аварийно завершаться в момент загрузки системы с сообщением "Starting UDev Daemon". Обычно это происходит потому, что udevd пытается определить имя через LDAP, но не может, так как в этот момент еще не установлено подключение к сети.
Необходимо, чтобы все используемые в LDAP группы были продублированы локально. Получить имена групп, используемых в правилах udev, и имена групп, присутствующих в системе, можно командами:
# grep -Fr GROUP /etc/udev/rules.d/ /usr/lib/udev/rules.d/ | sed 's:.*GROUP="\([-a-z_]\{1,\}\)".*:\1:' | sort -u >udev_groups # cut -d: -f1 /etc/gshadow /etc/group | sort -u >present_groups
Вывод будет записан в файлы и . Чтобы увидеть различия, выполните построчное сравнение командой diff:
# diff -y present_groups udev_groups ... network < nobody < ntp < optical optical power | pcscd rfkill < root root scanner scanner smmsp < storage storage ...
В данном примере группа по какой-то причине отсутствует в системе. Все такие группы необходимо добавить в систему. Также убедитесь, что имена всех локальных ресурсов разрешены, прежде чем возвращаться к LDAP. Файл должен содержать следующую строку:
group: files ldap
Устройство является съемным, однако не признается таковым
Создайте правило udev для конкретного устройства. Чтобы получить подробную информацию об устройстве вы можете либо использовать , либо (не забудьте поменять /dev/sdb
если нужно):
$ udevadm info /dev/sdb | grep ID_SERIAL
Теперь установите UDISKS_AUTO="1"
, чтобы пометить устройство для автоматического монтирования и , чтобы пометить устройство как съёмное. Подробнее см.
Перезагрузите правила udev командой . Теперь ваше устройство будет распознаваться как съёмное.
Проблемы с автоматической загрузкой модулей аудиоустройств
Некоторые пользователи испытывают проблемы с загрузкой модулей звуковых устройств, для которых остались старые записи в . Чистка файла от таких записей может помочь.
snd_seq_oss
, snd_pcm_oss
и snd_mixer_oss
) больше не загружаются автоматически.Поддержка дисководов IDE
Начиная с версии 170, udev не поддерживает устройства CD-ROM/DVD-ROM, загружаемые как обычные IDE дисководы модулем и отображаемые в системе как . Дисковод доступен только программам, которые обращаются к устройству напрямую, таким как cdparanoia, но невидим для более высокоуровневых программ вроде KDE.
Причина, по которой загрузка модуля имеет приоритет перед другими модулями, например, , может заключаться в том, что по какой-либо причине модуль загружается в вашем initramfs. В этом случае вы можете просто заменить его в файле на .
Оптические дисководы имеют неверный group ID
Если значение group ID вашего дисковода установлено как disk
, но вы хотите, чтобы оно было , вам следует создать такое правило:
Смотрите также
- Справочное руководство udev (англ.)
- Введение в udev (англ.)
- Почтовая рассылка udev (англ.)
- Сценарии udev (англ.)
- Правила udev (англ.)
- Организация устройств и модулей в LFS (англ.)
- GUI и переменные экрана в правилах udev (англ.)