
Я планирую разместить несколько экземпляров одного и того же веб-приложения для клиентов, использующих systemd
. Я хотел бы иметь возможность stop
и start
каждый экземпляр клиента, использующий systemd
, а также обрабатывать всю коллекцию экземпляров клиентов как единую службу, которую можно останавливать и запускать вместе.
systemd
кажется, предоставляет необходимые мне строительные блоки с использованием PartOf
, и файлов шаблонов единиц, но пошел я останавливаю родительскую службу, дочерняя служба клиентов не останавливается. Как мне заставить это работать с systemd? Вот что у меня есть на данный момент.
Файл родительского блока app.service
:
[Unit]
Description=App Web Service
[Service]
# Don't run as a deamon (because we've got nothing to do directly)
Type=oneshot
# Just print something, because ExecStart is required
ExecStart=/bin/echo "App Service exists only to collectively start and stop App instances"
# Keep running after Exit start finished, because we want the instances that depend on this to keep running
RemainAfterExit=yes
StandardOutput=journal
Файл шаблона блока с именем [email protected]
, используемый для создания экземпляров клиентов:
[Unit]
Description=%I Instance of App Web Service
[Service]
PartOf=app.service
ExecStart=/home/mark/bin/app-poc.sh %i
StandardOutput=journal
Мой app-poc.sh
скрипт (доказательство концепции, который просто печатает в файл журнала в цикле):
#!/bin/bash
# Just a temporary code to fake a full daemon.
while :
do
echo "The App PoC loop for $@"
sleep 2;
done
Для подтверждения концепции у меня есть файлы модулей systemd в формате ~/.config/systemd/user
.
Затем я запускаю родительский объект и экземпляр на основе шаблона (после systemctl --user daemon-reload
):
systemctl --user start app
systemctl --user start [email protected]
Из использования journalctl -f
я вижу, что оба запущены и что экземпляр клиента продолжает работать. Теперь я ожидаю, что выключение родителя остановит потомка (потому что я использовалPartOf
), но этого не происходит. Кроме того, запуск родителя также не запускает потомка, как ожидается.
systemctl --user stop app
Спасибо!
(Я использую Ubuntu 16.04 с systemd 229).
решение1
Я узнал, что для этого нужны systemd "Target Units". Используя Target Unit, я получаю желаемые преимущества без необходимости создания поддельного [Service]
раздела, который я привел выше. Рабочий пример файла "Target Unit" выглядит так:
# named like app.target
[Unit]
Description=App Web Service
# This collection of apps should be started at boot time.
[Install]
WantedBy=multi-user.target
Затем каждый экземпляр клиента должен включать PartOf
в себя [Unit]
раздел (как указал @meuh), а также должен иметь [Install]
раздел, который enable
будет disable
работать с определенной службой:
# In a file name like [email protected]
[Unit]
Description=%I Instance of App Web Service
PartOf=app.target
[Service]
ExecStart=/home/mark/bin/app-poc.sh %i
Restart=on-failure
StandardOutput=journal
# When the service runs globally, make it run as a particular user for added security
#User=myapp
#Group=myapp
# When systemctl enable is used, make this start when the App service starts
[Install]
WantedBy=app.target
Чтобы вызвать экземпляр клиента и запустить его при запуске цели, используется эта одноразовая команда включения:
systemctl enable app
Теперь на этом этапе я могу использовать и stop
для конкретного экземпляра или могу использовать и для остановки всех приложений одновременно.start
app@customer
start app
stop app
решение2
Вам нужно переместить линию.
PartOf=app.service
из раздела [Service]
и в [Unit]
раздел, и добавьте в [Unit]
список app.service
клиентов, чтобы начать, например
[email protected] [email protected]
или как сказал sourcejedi в комментариях, Requires=
то же самое. Вы можете сохранить, PartOf
чтобы остановить службы, которые вы запускаете вручную, которые не указаны в списке выше, например .systemctl --user start [email protected]