Tengo una aplicación crítica que se ejecuta como un servicio por systemd.
Está configurado para reiniciarse tan pronto como haya una falla.
¿Cómo enviar un correo electrónico si la aplicación se reinicia?
Tengo una aplicación crítica que se ejecuta como un servicio por systemd.
Está configurado para reiniciarse tan pronto como haya una falla.
¿Cómo enviar un correo electrónico si la aplicación se reinicia?
Respuestas:
Primero necesita dos archivos: un ejecutable para enviar el correo y un .service para iniciar el ejecutable. Para este ejemplo, el ejecutable es solo un script de shell que utiliza sendmail
:
/usr/local/bin/systemd-email:
#!/bin/bash
/usr/bin/sendmail -t <<ERRMAIL
To: $1
From: systemd <root@$HOSTNAME>
Subject: $2
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=UTF-8
$(systemctl status --full "$2")
ERRMAIL
Cualquiera que sea el ejecutable que use, probablemente debería tomar al menos dos argumentos como lo hace este script de shell: la dirección para enviar y el archivo de la unidad para obtener el estado. El .service
que creamos pasará estos argumentos:
/etc/systemd/system/status-email-user@.service:
[Unit]
Description=status email for %i to user
[Service]
Type=oneshot
ExecStart=/usr/local/bin/systemd-email address %i
User=nobody
Group=systemd-journal
Donde usuario es el usuario que se envía por correo electrónico y la dirección es la dirección de correo electrónico de ese usuario. Aunque el destinatario está codificado, el archivo de la unidad para informar se pasa como un parámetro de instancia, por lo que este servicio puede enviar correos electrónicos para muchas otras unidades. En este punto, puede comenzar status-email-user@dbus.service
a verificar que puede recibir los correos electrónicos.
Luego, simplemente edite el servicio para el que desea recibir correos electrónicos y agréguelo OnFailure=status-email-user@%n.service
a la [Unit]
sección. %n
pasa el nombre de la unidad a la plantilla.
ExecStartPost
es la opción correcta: también se dispararía después de un inicio "normal", no solo en caso de falla, correcto ?
La solución propuesta por @gf_ funcionó bien para nuestra situación ejecutando clickhouse en CentOS7. Clickhouse se bloquea con cierta frecuencia en nosotros, por lo que necesitábamos reiniciarlo automáticamente y recibir una notificación cuando ocurriera el reinicio. Si bien parece un poco complicado agregar un segundo servicio a systemd, esto es necesario debido al diseño de systemd.
Dicho esto, esta solución, cuando se combinó con el reinicio automático, dejó de funcionar para nosotros cuando la implementamos en CentOS8. Esto se debe a que systemd v239 enviado en C8 introdujo un cambio en la OnFailure=
semántica cuando se combina con una configuración no predeterminada de Restart=
( Restart=on-failure
en nuestro caso). El nuevo OnFailure=
comportamiento solo activa el servicio de una sola vez si el reinicio falla por completo, no solo después de un bloqueo. Este comportamiento más reciente reiniciaría felizmente el servicio, pero no recibiríamos el correo electrónico ya que OnFailure=
ya no se invoca.
Tenga en cuenta nuestra expectativa principal: queríamos que systemd reiniciara el proceso Y enviara una notificación por correo electrónico. La actualización v239 hizo que nuestra solución anterior citada por gf_ ya no funcionara. Afortunadamente pudimos hacer que esto funcione.
Nuestra solución es utilizar ExecStopPost
para invocar el script de notificación por correo electrónico. Esto funciona bien, pero ahora surgió un nuevo problema: se envió una notificación por correo electrónico cuando el servicio clickhouse comenzó normalmente, como en el inicio del servidor. Si bien no es un gran problema, idealmente queríamos recibir notificaciones por correo electrónico solo en caso de bloqueo. Pudimos lograr esto agregando el siguiente código a nuestro script de correo electrónico:
# Don't do anything if the service intentionally stopped successfully.
if [ $SERVICE_RESULT == "success" ]; then
exit
fi
... $SERVICE_RESULT
es una variable de entorno suministrada por systemd al proceso de destino de ExecStopPost
. Al verificar un success
resultado, asumimos que esta invocación proviene de un inicio o apagado normal, y no hacemos nada. En cualquier otro valor, como por ejemplo signal
, el script continuaría al enviar un correo electrónico. Los posibles valores de esta variable se indican en la documentación .
Gracias a gf_ por la solución inicial. Espero que la gente encuentre útil mi actualización para CentOS8. Algunos enlaces más que me ayudaron:
Puede intentar utilizar la opción de servicio systemd ExecStartPost.
La descripción está disponible aquí:
https://www.freedesktop.org/software/systemd/man/systemd.service.html
Puede haber más declaraciones de esta opción en el archivo de definición de servicio. Se activa uno por uno.
También tendrá algunos ejemplos en su sistema.
Puede crear un script de shell para verificar el estado del servicio y enviar correos electrónicos mientras se inicia el servidor. Este enlace puede ayudarte