Estoy escribiendo el archivo de unidad systemd para OSSEC HIDS. El problema es que cuando systemd inicia el servicio, los detiene inmediatamente.
Cuando uso esa directiva ExecStart todo funciona bien.
ExecStart=/var/ossec/bin/ossec-control start
Pero cuando hago una pequeña mejora, estoy bien en los registros de OSSEC, que recibe SIG 15 después del inicio.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Si hago otro cambio pequeño, 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 / bin / sh proceso después del inicio del servicio, y bin / sh luego mata a OSSEC.
¿Como puedó resolver esté problema?
Respuestas:
falta de coincidencia del protocolo de preparación
Como Wieland implicó,
Type
la prestación del servicio es importante. Esa configuración indica qué protocolo de preparación systemd espera que el servicio hable. Sesimple
supone que un servicio está listo de inmediato. Se consideraforking
que un servicio está listo después de que su proceso inicial bifurca a un niño y luego se cierra. Se consideradbus
que un servicio está listo cuando aparece un servidor en el Bus de escritorio. Etcétera.Si no logra que el protocolo de preparación declarado en la unidad de servicio coincida con lo que hace el servicio, entonces las cosas salen mal. Los desajustes del protocolo de preparación hacen que los servicios no se inicien correctamente o (más comúnmente) sean diagnosticados (erróneamente) por systemd como fallidos. Cuando se considera que un servicio no puede iniciar systemd, se garantiza que todos los procesos adicionales huérfanos del servicio que podrían haberse dejado como parte de la falla (desde su punto de vista) se eliminan para que el servicio vuelva correctamente al estado inactivo. estado.
Estás haciendo exactamente esto.
En primer lugar, las cosas simples:
sh -c
no coincideType=simple
oType=forking
.En el
simple
protocolo, el proceso inicial se toma para ser el proceso de servicio. Pero, de hecho, unsh -c
contenedor ejecuta el programa de servicio real como un proceso secundario . EntoncesMAINPID
sale mal yExecReload
deja de funcionar, para empezar. Cuando se usaType=simple
, uno debe usarsh -c 'exec …'
o no usarsh -c
en primer lugar. Este último es más a menudo el curso correcto de lo que algunas personas piensan.sh -c
tampoco coincideType=forking
. El protocolo de preparación para unforking
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 estar listo. Si el proceso inicial no sale dentro del tiempo asignado, eso también es un fracaso.el horror innecesario que es
ossec-control
Lo que nos lleva a las cosas complejas: ese
ossec-control
guión.Resulta que es un
rc
script del Sistema 5 que desvía entre 4 y 10 procesos, que a su vez se bifurcan y salen también. Es uno de esosrc
scripts del Sistema 5 que intenta administrar un conjunto completo de procesos del servidor en un solo script, confor
bucles, condiciones de carrera,sleep
s arbitrarios para tratar de evitarlos, modos de falla que pueden ahogar el sistema en un estado medio iniciado, y todos los otros horrores que hicieron que las personas inventaran cosas como el Controlador de recursos del sistema AIX y las herramientas demoníacas hace dos décadas. Y no olvidemos el script de shell oculto en un directorio binario que reescribe sobre la marcha, para implementar idiosincrásicosenable
ydisable
verbos.Entonces, cuando lo
/bin/sh -c '/var/ossec/bin/ossec-control start'
que sucede es que:ossec-control
.ossec-control
salidasforking
ni elsimple
protocolo de preparación, systemd considera el servicio como un todo para han fracasado y se cierra de nuevo hacia abajo.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 :
Guarda esto como
/etc/systemd/system/[email protected]
.Los diversos servicios reales son instancias de esta plantilla, llamada:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Luego, la función de habilitar y deshabilitar viene directamente del sistema de administración de servicios (con el error RedHat 752774 corregido), sin necesidad de scripts de shell ocultos.
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 están habilitados y en ejecución.Por cierto:
Type=simple
y la-f
opción es tan correcta aquí como en muchos otros casos. Muy pocos servicios en la naturaleza en realidad señalan su preparación a fuerza deexit
, y estos tampoco son tales casos. Pero eso es lo queforking
significa el tipo. Los servicios en la naturaleza en general solo se bifurcan y salen debido a una noción errónea de sabiduría recibida de que eso es lo que se supone que deben hacer los demonios. De hecho, no lo es. No ha sido desde la década de 1990. Es hora de ponerse al día.Otras lecturas
fuente
Requires=
todas las instancias necesarias, y luego establecerPartOf=ossec.target
en ossec @ .service. Esto permitirá iniciar y detener ossec iniciando y deteniendo ossec.target.Mantenga Type = forking y proporcione una ubicación de archivo pid si el servicio / aplicación de inicio mantiene cualquier pid.
[Unidad]
Descripción = "Ejecutar aplicación en el arranque"
Después = network.target syslog.target auditd.service
[Servicio]
Tipo = bifurcación
PIDFile = / var / run / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 iniciar
ExecStop = / etc / init.d / apache2 detener
StandardOutput = syslog
StandardError = syslog
Reiniciar = en caso de falla
SyslogIdentifier = webappslog
[Instalar]
WantedBy = multi-user.target
Alias = webapps
fuente
Algo relacionado, tenía un servicio systemd que parecía que systemd lo "mataría" después de los 30 años.
systemctl status service-name
apareceríamain process exited, code=exited, status=1/FAILURE
después de que hubieran transcurrido 30 años.Funcionaría bien "de forma aislada" (como manualmente en la terminal con el mismo entorno ).
Resulta que era
dentro
my_script_to_spawn_process.sh
estaba haciendo/bin/something > /dev/null 2>&1 &
que funciona pero estaba descartando información de registro de salida (normalmente va a un archivo, o, si no es eso, posiblemente
journalctl
).Cambiarlo para iniciar sesión en otro lugar como
/bin/something > /tmp/my_file
luego siguiendo la
/tmp/my_file
revelada la causa real. Lo que era (tangencialmente) que no puede usar la sintaxisEnvironment=ABC="true"
como puede hacerlo en bash, no tiene que ser comillas o el valor clave, todo dentro de comillas, como loEnvironment="ABC=true"
que estaba causando que mi proceso salga "en su fase de configuración" después de unos 30 años.fuente
Tenga en cuenta que el modelo de daemon de systemd es simplista e incompatible con muchos daemons existentes que realizan múltiples bifurcaciones, ejecuciones y ajustes. Los más comunes son los demonios que comienzan como root para configurar las cosas y luego cambian a un UID menos privilegiado para la operación de rutina. por ejemplo, la inicialización del archivo Pid es una cosa que falla en systemd debido a problemas de privilegios. Hay soluciones (no arreglos) pero está mal documentado.
La explicación de JdeBP es bienvenida pero incompleta y su afirmación de que todo es culpa del control de Ossec simplemente no es cierta. Incluso cosas bastante triviales son problemáticas, por ejemplo, obtener líneas de registro no truncadas para depurar problemas o mensajes de error significativos del propio sistema cuando mata procesos.
fuente