Вопрос или проблема
У меня есть монитор с интегрированным USB хабом (и физическим выключателем питания), подключенный к моему Raspberry Pi, и я хочу выполнить два разных скрипта, когда монитор включается и выключается.
Первая часть, отвечающая за включение монитора, работает хорошо, но при его выключении ничего не происходит. Опираясь на другие сообщения на форумах, я попробовал разные варианты правила, но ни одно не сработало.
Файл правил в /etc/udev/rules.d
(со всеми тремя вариациями)
SUBSYSTEM=="usb", ACTION=="add", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_on.sh"
SUBSYSTEM=="usb", ACTION=="remove", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_off.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_MODEL}=="2514", ENV{ID_VENDOR}=="03f0", RUN+="/home/pi/monitor_off.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{idProduct}=="2514", ENV{idVendor}=="03f0", RUN+="/home/pi/monitor_off.sh"
Тестирование с udevadm test
показывает, что первые два правила удаления должны сработать, третье – нет.
udevadm test --action="remove" /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4
Эта программа предназначена только для отладки, она не запускает никакую программу
[...]
Чтение файла правил: /etc/udev/rules.d/99-monitor.rules
[...]
1-1.4: RUN '/home/pi/monitor_off.sh' /etc/udev/rules.d/99-monitor.rules:2
1-1.4: RUN '/home/pi/monitor_off.sh' /etc/udev/rules.d/99-monitor.rules:3
DEVPATH=/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4
DEVNAME=/dev/bus/usb/001/060
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=3f0/2514/0
TYPE=9/0/2
BUSNUM=001
DEVNUM=060
MAJOR=189
MINOR=59
ACTION=remove
SUBSYSTEM=usb
USEC_INITIALIZED=1470318118448
ID_VENDOR=03f0
ID_VENDOR_ENC=03f0
ID_VENDOR_ID=03f0
ID_MODEL=2514
ID_MODEL_ENC=2514
ID_MODEL_ID=2514
ID_REVISION=0000
ID_SERIAL=03f0_2514
ID_BUS=usb
ID_USB_INTERFACES=:090001:090002:
ID_VENDOR_FROM_DATABASE=HP, Inc
ID_MODEL_FROM_DATABASE=4-port hub
ID_PATH=platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.4
ID_PATH_TAG=platform-fd500000_pcie-pci-0000_01_00_0-usb-0_1_4
ID_FOR_SEAT=usb-platform-fd500000_pcie-pci-0000_01_00_0-usb-0_1_4
TAGS=:seat:
run: '/home/pi/monitor_off.sh'
run: '/home/pi/monitor_off.sh'
Разгрузка индекса модулей
Разгружен контекст конфигурации ссылок.
Таким образом, при выключении монитора не срабатывает скрипт monitor_off.sh
. В daemon.log
есть много сообщений, не знаю, как их проанализировать. Ниже приведены сообщения, связанные с USB хабом (1-1.4).
13 сен 17:57:05 crumble systemd-udevd[5413]: 1-1.4: sd-device-monitor: Передано 326 байт в монитор netlink
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Обработка устройства (SEQNUM=3310, ACTION=unbind)
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: ИМПОРТ встроенного 'usb_id' /usr/lib/udev/rules.d/50-udev-default.rules:13
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Не удалось открыть файл 'descriptors' USB устройства: Нет такого файла или каталога
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Не удалось получить атрибут idVendor: Нет такого файла или каталога
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: ИМПОРТ встроенного 'usb_id' не удался: Нет такого файла или каталога
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Обработка узла устройства '/dev/bus/usb/001/060', devnum=c189:59, mode=0600, uid=0, gid=0
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: не удается stat() узел '/dev/bus/usb/001/060' (Нет такого файла или каталога)
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: sd-device: Создан пустой файл '/run/udev/data/c189:59' для '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4'
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Устройство (SEQNUM=3310, ACTION=unbind) обработано
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: sd-device-monitor: Передано 326 байт в монитор netlink
13 сен 17:57:05 crumble systemd-udevd[5413]: 1-1.4: sd-device-monitor: Передано 326 байт в монитор netlink
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Обработка устройства (SEQNUM=3311, ACTION=remove)
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: Устройство (SEQNUM=3311, ACTION=remove) обработано
13 сен 17:57:05 crumble systemd-udevd[23020]: 1-1.4: sd-device-monitor: Передано 326 байт в монитор netlink
Я также пытался использовать ATTRS
вместо ATTR
или ENV
, и это срабатывало, однако это срабатывало несколько раз в зависимости от того, что подключено к хабу.
Версия ОС – raspbian buster.
В конце концов, я решил проблему с этими правилами:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_on.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="3f0/2514/0", RUN+="/home/pi/monitor_off.sh"
Похоже, что доступно только несколько атрибутов в качестве переменных среды, и PRODUCT является одним из них, который содержит информацию о производителе, продукте и что-то еще (0 в моем случае). Добавление DEVTYPE было необходимо, чтобы избежать многократного выполнения, поскольку то же самое значение PRODUCT также было установлено для USB портов.
У меня была точно такая же проблема, когда я пытался сделать скрипт для моего ЦАПа Fiio X5 gen III. Я не хотел, чтобы ALSA переключала мой поток, когда он не был подключен, поэтому я создал эти правила (закомментированное правило удаления неверно):
# Bus 001 Device 017: ID 2972:0026 FiiO Electronics Technology X5
SUBSYSTEM=="usb", ATTR{idVendor}=="2972", ATTR{idProduct}=="0026", ACTION=="add", RUN+="/usr/local/bin/x5_audio_connect.sh"
#SUBSYSTEM=="usb", ATTR{idVendor}=="2972", ATTR{idProduct}=="0026", ACTION=="remove", RUN+="/usr/local/bin/x5_audio_disconnect.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="2972/26/222", RUN+="/usr/local/bin/x5_audio_disconnect.sh"
Адаптация вашего решения сработала отлично!
Ответ или решение
Решение проблемы с правилами UDev для отключения устройств
Если вы столкнулись с проблемой, что скрипт не выполняется при отключении монитора с интегрированным USB-хабом от Raspberry Pi, то вы не одиноки. Давайте подробно рассмотрим, почему это может происходить, и как можно устранить проблему.
Причины проблемы
-
Отсутствие срабатывания правил UDev: Ваша конфигурация правил может быть некорректной, что не позволяет событию "remove" корректно триггерить необходимый скрипт.
-
Атрибуты и окружения: Некоторые атрибуты могут отсутствовать в момент, когда устройство отключается. Это особенно актуально для таких атрибутов, как
idVendor
иidProduct
, которые могут не определяться корректно. -
Множественные срабатывания: Если устройство на самом деле отключает несколько подустройств (например, USB-порты), это может привести к множественным срабатываниям одного и того же события.
Ваши текущие правила
На основе представленных правил можно выделить следующее:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_on.sh"
SUBSYSTEM=="usb", ACTION=="remove", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_off.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_MODEL}=="2514", ENV{ID_VENDOR}=="03f0", RUN+="/home/pi/monitor_off.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{idProduct}=="2514", ENV{idVendor}=="03f0", RUN+="/home/pi/monitor_off.sh"
Из-за того, что некоторые правила не срабатывают, вы не получаете ожидания скрипта для отключения.
Решение
На основании ваших наблюдений и итогов, вы нашли правильные правила:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idProduct}=="2514", ATTR{idVendor}=="03f0", RUN+="/home/pi/monitor_on.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="3f0/2514/0", RUN+="/home/pi/monitor_off.sh"
Краткое пояснение:
- ENV{DEVTYPE}: Указывает, что вы работаете именно с устройством типа USB, что позволяет избежать множественных срабатываний в случае отключения порта.
- ENV{PRODUCT}: Уникально определяет комбинацию idVendor и idProduct с дополнительным значением, что исключает возможность конфликтов, связанных с другими устройствами на хабе.
Это правило корректно работает благодаря наличию специфических для вашего устройства атрибутов, которые являются стабильными в момент отключения.
Рекомендации по тестированию
-
Проверка логов: Откройте файл
/var/log/daemon.log
, чтобы убедиться, что вызывает ошибки или проблемы при выполнении скрипта. -
Использование
udevadm
: Применяйте командуudevadm test
для отладки правил и подтверждения, что скрипт действительно сработает при отключении устройства. -
Логи скриптов: Добавьте логи в ваши скрипты (
monitor_on.sh
иmonitor_off.sh
), чтобы удостовериться в их выполнении и отлавливать возможные ошибки.
Заключение
Проблемы с правилами UDev могут быть сложными и требуют внимательного подхода к детальным нюансам конфигурации устройств и их атрибутов. Ваша задача заключалась в правильном определении условий, при которых срабатывают события. Найденное вами решение позволяет избежать множества потенциальных проблем и является надежным вариантом для управления вашими USB-устройствами.