Автозапуск служб, работающих с CAN интерфейсом

Вводная проста. Имеем самописную службу, которая висит на CAN и что-то отдает из CAN в mqtt.
Имеем файл, который запускает службу. И после долгих мучений подгоняем параметр

ExecStartPre=/bin/sleep 80

к значение в 80 секунд! 60 секунд мало! При 60 секундах утилита запускается, но данных с шины can еще не видит. И по прошествии времени так и не начинает видеть. Помогает или перезагрузка службы, или отложенный на 80 сек запуск службы при рестарте контроллера.
Я согласен, что и код надо посмотреть у утилиты, но все же хотелось бы понять, от какой службы зависит доступность интерфейса can?
Что надо поставить параметр After= ?
Картинка с графиком загрузки служб контроллера на ЯД.

[Unit]
Description=can-mqtt.service

After=wb-hwconf-manager.service
After=wb-rules.service
After=mosquitto.service
After=network-online.target

[Service]
Type=simple                        
User=root                          
Group=root                         
ExecStartPre=/bin/sleep 80        
#ExecStart=/bin/bash -c 'exec /opt/canmqttd >> /var/log/canmqttd.log'
ExecStart= /opt/canmqttd           
Restart=always                     
TimeoutSec=5min

[Install]
WantedBy=multi-user.target

От After=wb-hwconf-manager.service, но, насколько я понимаю, это не зависимость от сервиса в чистом виде. Т.е. ждать нужно пока сервис wb-hwconf-manager закончит работать, а не просто стартует.

Вижу два решения:

  1. в systemd написать зависимость от появления интерфейса can0
  2. в вашем сервисе ждать появления can0

Но интерфейс появляется сразу после загрузки. Вот жить он начинает сильно позже.

“Жить” - имеете в виду что возникает ошибка при записи/чтении?

Приветствую!
Не ясно, что означают понятия интерфейс “появляется” и “живёт”. Прошу описать симптомы.

Немного о том, как всё работает внутри:

  1. Когда в веб-интерфейсе в настройках RS485-2 выставлен CAN, включается CAN-трансивер и ядро загружает нужный драйвер. Это можно увидеть, посмотрев в /sys/class/net/ или же - увидев
[   24.294722] CAN device driver interface
[   24.352888] 2094000.flexcan supply xceiver not found, using dummy regulator
[   24.510496] flexcan 2094000.flexcan: device registered (reg_base=e2578000, irq=219)

в логе загрузки контроллера. Соответственно, это сохраняется при перезагрузках (после выполнения wb-hwconf-manager.service (запускается перед multi-user.target)). На данный момент, интерфейс доступен, но не настроен.
2) Для передачи данных интерфейс надо настраивать руками ip link set can0 up type can bitrate 125000 или можно автоматизировать, вставив

auto can0
iface can0 inet manual
   pre-up /sbin/ip link set $IFACE type can bitrate 125000
   up /sbin/ifconfig $IFACE up
   down /sbin/ifconfig $IFACE down

в /etc/network/interfaces.

Мы провели в офисе небольшой эксперимент: прописали то, что выше в /etc/network/interfaces и перезагрузили контроллер. 2020-09-09-142242_655x228_scrot
CAN работает сразу после перезагрузки (53c, пока станет доступен терминал).

Резюмирую:

  1. Кажется, из текущего systemd-юнита можно убрать все After=, кроме mosquitto
  2. Попробуйте поднимать CAN через /etc/network/interfaces
    Если проблема сохранится - скорее всего, виноват canmqttd

Прошу прощения за задержку, но sleep 80 проблему не то чтобы снял, но перевел ее в приоритет пониже.
Итак, поехали!

  1. Что бы canmqtd убрать за скобки будем работать с candump. К нему ведь нет претензий?
  2. /etc/network/interfaces
