Служба не останавливается при отключении устройства
Для устройств systemd создаёт unit, за состоянием которых можно следить. Служба, привязанная к устройству, останавливается при его отключении сама. Без привязки она продолжает работать и заполняет журнал ошибками ввода-вывода.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Привязка к устройству не объявлена
Служба не знает об устройстве. При его исчезновении она остаётся активной и продолжает попытки обращения.
-
Имя unit устройства указано неверно
Имя выводится из пути устройства по особым правилам. Написанное вручную легко ошибочно, и привязка не работает.
-
Устройство не помечено как подходящее для unit
Не для каждого устройства создаётся unit: это зависит от правил подсистемы устройств. Без метки unit не появляется.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Какие устройства представлены unit.
systemctl list-units --type=device --all --no-legend | head -20Верное имя unit для пути устройства.
systemd-escape -p --suffix=device /dev/ttyUSB0Свойства и метки устройства.
udevadm info /dev/ttyUSB0 2>/dev/null | head -20Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Служба не знает об устройстве. При его исчезновении она остаётся активной и продолжает попытки обращения.
- Как проверить
-
Посмотрите unit устройства и зависимости службы.
systemctl list-units --type=device --no-legend | grep -i usb | head systemctl show myapp.service -p BindsTo -p After
- Как исправить
-
Объявите жёсткую привязку к unit устройства: при его исчезновении служба остановится сама.
[Unit] BindsTo=dev-ttyUSB0.device After=dev-ttyUSB0.device
- Почему происходит
- Имя выводится из пути устройства по особым правилам. Написанное вручную легко ошибочно, и привязка не работает.
- Как проверить
-
Посмотрите верное имя unit для устройства.
systemd-escape -p --suffix=device /dev/ttyUSB0 systemctl list-units --type=device --all --no-legend | grep -i ttyusb
- Как исправить
- Используйте вычисленное имя. Проверить существование unit устройства можно в списке устройств.
- Почему происходит
- Не для каждого устройства создаётся unit: это зависит от правил подсистемы устройств. Без метки unit не появляется.
- Как проверить
-
Посмотрите свойства устройства.
udevadm info /dev/ttyUSB0 2>/dev/null | grep -iE "SYSTEMD_WANTS|TAGS" | head
- Как исправить
- Добавьте правило подсистемы устройств с нужной меткой либо следите за устройством из самой службы. Привязка работает только для помеченных устройств.
Пример вывода
Устройство отключено, служба продолжает обращения. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
kernel: usb 1-2: USB disconnect, device number 4
kernel: ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected
myapp[9400]: error: read /dev/ttyUSB0: no such device
myapp[9400]: error: read /dev/ttyUSB0: no such device
Связанные ошибки
- Служба ждёт устройство: device-unit не появляется Зависимость от .device не выполняется: устройства нет, оно не размечено, или ядро не сообщило о нём.
- Служба не запускается вместе с зависимостью After= без Wants= не запускает зависимость. Разбор частой путаницы между порядком и необходимостью.
- Input/output error в журнале службы Ошибка ввода-вывода: проблемы носителя, отвалившийся сетевой ресурс, повреждённая файловая система. Что проверять срочно.
- Connection refused в журнале службы Соединение отклонено: служба не может подключиться к базе, кешу или другому сервису. Порядок запуска, адрес, брандмауэр.
- Dependency failed for … и результат 'dependency' Сообщение Dependency failed for: служба не запускалась, потому что упала её зависимость. Как найти настоящего виновника.
- Docker: демон не запускается без containerd docker.service падает, потому что не работает containerd.service. Разбор зависимости и сокета containerd.
- Found ordering cycle: циклическая зависимость при загрузке systemd нашёл цикл в порядке запуска и разорвал его, отбросив одну зависимость. Как найти цикл и правильно расставить After и Requires.
- Operation refused, unit may be requested by dependency only systemd отказывается запускать unit вручную из-за RefuseManualStart=yes. Что это значит и как запустить службу правильно.
Источники
-
systemd.device(5)
Unit устройств и метки подсистемы устройств. -
systemd.unit(5)
BindsTo= и остановка вслед за исчезновением unit. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Проверено на systemd 255: без привязки служба остаётся активной после отключения устройства.