Uno no necesariamente necesita esto.
Si los C
servicios necesitan esperar S
a estar listos para poder abrir una conexión de socket, entonces uno no necesariamente necesita hacer esto. Por el contrario, uno puede aprovechar la apertura temprana del socket de escucha por parte de los administradores de servicios.
Varios sistemas, incluido el s6 de Laurent Bercot , mi conjunto de herramientas nosh y systemd, tienen formas en las que se puede abrir un socket de escucha desde el principio, lo primero en la configuración del servicio. Todos ellos implican algo más que el programa de servicio que abre los sockets de escucha, y el programa de servicio, cuando se invoca, recibe los sockets de escucha como descriptores de archivo ya abiertos.
Con systemd, específicamente, uno crea una unidad de socket que define el socket de escucha. systemd abre la unidad de socket y la configura para que el subsistema de red del kernel escuche las conexiones; y lo pasa al servicio real como un descriptor de archivo abierto cuando se trata de generar los procesos que manejan las conexiones al socket. (Puede hacer esto de dos maneras, como inetd
podría hacerlo , pero una discusión de los detalles de los servicios Accept=true
versus Accept=false
está más allá del alcance de esta respuesta).
El punto importante es que uno no necesariamente necesita más pedidos que eso. El núcleo agrupa las conexiones del cliente en una cola hasta que se inicializa el programa de servicio y está listo para aceptarlas y hablar con los clientes.
Cuando uno lo hace, los protocolos de preparación son la cosa.
systemd tiene un conjunto de protocolos de preparación que comprende, servicio específico por servicio con la Type=
configuración en la unidad de servicio. El protocolo de preparación particular de interés aquí es el notify
protocolo de preparación. Con él, se le dice a systemd que espere mensajes del servicio, y cuando el servicio está listo, envía un mensaje que señala la preparación. systemd retrasa la activación de los otros servicios hasta que se marca la disponibilidad.
Hacer uso de esto implica dos cosas:
- Modificando el código de
S
modo que llame a algo como la función de Pierre-Yves Ritschard notify_systemd()
o la función de Cameron T Norman notify_socket()
.
- Configuración de la unidad de servicio para el servicio con
Type=notify
y NotifyAccess=main
.
La NotifyAccess=main
restricción (que es la predeterminada) se debe a que systemd necesita saber para ignorar mensajes de programas traviesos (o simplemente defectuosos), porque cualquier proceso en el sistema puede enviar mensajes al socket de notificación de systemd.
Uno usa el código de Pierre-Yves Ritschard o Cameron T Norman de preferencia porque no excluye la posibilidad de tener este mecanismo en UbuntuBSD, Debian FreeBSD, FreeBSD real, TrueOS, OpenBSD, etc. que el código proporcionado por los autores systemd excluye.
Una trampa para evitar es el systemd-notify
programa. Tiene varios problemas importantes, uno de los cuales es que los mensajes enviados con él pueden terminar siendo descartados sin procesar por systemd. El problema más importante en este caso es que no se ejecuta como el proceso "principal" del servicio, por lo que hay que abrir las notificaciones de preparación para el servicio S
a cada proceso en el sistema NotifyAccess=all
.
Otra trampa para evitar es pensar que el forking
protocolo es más simple. No lo es. Hacerlo correctamente implica no bifurcar y salir del padre hasta que (por una cosa) se estén ejecutando todos los subprocesos de trabajo del programa. Esto no coincide con la abrumadora mayoría de los demonios que se bifurcan.
Otras lecturas
systemd.service(5)
,NotifyAccess=all
aceptará mensajes de todos los miembros del grupo de control del servicio , lo que no implica ningún proceso malicioso en el sistema. Esto es lo suficientemente seguro para la mayoría de los casos de uso. Además, su preocupación por la portabilidad a otros sistemas operativos no es relevante para OP, ya que ya estamos aquí en el tema de Systemd.En referencia a la página del manual para
systemd.service(5)
, específicamente la sección sobre Tipo = , cada tipo de servicio tiene una forma diferente para que Systemd determine que está listo para ofrecer funcionalidad a otros servicios:Si
Type=simple
, sus canales de comunicación deben instalarse antes de que se inicie el demonio (por ejemplo, los sockets configurados por systemd, mediante la activación de sockets).Si
Type=forking
, se espera que el proceso principal salga cuando se complete el inicio y se configuren todos los canales de comunicación.Si
Type=dbus
, se espera que el demonio adquiera un nombre en el bus D-Bus, en ese momento systemd procederá a iniciar las unidades de seguimiento.Si
Type=notify
, se espera que el demonio envíe un mensaje de notificación a través desd_notify(3)
o una llamada equivalente cuando haya terminado de iniciarse. systemd procederá a iniciar las unidades de seguimiento después de que se haya enviado este mensaje de notificación.Para la última opción (enviar un mensaje a través de
sd_notify
), puede usar lasystemd-notify
utilidad y recordar concederle accesoNotifyAccess=all
.Dado que tiene control sobre el servicio
S
, puede elegir la mejor opción para su caso de uso, o simplemente la que sea más fácil de implementar.fuente
Me gusta esto:
S.service
Servicio C0.
C1.service
Servicio C9.
Donde / usr / bin / myBinary realiza una llamada sd_notify READY = 1 cuando se completa la inicialización.
Según cómo desee que se comporte la dependencia, puede usar PartOf, Requiere o BindsTo u otros .
fuente