Назад | Перейти на главную страницу

Может ли systemd управлять конвейером?

Может ли systemd управлять конвейером аналогично тому, как это делает семейство daemontools? И если да, то как лучше всего этого добиться?

Я хочу запустить эквивалент service1 | service2 где оба service1 и service2 являются (отдельными или нет) службами, управляемыми systemd.

Я хотел бы перезапустить service2 процесс без прерывания service1. Другими словами, дескриптор файла, к которому service1 пишет, нельзя закрывать, когда service2 выходы. Когда новый экземпляр service2 запускается, он должен наследовать существующий дескриптор файла, чтобы stdout из service1 потечет в новый service2. (Подобно тому, как daemontools поддерживает канал между run и log/run, хотя конвейер не обязательно должен быть службой и регистратором.)

Возможно, что-то с управляемым системой FIFO между ними?

Наконец-то появилась возможность и необходимость самому проработать это. Мое решение требует поддержки fd возможность StandardOutput=, который доступен (как минимум) в systemd версии 232, но не доступен в версии 215.

Есть три сервиса и два FIFO. Вместе они создают трубопровод input | filter | output, и любая часть конвейера может быть индивидуально перезапущена без потери данных.

В input процесс записывает в FIFO, из которого filter читает, который, в свою очередь, записывает в FIFO, который output читает.

input.service

[Unit]
Description=The input process
Requires=filter.socket
After=filter.socket

Wants=filter.service output.service

[Service]
TimeoutStartSec=infinity

Sockets=filter.socket

StandardInput=null
StandardOutput=fd:filter.socket
StandardError=journal
ExecStart=/path/to/input

Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target

filter.service

[Unit]
Description=The filter process
Requires=filter.socket output.socket
After=filter.socket output.socket

[Service]
TimeoutStartSec=infinity

Sockets=filter.socket
Sockets=output.socket

StandardInput=fd:filter.socket
StandardOutput=fd:output.socket
StandardError=journal
ExecStart=/path/to/filter

Restart=always
RestartSec=5s

filter.socket

[Unit]
Description=Filter process reads from this

[Socket]
ListenFIFO=/run/filter
SocketMode=0600
RemoveOnStop=false

output.service

[Unit]
Description=The output process
Requires=output.socket
After=output.socket

[Service]
TimeoutStartSec=infinity

Sockets=output.socket

StandardInput=fd:output.socket
StandardOutput=journal
StandardError=journal
ExecStart=output

Restart=always
RestartSec=5s

output.socket

[Unit]
Description=Output process reads from this

[Socket]
ListenFIFO=/run/output
SocketMode=0600
RemoveOnStop=false

Попросите службу записать в стандартный вывод и настройте StandardOutput в файле модуля systemd, чтобы служба записывала в журнал:

http://0pointer.de/public/systemd-man/systemd.exec.html

Это делает журналы доступными для службы journald, которая предлагает другие варианты использования журналов.

http://0pointer.de/public/systemd-man/journald.conf.html

Настраиваемый «регистратор» может быть клиентом журнала и может напрямую извлекать из журнала, и, если он недоступен, вышестоящая служба, конечно, не пострадает. Регистратор также может быть настроен с собственным файлом модуля, поэтому им управляет systemd.