Estoy escribiendo systemd
archivos unitarios para OSSEC HIDS. El problema es que cuando systemd
inicia los servicios, los detiene inmediatamente.
Cuando uso el siguiente ExecStart
directiva todo funciona bien.
ExecStart=/var/ossec/bin/ossec-control start
Pero cuando hago esto después de una pequeña mejora, encuentro en los registros OSSEC que recibe SIG 15
después del inicio.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Si hago otro pequeño cambio, el servicio recibirá SIG 15
después de 20 segundos.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
Entonces, supongo que systemd
mata a /bin/sh
proceso después del inicio del servicio, y /bin/sh
luego mata a OSSEC
.
¿Cómo puedo solucionar este problema?
Respuesta aceptada:
discordancia del protocolo de preparación
Como insinuó Wieland, el Type
del servicio es importante. Esa configuración indica qué protocolo de preparación systemd espera que el servicio hable. Un simple
se supone que el servicio está listo inmediatamente. Una forking
Se considera que el servicio está listo después de que su proceso inicial bifurca a un niño y luego sale. Un dbus
se considera que el servicio está listo cuando aparece un servidor en el Desktop Bus. Y así sucesivamente.
Si no obtiene el protocolo de preparación declarado en la unidad de servicio para que coincida con lo que hace el servicio, entonces las cosas salen mal. Las discrepancias en el protocolo de preparación hacen que los servicios no se inicien correctamente o (más generalmente) que systemd diagnostique (erróneamente) que fallan. Cuando se considera que un servicio no se inicia, systemd garantiza que todos los procesos adicionales huérfanos del servicio que podría haberse dejado en ejecución como parte de la falla (desde su punto de vista) se cancela para que el servicio vuelva correctamente al estado inactivo.
Estás haciendo exactamente esto.
En primer lugar, las cosas simples:sh -c
no coincide con Type=simple
o Type=forking
.
En el simple
protocolo, el proceso inicial se lleva a be el proceso de servicio. Pero de hecho un sh -c
wrapper ejecuta el programa de servicio real como un proceso secundario . Entonces MAINPID
sale mal y ExecReload
deja de funcionar, para empezar. Al usar Type=simple
, uno debe usar sh -c 'exec …'
o no usar sh -c
en primer lugar. Este último es más a menudo el curso correcto de lo que algunas personas piensan.
sh -c
no coincide con Type=forking
o. El protocolo de preparación para un forking
El servicio es bastante específico. El proceso inicial tiene que bifurcar a un niño y luego salir. systemd aplica un tiempo de espera a este protocolo. Si el proceso inicial no se bifurca dentro del tiempo asignado, es un fracaso para estar listo. Si el proceso inicial no finaliza dentro del tiempo asignado, eso también es una falla.
el horror innecesario que es ossec-control
Lo que nos lleva a las cosas complejas:ese ossec-control
guión.
Resulta que es un System 5 rc
script que se bifurca entre 4 y 10 procesos, que a su vez también se bifurcan y salen. Es uno de esos System 5 rc
scripts que intentan administrar un conjunto completo de procesos de servidor en un solo script, con for
bucles, condiciones de carrera, sleep
arbitrario s para tratar de evitarlos, los modos de falla que pueden ahogar el sistema en un estado medio iniciado y todos los demás horrores que hicieron que la gente inventara cosas como el controlador de recursos del sistema AIX y los daemontools hace dos décadas. Y no olvidemos el script de shell oculto en un directorio binario que reescribe sobre la marcha, para implementar enable
idiosincrásico y disable
verbos.
Así que cuando /bin/sh -c '/var/ossec/bin/ossec-control start'
lo que pasa es que:
- systemd bifurca lo que espera que sea el proceso de servicio.
- Ese es el caparazón, que bifurca
ossec-control
. - Eso a su vez da entre 4 y 10 nietos.
- Todos los nietos se bifurcan y salen por turnos.
- Todos los bisnietos se bifurcan y salen en paralelo.
ossec-control
salidas.- El primer caparazón sale.
- Los procesos de servicio fueron los gran-gran- nietos, sino porque esta forma de trabajar no la
forking
ni elsimple
protocolo de preparación, systemd considera que el servicio como un todo ha fallado y lo vuelve a apagar.
Nada de este horror es realmente necesario bajo systemd en absoluto. Nada de eso.
una unidad de servicio de plantilla systemd
En cambio, uno escribe una unidad de plantilla muy simple :
[Unit] Description=The OSSEC HIDS %i server After=network.target [Service] Type=simple ExecStartPre=/usr/bin/env /var/ossec/bin/%p-%i -t ExecStart=/usr/bin/env /var/ossec/bin/%p-%i -f [Install] WantedBy=multi-user.target
Guárdelo como /etc/systemd/system/[email protected]
.
Los diversos servicios reales son instancias de esta plantilla, denominada:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Luego, habilitar y deshabilitar la función viene directamente del sistema de administración de servicios (con el error 752774 de RedHat solucionado), sin necesidad de scripts de shell ocultos.
systemctl enable [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
Además, systemd conoce y realiza un seguimiento de cada servicio real directamente. Puede filtrar sus registros con journalctl -u
. Puede saber cuándo un servicio individual ha fallado. Sabe qué servicios se supone que deben estar habilitados y en ejecución.
Por cierto:Type=simple
y el -f
opciones son tan correctas aquí como lo son en muchos otros casos. Muy pocos servicios en la naturaleza realmente señalan su preparación a fuerza de exit
, y estos de aquí tampoco son tales casos. Pero de eso se trata la forking
tipo significa. Los servicios en la naturaleza en general simplemente se bifurcan y salen debido a una noción de sabiduría recibida errónea de que eso es lo que se supone que deben hacer los demonios. De hecho, no lo es. No lo ha sido desde la década de 1990. Es hora de ponerse al día.
Lecturas adicionales
- Jonathan de Boyne Pollard (2015). Problemas de protocolo de preparación con demonios Unix . Respuestas frecuentes.