Uno non ha necessariamente bisogno di questo.
Se i C
servizi devono attendere per S
essere pronti in modo che possano aprire una connessione socket ad esso, allora non è necessario farlo affatto. Piuttosto, si può trarre vantaggio dall'apertura anticipata della presa di ascolto da parte dei gestori dei servizi.
Diversi sistemi, tra cui il s6 di Laurent Bercot , il mio set di strumenti nosh e systemd, hanno dei modi in cui una presa di ascolto può essere aperta in anticipo, la prima cosa da fare per impostare il servizio. Tutti implicano qualcosa di diverso dal programma di servizio che apre i socket di ascolto e il programma di servizio, quando viene invocato, riceve i socket di ascolto come descrittori di file già aperti.
Con systemd, in particolare, si crea un'unità socket che definisce la presa di ascolto. systemd apre l'unità socket e la configura in modo che il sottosistema di rete del kernel ascolti le connessioni; e lo passa al servizio effettivo come descrittore di file aperto quando si tratta di spawn i processi che gestiscono le connessioni al socket. (Può farlo in due modi, proprio come inetd
potrebbe, ma una discussione sui dettagli Accept=true
rispetto ai Accept=false
servizi va oltre lo scopo di questa risposta.)
Il punto importante è che non è necessario necessariamente più ordinamento di quello. Il kernel raggruppa le connessioni client in una coda fino a quando il programma di servizio non viene inizializzato e pronto ad accettarle e parlare con i client.
Quando si fa, i protocolli di prontezza sono la cosa.
systemd ha una serie di protocolli di prontezza che comprende, servizio specificato per servizio con l' Type=
impostazione nell'unità di servizio. Il protocollo di prontezza particolare di interesse qui è il notify
protocollo di prontezza. Con esso, viene richiesto a systemd di aspettarsi messaggi dal servizio e quando il servizio è pronto, invia un messaggio che segnala la disponibilità. systemd ritarda l'attivazione degli altri servizi fino a quando la disponibilità non viene contrassegnata.
Fare uso di questo implica due cose:
- Modifica del codice in
S
modo che chiami qualcosa come la funzione di Pierre-Yves Ritschard notify_systemd()
o la funzione di Cameron T. Norman notify_socket()
.
- Impostazione dell'unità di servizio per il servizio con
Type=notify
e NotifyAccess=main
.
La NotifyAccess=main
restrizione (che è l'impostazione predefinita) è perché systemd deve sapere di ignorare i messaggi provenienti da programmi maliziosi (o semplicemente difettosi), poiché qualsiasi processo sul sistema può inviare messaggi al socket di notifica di systemd.
Uno usa il codice di Pierre-Yves Ritschard o Cameron T. Norman come preferenza perché non esclude la possibilità di avere questo meccanismo su UbuntuBSD, Debian FreeBSD, FreeBSD attuale, TrueOS, OpenBSD e così via; che il codice fornito dagli autori di systemd esclude.
Una trappola da evitare è il systemd-notify
programma. Ha diversi problemi importanti, non ultimo il fatto che i messaggi inviati con esso possono finire per essere eliminati non elaborati da systemd. Il problema più importante in questo caso è che non funziona come il processo "principale" del servizio, quindi è necessario aprire le notifiche di disponibilità per il servizio S
a ogni processo sul sistema con NotifyAccess=all
.
Un'altra trappola da evitare è pensare che il forking
protocollo sia più semplice. Non è. Farlo correttamente implica non biforcarsi ed uscire dal genitore fino a quando (per prima cosa) tutti i thread di lavoro del programma sono in esecuzione. Questo non corrisponde a come la stragrande maggioranza dei demoni che si biforcano effettivamente biforcano.
Ulteriori letture
systemd.service(5)
,NotifyAccess=all
accetterà i messaggi di tutti i membri del gruppo di controllo del servizio , il che non implica solo alcun processo canaglia sul sistema. Questo è abbastanza sicuro per la maggior parte dei casi d'uso. Inoltre, la tua preoccupazione per la portabilità ad altri sistemi operativi non è rilevante per OP, poiché qui siamo già sull'argomento Systemd.