iface can0 inet manual
  down /sbin/ifconfig can0 down
  pre-up /sbin/ip link set can0 up type can bitrate 500000
  up /sbin/ifconfig can0 up

В терминале данные бегут, никто не спорит.

root@wirenboard-AJYF6OUR:/etc/network# candump can0
  can0  1F6   [8]  00 C0 42 00 00 FF 0F FF
  can0  186   [7]  00 00 FF FF FF FF F8
  can0  217   [8]  FF FF 00 00 00 00 00 FC
  can0  18A   [6]  FF F0 FF C4 D8 00
  can0  189   [8]  FF FF FF FF F0 00 00 00
  can0  1F6   [8]  00 C0 42 00 00 FF 0F FF

создаем службу candumpd.service

[Unit]
Description=CANDUMP service daemon

[Service]
Type=simple
ExecStart=/bin/bash -c 'exec /usr/bin/candump can0 >> /var/log/candump.log'

[Install]
WantedBy=multi-user.target

далее
systemctl enable candumpd
и
reboot
смотрим /var/log/candump.log - пусто.
ps ax | grep can
тоже пусто.
однако
service candumpd start
из терминала, и все работает!

Я так понимаю, что понимания по теме ни у кого нет?

Именно разработчик занимается и обязательно напишет. Я ему напоминаю и про вас не забыли.

Приветствую и прошу прощения за задержку!

Провели ещё один эксперимент в офисе с Вашим конфигом /etc/network/interfaces (предполагаю, в нём не указана строчка auto can0) и Вашим же systemd-юнитом.

Действительно, CAN ничего не принимает.
systemctl status candumpd после перезагрузки говорит нам, в чём проблема:


Тестовый сервис candumpd стартует и пытается слушать CAN до того, как интерфейс can0 оказывается поднят и сконфигурирован (через /etc/network/interfaces). Если дёрнуть сервис candumpd руками после загрузки, данные пойдут, т.к. интерфейсы-то подняты!

Интересное наблюдение: похоже, текущая реализация настроек сети (debian-овский networking (/etc/network/interfaces) + systemd) не позволяет нам отследить момент поднятия сетевых интерфейсов и запустить наш сервис после этого.
Другими словами, что-то вроде After=network-online.target сейчас работать не будет.

Предлагаю решение: в ExecStartPre ждать, пока сетевые интерфейсы (прописанные в /etc/network/interfaces) не поднимутся. Прилагаю сервис, заработавший у нас. candumpd.service (618 Байт). Получается некоторый апгрейд вашего sleep 80.

Подозреваю, также можно выкинуть настроку CAN из /etc/network/interfaces и прописать её в ExecStartPre сервиса вместо того, что есть сейчас (не проверял).

Таким образом, перед работой с CAN нужно иметь:

  1. Стартовавший wb-hwconf-manager.service (включает трансивер и дёргает линуксовый драйвер)
  2. Настроенный CAN-интерфейс

UPD: проверили вторую гипотезу. Кажется, действительно, проще настраивать интерфейс в ExecStartPre вместо /etc/network/interfaces

[Unit]
Description=CANDUMP service daemon
Requires=wb-hwconf-manager.service
After=wb-hwconf-manager.service
ConditionPathExists=/sys/class/net/can0/

[Service]
Type=simple
ExecStartPre=/sbin/ip link set can0 up type can bitrate 125000
ExecStart=/bin/bash -c 'exec /usr/bin/candump can0 >> /var/log/candump.log'

[Install]
WantedBy=multi-user.target

Логика следующая: запускаемся после wb-hwconf-manager и смотрим, что can0 появился в sysfs.

Похоже, что бы служба нормально порезапускалась из терминала ручками, надо добавить первым ExecStartPre

ExecStartPre=/sbin/ip link set can0 down

Возникает вопрос, как работать с контроллерами, у которых может быть как 1 так и 2 интерфейса CAN. И они могут работать на разных скоростях. Писать свой конфигурационный файл под службу?