7.1 KiB
title, tags, updated, status
| title | tags | updated | status | |||||
|---|---|---|---|---|---|---|---|---|
| План: защита modbus-bridge от гонки с udev (ZONT датчики) |
|
2026-08-25 | proposed |
План: защита modbus-bridge/mbusd от гонки с udev (после рестарта TrueNAS)
Статус: план на согласование (2026-08-25), ничего не применено. Задача: исключить повторение «485-датчики недоступные в ZONT» после перезагрузки TrueNAS.
Контекст / причины
- ZONT (192.168.0.10) — Modbus master на RS-485 шине
ttyZONT. 485-датчики: Dining=1, Kids=2, Bedroom=3. - Контейнер
modbus-bridgeсниффит их и подставляет виртуальные slaves 101/102/103 → ZONT опрашивает как внешние датчики. - Если modbus-bridge не слушает шину → ZONT показывает датчики «недоступные».
- Первопричина 2026-08-25: гонка загрузки — docker стартовал раньше udev,
/dev/ttyZONTи/dev/ttyVentещё не существовали → контейнеры упали на старте:error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory(ExitCode 128/255, RestartCount=0). restart: unless-stoppedне перезапускает контейнер, упавший на этапеdocker start(binding device fail) — отказ до старта процесса.
Ключевое ограничение (почему задержка в entrypoint НЕ поможет в чистом виде)
У modbus-bridge и mbusd устройство проброшено через devices: /dev/ttyZONT:/dev/ttyUSB0 / devices: /dev/ttyVent:/dev/ttyUSB0.
Docker при start монтирует устройство ДО запуска процесса — если <src> не существует на момент создания/старта контейнера, контейнер вообще не стартует, и sleep внутри entrypoint/CMD никогда не выполнится.
→ Простой «sleep N в entrypoint» проблему НЕ решает.
Почему контейнеры сами НЕ поднялись (RestartCount=0) — разбор
restart: unless-stopped/always ретраит в ДВУХ случаях:
- Процесс контейнера стартовал и завершился с ненулевым кодом → демон ретраит с backoff (RestartCount растёт).
- Перезапуск самого docker daemon → демон пробует поднять
unless-stopped/alwaysконтейнеры.
Наш случай — ТРЕТИЙ, особый: контейнер вообще не стартовал — ошибка на этапе монтирования устройства:
error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory.
- Нет процесса, который «завершился бы» — docker не смог примонтировать устройство, процесс не запущен вовсе.
- Раз нет завершённого процесса, restart policy не на что применять →
RestartCount=0, демон не ретраит. - После падения (13:24) демон НЕ перезапускался (docker.pid с 07:14) → второго триггера не было.
Вывод: отказ на этапе mount устройства НЕ перезапускается restart policy. Авто-подъём при перезагрузке гарантирован только если устройства существуют на момент старта демона. Иначе — контейнеры молча остаются в exited до ручного docker start.
Решение (рекомендуемое): POSTINIT init script с ожиданием + docker start
Уже есть init script id=1 «Map ttyUSB» (POSTINIT), который копирует udev-правила и делает udevadm trigger. Он НЕ ждёт создания симлинков и не запускает докер-контейнеры.
Добавить новый POSTINIT init script (COMMAND, when=POSTINIT, enabled=true), который:
- Ждёт появления
/dev/ttyZONTи/dev/ttyVent(poll до ~20 сек). - Как только оба есть —
docker start modbus-bridge mbusd. - Если docker ещё не готов — также пробует переждать.
Пример скрипта (положить в /mnt/RED_2TB/system/start-modbus.sh):
#!/bin/bash
# Ожидание tty-алиасов от udev (макс ~25 сек)
for i in $(seq 1 25); do
[ -e /dev/ttyZONT ] && [ -e /dev/ttyVent ] && break
sleep 1
done
sleep 2 # небольшая пауза на устойчивость udev
docker start modbus-bridge mbusd 2>/dev/null
Команда в TrueNAS init: bash /mnt/RED_2TB/system/start-modbus.sh
Timeout скрипта в TrueNAS: 30.
Альтернатива (не рекомендуется): поменять
devices:на прямой/dev/ttyUSB1//dev/ttyUSB0— но номер ttyUSB может прыгать, алиасы для того и нужны.
Примечание: менять Dockerfile/entrypoint и/или
restart: alwaysздесь недостаточно — отказ на этапе mount устройства restart policy не обрабатывает.
Шаги внедрения (после согласования)
- Создать
/mnt/RED_2TB/system/start-modbus.shна TrueNAS (chmod +x). - Добавить init script через midclt:
midclt call initshutdownscript.create '{"type":"COMMAND","command":"bash /mnt/RED_2TB/system/start-modbus.sh","when":"POSTINIT","enabled":true,"timeout":30,"comment":"Start modbus-bridge/mbusd after udev tty aliases"}' - Проверить:
midclt call initshutdownscript.query - Проверить после reboot: контейнеры Up,
ttyZONT/ttyVentсозданы, датчики в ZONT отвечают.
Вердикт по исходному вопросу «добавить задержку в entrypoint»
- Задержка внутри entrypoint/CMD для этих контейнеров не выполняется из-за device mount до старта процесса → этот путь отпадает.
- Правильный эквивалент «задержки до готовности» — скрипт выше на уровне TrueNAS init (ожидание устройств, затем
docker start).
Связанные заметки
- family/how-to/home-automation.md — карта slave ID, ZONT, датчики
- family/how-to/truenas-infrastructure.md — docker, modbus-bridge, mbusd, udev rules, init scripts