Como criar um serviço systemd virtual para parar/iniciar várias instâncias juntas?

Como criar um serviço systemd virtual para parar/iniciar várias instâncias juntas?

Pretendo hospedar várias instâncias do mesmo aplicativo Web para clientes que usam o systemd. Eu gostaria de poder stopusar startcada instância do cliente systemd, além de tratar toda a coleção de instâncias do cliente como um único serviço que pode ser interrompido e iniciado em conjunto.

systemdparece fornecer os blocos de construção que preciso usar PartOfe arquivos de unidade de modelo, mas quando interrompo o serviço pai, o atendimento ao cliente filho não é interrompido. Como posso fazer isso funcionar com o systemd? Aqui está o que tenho até agora.

O arquivo da unidade pai 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

Um arquivo de modelo de unidade chamado [email protected], usado para criar instâncias de clientes:

[Unit]
Description=%I Instance of App Web Service

[Service]
PartOf=app.service
ExecStart=/home/mark/bin/app-poc.sh %i
StandardOutput=journal

Meu app-poc.shscript (prova de conceito que apenas imprime no arquivo de log em um loop):

#!/bin/bash
# Just a temporary code to fake a full daemon.
while :
do
  echo "The App PoC loop for $@"
  sleep 2;
done

Para prova de conceito, coloquei os arquivos da unidade do systemd no formato ~/.config/systemd/user.

Em seguida, inicio o pai e uma instância com base no modelo (depois systemctl --user daemon-reload):

systemctl --user start app
systemctl --user start [email protected]

Ao usar, journalctl -fposso ver que ambos foram iniciados e que a instância do cliente continua em execução. Agora, espero que desligar o pai pare o filho (porque eu useiPartOf), mas isso não acontece. Além disso, iniciar o pai também não é iniciar o filho como esperado.

systemctl --user stop app

Obrigado!

(Estou usando o Ubuntu 16.04 com systemd 229).

Responder1

Eu aprendi que é para isso que servem as "Unidades de destino" do systemd. Ao usar uma Unidade Alvo, obtenho os benefícios que desejo sem precisar criar a [Service]seção falsa que criei acima. Um exemplo funcional de arquivo "Target Unit" se parece com este:

# named like app.target
[Unit]
Description=App Web Service

# This collection of apps should be started at boot time.
[Install]
WantedBy=multi-user.target

Então cada instância do cliente deve incluir PartOfna [Unit]seção (conforme apontado por @meuh), e também deve ter uma [Install]seção para que enablefuncione disableno serviço específico:

# 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

Para abrir a instância do cliente e iniciá-la quando o destino for iniciado, este comando único de ativação é usado:

 systemctl enable app

Agora, neste ponto, posso usar stope startpara app@customeruma instância específica ou posso usar start appe stop apppara interromper todos os aplicativos juntos.

Responder2

Você precisa mover a linha

PartOf=app.service

fora [Service]e dentro da [Unit]seção e adicione à [Unit]lista app.servicede clientes para começar, por exemplo

[email protected] [email protected]

ou como sourcejedi disse nos comentários, Requires=a mesma coisa. Você pode manter os PartOfserviços para parar que você inicia manualmente e que não estão na lista acima, como .systemctl --user start [email protected]

informação relacionada