
Pretendo hospedar várias instâncias do mesmo aplicativo Web para clientes que usam o systemd
. Eu gostaria de poder stop
usar start
cada 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.
systemd
parece fornecer os blocos de construção que preciso usar PartOf
e 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.sh
script (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 -f
posso 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 PartOf
na [Unit]
seção (conforme apontado por @meuh), e também deve ter uma [Install]
seção para que enable
funcione disable
no 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 stop
e start
para app@customer
uma instância específica ou posso usar start app
e stop app
para 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.service
de 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 PartOf
serviços para parar que você inicia manualmente e que não estão na lista acima, como .systemctl --user start [email protected]