Выполнение оператора udev RUN после запуска службы systemctl

Я написал демон, который управляет несколькими коммуникационными протоколами через одно или несколько устройств RS232 (обычно FT232R usb2serial). После появления устройства /dev/ttyUSB*, если обнаружены определенные атрибуты, systemd получает указание запустить этот демон через udev:

ENV{SYSTEMD_WANTS}="%s{manufacturer}.service"

После запуска демона ему нужно указать, какое устройство открывать, что я и делаю через udev:

RUN="/usr/bin/sercomc open %E{sd_name} %E{sd_proto} %N"

Таким образом, полное правило udev выглядит так:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{manufacturer}=="sercomd", ENV{SYSTEMD_WANTS}="%s{manufacturer}.service", ENV{sd_proto}="%s{product}", ENV{sd_name}="%s{serial}", RUN="/usr/bin/sercomc open %E{sd_name} %E{sd_proto} %N"

Теперь проблема в том, что RUN выполняется до запуска демона, так что эта команда явно не действует:

systemd-udevd[1638]: starting '/usr/bin/sercomc open ctl-vk1 ctserial /dev/ttyUSB0'
systemd-udevd[1632]: '/usr/bin/sercomc open ctl-vk1 ctserial /dev/ttyUSB0'(err) 'Couldn't connect to server: Connect failed: Connection refused'
[...]
sercomctl[1639]: [2015-10-12 03:05:39:291634] Serial communication daemon ver. 0.5 starting up

Есть ли рекомендуемый способ решения этой проблемы, т. е. запуск команды после того, как systemd завершит запуск службы?


person Thilo Schulz    schedule 12.10.2015    source источник


Ответы (1)


Если вы столкнулись с похожей проблемой и прочитали вопрос, пусть вас не смущает название используемого мной программного обеспечения. Сразу скажу, что «sercomd» — это имя демона, который управляет последовательными соединениями, а «sercomc» — это программа-клиент, которая сообщает sercomd открыть это устройство, используя определенный протокол. Кроме того, я манипулировал EEPROM микросхемы FTDI usb2serial таким образом, чтобы строки продукта, производителя и серийного номера отображали определяемые пользователем значения, которые я могу использовать для автоматического распознавания последовательных адаптеров по принципу «подключи и работай».

Сейчас я использую экземпляр службы с файлом модуля /lib/systemd/system/[email protected] для каждого появляющегося устройства.

Правило udev теперь гласит:

    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{manufacturer}=="sercomd", ACTION=="add", SYMLINK="tty%s{serial}", PROGRAM="/bin/systemd-escape %s{serial}", ENV{SYSTEMD_WANTS}="sercomd@%c.service", ENV{sd_proto}="%s{product}", ENV{sd_dev}="%N"

Это правило устанавливает несколько переменных среды sd_proto и sd_dev, а также третий параметр sd_dev, который затем можно извлечь из файла [email protected]:

    ExecStart=/bin/bash -c "eval $$( udevadm info --query=env --export /dev/tty%I ); sercomc open %I $$sd_proto $$sd_dev"
    ExecStop=/usr/bin/sercomc -l %I close

Таким образом, каждый раз, когда устройство добавляется или удаляется из USB-концентратора, соответствующая клиентская команда запускается из systemd. Добавлением

    Requires=sercomd.service
    After=sercomd.service

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

person Thilo Schulz    schedule 23.02.2016
comment
Если вы считаете, что ваш вопрос сбивает с толку, отредактируйте свой вопрос, чтобы объяснить. - person Jeffrey Bosboom; 23.02.2016