Can systemd manage a pipeline similar to how the daemontools family does it? And if so, what's the best way to achieve this?
I want to run the equivalent of service1 | service2
where both service1
and service2
are (separate or not) services managed by systemd.
I would like to be able to restart the service2
process without interrupting service1
. In other words, the file descriptor to which service1
is writing must not be closed when service2
exits. When a new instance of service2
starts, it should inherit the existing file descriptor so that stdout from service1
will flow into the new service2
. (Much like daemontools maintains a pipe between run
and log/run
, though the pipeline need not be a service and a logger.)
Perhaps something with a systemd-managed FIFO in between?
Наконец-то у меня появилась возможность и необходимость пройти через это самостоятельно. Мое решение требует поддержки опции fd
к StandardOutput=
, которая доступна в (как минимум) systemd версии 232, но не в версии 215.
Есть три сервиса и два FIFO. Вместе они создают поток -вход | -фильтр | -выход
, и любая часть потока может быть перезапущена по отдельности без потери данных.
-вход -вход
записывает в FIFO, из которого считывается -фильтр
, который, в свою очередь, записывает в FIFO, из которого считывается -выход
.
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
Пользовательский «регистратор» может быть клиентом journald и может напрямую извлекать из журнала, а если недоступно, из восходящего потока сервис конечно не влияет.Регистратор также может быть настроен с его собственным файлом модуля, поэтому им управляет systemd.