Запуск сетевых служб через systemd

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

  1. Файл, описывающий сокет, на котором ожидается соединение;
  2. Файл, описывающий сервис - программу, которую надо запустить после подключения клиента к сокету.

В файле сокета ListenStream - указывает на протокол TCP (для UDP используется параметр ListenDatagram=). В качестве значения ListenStream может быть указан номер порта или пара IP:Port. Параметр Accept=yes указывает на то, что для каждого подключения надо стартовать отдельный экземпляр программы. Чтобы проинформировать приложение о свойствах соединения, ему передаются переменные окружения REMOTE_ADDR и REMOTE_PORT.

/etc/systemd/system/baz.socket:

[Unit]
Description=Baz Socket

[Socket]
ListenStream=127.0.0.1:9999
Accept=yes

[Install]
WantedBy=sockets.target

Имя файла сервиса должно заканчиваться на @, чтобы указать, что одновременно может быть запущено много экземпляров данной программы. В данной конфигурации стандартный ввод программы будет назначен на /dev/null, стандартный вывод будет перенаправлен в сокет, сообщения об ошибках будут сохранены в логах journald. Программа может быть написана на чем угодно. Переменным окружения VAR1 и VAR2 будут назначены значения "word1 word2" и 'word3" соответственно, текущий каталог будет изменен на /tmp, вместо %i будет подставлено имя экземпляра программы, которое также будет видно в списке запущенных сервисов между @ и .service.

/etc/systemd/system/baz@.service:

[Unit]
Description=Baz Service
Requires=baz.socket

[Service]
Type=simple
Environment="VAR1=word1 word2" VAR2=word3
ExecStart=/usr/local/baz %i
WorkingDirectory=/tmp
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

/usr/local/bin/baz:

#!/bin/bash
pwd
echo ${VAR1}
echo ${VAR2}
echo $1