--- status: obsolete tags: - family - homeautomation - zont - modbus title: Защита modbus-bridge от гонки с udev (ZONT датчики) updated: '2026-09-14' --- # Защита modbus-bridge/mbusd от гонки с udev (ZONT датчики) > 🔴 **ДОКУМЕНТ УСТАРЕЛ (2026-09-14).** Речь идёт о контейнерах **на TrueNAS** — `modbus-bridge` и `mbusd`. Они **погашены** (`docker stop` + `--restart=no`) вместе со всем стеком автоматизации; USB-адаптеры физически переехали на **t610**, где узлов `/dev/ttyZONT`/`/dev/ttyVent` на TrueNAS больше не существует. **Проблема неактуальна.** > На **t610** гонка udev решается иначе: Supervisor (HA OS) сам ждёт устройство перед стартом аддона — отдельный init-скрипт не нужен. > История/контекст декомиссии: [[family/plans/t610-home-automation]] §5-кватер-Л, канон-блок — [[family/how-to/truenas-infrastructure]]. > ⚠️ Документ **оставлен как историческая справка** (пригодится, если когда-нибудь откатывать TrueNAS-стек). > > ~~Статус: **внедрено** (2026-08-25, шаги 1–3). Датчики в ZONT снова отвечают, скрипт и init script на месте.~~ ## Проблема 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):** гонка загрузки TrueNAS — docker стартовал раньше udev, `/dev/ttyZONT` и `/dev/ttyVent` ещё не существовали → контейнеры `modbus-bridge` (Exit 128) и `mbusd` (Exit 255) упали на старте: `error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory` (RestartCount=0). Фикс был: ручной `docker start modbus-bridge mbusd`. ## Почему контейнеры сами НЕ поднялись (RestartCount=0) `restart: unless-stopped`/`always` ретраит в ДВУХ случаях: 1. Процесс контейнера **стартовал и завершился** с ненулевым кодом → демон ретраит с backoff. 2. **Перезапуск docker daemon** → демон пробует поднять `unless-stopped`/`always` контейнеры. Наш случай — ТРЕТИЙ, особый: контейнер **вообще не стартовал** — ошибка на этапе монтирования устройства. - Нет процесса, который «завершился бы» → **restart policy не на что применять** → `RestartCount=0`, демон не ретраит. - После падения (13:24) демон не перезапускался → второго триггера не было. **Вывод:** отказ на этапе mount устройства НЕ перезапускается restart policy. Авто-подъём гарантирован только скриптом, ждущим устройства. ## Ключевое ограничение (задержка в entrypoint НЕ помогает) У обоих контейнеров устройство проброшено через `devices: /dev/ttyZONT:/dev/ttyUSB0` / `devices: /dev/ttyVent:/dev/ttyUSB0`. **Docker при `start` монтирует устройство ДО запуска процесса** — если `` отсутствует на момент старта, контейнер вообще не стартует, и `sleep` внутри entrypoint/CMD **не выполняется**. Поэтому решение — на уровне init скрипта. ## Внедрённое решение ### 1. Скрипт `/mnt/RED_2TB/system/start-modbus.sh` (root, `-rw-r--r--`) Ожидает появления tty-алиасов от udev (до ~50с), затем запускает контейнеры: ```bash #!/bin/bash # Ждём tty-алиасы от udev (макс ~25с), затем стартуем modbus контейнеры. for i in $(seq 1 50); do [ -e /dev/ttyZONT ] && [ -e /dev/ttyVent ] && break sleep 1 done sleep 2 docker start modbus-bridge mbusd 2>/dev/null ``` ### 2. Init script (TrueNAS, id=3) - **when:** POSTINIT, **type:** COMMAND, **timeout:** 30, **enabled:** true - **command:** `bash /mnt/RED_2TB/system/start-modbus.sh` - **comment:** `Start modbus-bridge/mbusd after udev tty aliases` ### Порядок POSTINIT скриптов | id | command | comment | enabled | |----|---------|---------|---------| | 1 | `cp .../99-tty-alias.rules /etc/udev/rules.d/ && udevadm control --reload-rules && udevadm trigger` | Map ttyUSB | ✅ | | 2 | `bash /mnt/RED_2TB/system/tunnel.sh &` | — | ✅ | | 3 | `bash /mnt/RED_2TB/system/start-modbus.sh` | Start modbus-bridge/mbusd after udev tty aliases | ✅ | ## Проверка - `/dev/ttyZONT` → `ttyUSB1` (CH340), `/dev/ttyVent` → `ttyUSB0` — симлинки появляются после POSTINIT id=1. - После reboot: `docker ps` — modbus-bridge и mbusd Up; датчики в ZONT отвечают. - Просмотр init scripts: `midclt call initshutdownscript.query` - Откат: `midclt call initshutdownscript.delete ` + удалить скрипт с диска. ## Связанные заметки - [[family/how-to/home-automation.md]] — карта slave ID, ZONT, датчики - [[family/how-to/truenas-infrastructure.md]] — docker, modbus-bridge, mbusd, udev rules, init scripts