Come creare un servizio systemd virtuale per arrestare / avviare più istanze insieme?


12

Ho intenzione di ospitare diverse istanze della stessa app Web per i clienti che utilizzano systemd. Vorrei essere in grado di stope startogni istanza cliente utilizzando systemd, così come trattare l'intera collezione di istanze dei clienti come un unico servizio che può essere interrotto e avviato insieme.

systemdsembra fornire gli elementi costitutivi di cui ho bisogno PartOfe i file di unità modello, ma ho smesso il servizio padre, il servizio clienti figlio non è stato arrestato. Come posso farlo funzionare con systemd? Ecco cosa ho finora.

Il file unità genitore, 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

Un file modello unità denominato app@.service, utilizzato per creare istanze del cliente:

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

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

Il mio app-poc.shscript (Proof of concept che stampa solo nel file di registro in un ciclo):

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

Per la dimostrazione del concetto, ho i file di unità systemd ~/.config/systemd/user.

Quindi avvio il genitore e un'istanza in base al modello (dopo systemctl --user daemon-reload):

systemctl --user start app
systemctl --user start app@customer.service

Dall'uso journalctl -fvedo che entrambi sono stati avviati e che l'istanza del cliente continua a essere eseguita. Ora mi aspetto che lo spegnimento del genitore fermerà il bambino (perché l'ho usato PartOf), ma non lo fa. Inoltre, l'avvio del genitore non sta nemmeno avviando il figlio come previsto.

systemctl --user stop app

Grazie!

(Sto usando Ubuntu 16.04 con systemd 229).


1
"PartOf = Configura dipendenze simili a Richiede =, ma limitato all'arresto e al riavvio delle unità." Se vuoi iniziare a lavorare, non devi usare Requires=invece?
sourcejedi,

Risposte:


10

Devi spostare la linea

PartOf=app.service

fuori [Service]e dentro la [Unit]sezione e aggiungere alla [Unit]del app.servicel'elenco dei clienti per iniziare, ad esempio,

Wants=app@customer1.service app@customer2.service

o come ha detto sourcejedi nei commenti, Requires=la stessa cosa. Puoi mantenere il PartOfper interrompere i servizi che avvii a mano che non sono nell'elenco sopra, come systemctl --user start app@customer3.service.


Ho confermato che avevi ragione PartOf. Grazie. Ho intenzione di gestire i "Wants" tramite un collegamento simbolico, che diventa l'unica azione che devo intraprendere per attivare un nuovo cliente con systemd. Per il mio caso di prova: `ln -s /home/mark/.config/systemd/user/app@.service / home / mark / .config / systemd / user / app.service.wants / unity @ foo.service`
Mark Stosberg,

13

Ho imparato che questo è ciò che Systemd "Target Units" sono per. Usando un'unità target, ottengo i benefici che desidero senza dover creare la [Service]sezione falsa che ho avuto sopra. Un file di lavoro "Target Unit" di esempio è simile al seguente:

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

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

Quindi ogni istanza cliente deve includere PartOfnella [Unit]sezione (come fuori punte da @meuh), e deve anche avere una [Install]sezione in modo che enablee disablelavorerà sul servizio specifico:

# In a file name like app@.service
[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

Per visualizzare l'istanza del cliente e avviarla all'avvio della destinazione, viene utilizzato questo comando di abilitazione singolo:

 systemctl enable app

Ora a questo punto posso usare stope startpassare app@customera per un'istanza specifica, oppure posso usare start appe stop appfermare tutte le app insieme.


Che ne dici di stato? Non riesco a trovare un modo semplice per ottenere lo stato di tutti i servizi desiderati dall'App. So come posso
scriverlo

1
Voglio dire come ottenere lo stato delle app in quel gruppo target senza elencare tutto ciò che ne fa parte, caratteri jolly o meno, preferibilmente usando quel nome di gruppo e senza nemmeno preoccuparsi di cosa sia fatto.
Tommi Kyntola,

2
Non è così semplice. A quale pacchetto appartiene quello script? Dovrebbe essere modificato ogni volta che viene aggiunto un nuovo componente. Dimenticalo e l'implementazione / manutenzione va in tilt. Quello che vorrei ovviamente è solo aggiungere un nuovo pacchetto con l'impostazione partOf che indica la sua presenza in quel gruppo e non modificare alcuni script che persistono. E poi fermarsi e iniziare quell'obiettivo funziona come prima. Funziona, ma lo stato sembra non rientrare in tale ambito. Non riesco nemmeno a trovare un modo per ottenere un elenco di unità che sono presenti in fase di esecuzione in una destinazione. Questo caso d'uso non è coperto da systemd.
Tommi Kyntola,

2
@TommiKyntola Ecco un one-liner bash che non è necessario aggiornare quando cambiano le dipendenze target:systemctl status $(systemctl list-dependencies --plain otp.target)
Mark Stosberg

2
@TommiKyntola Sono d'accordo che systemdpotrebbe migliorare l'usabilità qui. Ho aperto una richiesta di funzionalità per suggerire uno stato migliorato per gli obiettivi.
Mark Stosberg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.