На сервере Ubuntu 20.04.2 TLS мне нужно запустить службу после того, как другая служба полностью запущена. В частности, служба openvpn-server
создает интерфейс tun0
с IP-адресом 10.87.0.1, к которому затем привязывается служба rinetd
. Поэтому служба rinetd
должна запускаться только после того, как служба openvpn-server
создаст этот интерфейс.
rinetd
поставляется со сценарием службы sysvinit /etc/init.d/rinetd
, говорящим:
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
Это заставляет rinetd
запускаться во время запуска системы до того, как openvpn-server
создал интерфейс. Затем он выдает сообщение журнала:
rinetd[792]: couldn't bind to address 10.87.0.1 port 873 (Cannot assign requested address)
и не принимает соединения, пока я не перезапущу его вручную с помощью sudo systemctl restart rinetd
, после чего он работает нормально.
Согласно sudo systemctl status
серверный процесс openvpn
запускается службой systemd под названием openvpn-server@server.service
.
Расширение строки Required-Start
в /etc/init.d/rinetd
, чтобы сказать:
# Required-Start: $remote_fs $syslog openvpn-server@server
должным образом переводится systemd-sysv-generator
в дополнительную строку
After=openvpn-server@server.service
в /run/systemd/generator.late/rinetd.service
.
Но systemd игнорирует это. rinetd
все еще показывает то же сообщение журнала и сбой, доказывая, что он все еще запущен до того, как openvpn-server
встал.
Как заставить systemd надежно запускать службу rinetd
только после того, как служба openvpn-server
выполнила свою часть работы и создала интерфейс?
Если мы сначала возьмем systemd, я думаю, будет лучше, если вы обратитесь непосредственно к интерфейсу. Устройства в дереве dev и sysfs открыты для systemd и могут быть использованы для создания зависимостей с другими устройствами.
Начните с маскировки исходного сценария запуска.
systemctl mask --now rinetd.service
С помощью инстанцированного .service, например, rinetd-daemon@.service
, вы можете запустить один или несколько экземпляров, если потребуется, чтобы иметь более одного устройства (при условии, что rinetd может связываться с несколькими интерфейсами).
[Unit]
Description=Rinetd connection forwarding service (%I)
After=sys-subsystem-net-devices-%i.device
BindsTo=sys-subsystem-net-devices-%i.device
[Service]
Type=forking
ExecStart=/usr/sbin/rinetd
PIDFile=/var/run/rinetd.pid
ExecReload=kill -HUP $MAINPID
[Install]
WantedBy=sys-subsystem-net-devices-%i.device
Затем вы можете инстанцировать службу вместе с именем устройства:
systemctl enable --now rinetd-daemon@tun0.service
Новый файл .service
, вероятно, нуждается
[Unit]
After=openvpn-server@server.service
Requires=openvpn-server@server.service
Опции могут быть запутанными, но есть тонна других ресурсов, которые охватывают аналогичную тему.