Вопрос или проблема
Я прочитал другие похожие вопросы, но ответы там не работают в моем случае. У меня есть правило udev в файле /etc/udev/rules.d/99-headset_switcher.rules
Правило следующее:
ACTION=="add", RUN="/usr/local/bin/switch_headset.sh"
Когда я запускаю udevadm test /sys/class/bluetooth/hci0
, я вижу:
DEVPATH=/devices/pci0000:00/0000:00:08.1/0000:04:00.4/usb3/3-1/3-1:1.0/bluetooth/hci0
DEVTYPE=host
ACTION=add
SUBSYSTEM=bluetooth
TAGS=:systemd:
CURRENT_TAGS=:systemd:
SYSTEMD_ALIAS=/sys/subsystem/bluetooth/devices/hci0
SYSTEMD_WANTS=bluetooth.target
SYSTEMD_USER_WANTS=bluetooth.target
USEC_INITIALIZED=9792645
run: '/usr/local/bin/switch_headset.sh'
Unload module index
Unloaded link configuration context.
Что указывает на то, что мой скрипт запускается. Скрипт содержит:
cat /usr/local/bin/switch_headset.sh
#!/bin/bash
/usr/bin/echo переключение гарнитуры >>/tmp/headset.log
Тест udev не добавляет ничего в файл лога. Если я запускаю файл в оболочке, все работает нормально.
Вот что я попробовал до сих пор.
- Изменил все пути на абсолютные.
- Пробовал RUN+= и RUN=.
- Удалил все из моего правила и поэтапно строил его с RUN…, ничего не сработало.
- Я знаю, что правила udev работают очень короткое время, но не думаю, что это проблема здесь.
Буду рад любым подсказкам, чего я упускаю.
Ответ или решение
Запуск Bash-скрипта из правила udev может быть сложной задачей, и справедливо, что у вас возникают трудности. Важно знать, что окружение, в котором выполняются правила udev, значительно отличается от обычной командной оболочки. Давайте разберемся, как правильно настроить вашу udev-правило для запуска скрипта.
Проблема
Ваше правило udev, которое находится в файле /etc/udev/rules.d/99-headset_switcher.rules
, выглядит следующим образом:
ACTION=="add", RUN="/usr/local/bin/switch_headset.sh"
Вы упомянули, что ваш скрипт не записывает данные в файл /tmp/headset.log
, когда udev запускает его, хотя при ручном запуске все проходит корректно.
Причины и решение
-
Ограниченные переменные среды: Скрипты, выполняемые через udev, не имеют доступа к той же переменной среды, что и обычные сессии оболочки. Это значит, что некоторые команды или пути могут не работать.
-
Проблемы с правами: Хотя сам udev запускается с правами root, следует убедиться, что пользователь, под которым записывается файл, имеет соответствующие разрешения на запись в
/tmp/headset.log
. -
Логи и диагностика: Чтобы упростить диагностику, необходимо добавить больше логирования в ваш скрипт. Отредактируйте ваш файл
switch_headset.sh
, чтобы записывать сообщения об ошибках:#!/bin/bash echo "$(date): switching headset" >> /tmp/headset.log 2>&1
-
Echo вместо /usr/bin/echo: В вашем скрипте, верно использование
echo
, но убедитесь, что вы используете его корректно. Явное указание пути может быть не обязательным. -
Использование
udevadm control
: После изменения правил udev, возможно, вам понадобится перезагрузить daemon:sudo udevadm control --reload-rules sudo udevadm trigger
Альтернативные подходы
Если все вышеупомянутое не помогло, вы можете попробовать следующие альтернативные пути:
-
Запуск через другой механизм: Вместо
RUN
вы можете использоватьPROGRAM
, чтобы запустить ваш скрипт через интерпретатор.ACTION=="add", PROGRAM="/usr/local/bin/switch_headset.sh"
-
Использование
systemd
: Если ваша система поддерживает systemd, вы можете рассмотреть возможность создания systemd-сервиса, который будет зависеть от события udev. Это поможет избежать ограничений, связанных с запуском через udev.
Подведение итогов
Запуск скриптов через udev требует понимания специфики окружения, в котором выполняются правила. Путем тщательной настройки и добавления логирования можно диагностировать проблемы и обеспечить успешное выполнение скриптов. Используйте приведенные стратегии для выявления и устранения возможных проблем, и вы сможете решить свою задачу более эффективно.