¿Cómo enviar un correo electrónico si se reinicia un servicio systemd?

8

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?

Greg
fuente
2
No sé cómo hacerlo con systemd, pero con monit puede hacer que vea un proceso y puede enviar una notificación si cambia la identificación del proceso.
Zoredache

Respuestas:

16

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 .serviceque creamos pasará estos argumentos:

/etc/systemd/system/[email protected]:

[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 [email protected]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.servicea la [Unit]sección. %npasa el nombre de la unidad a la plantilla.

Fuente: archlinux wiki: systemd timers MAILTO

gf_
fuente
Pero @Dave no requiere otro servicio. Quiere que el servicio que ya usa pueda enviar correo en cada inicio / reinicio. Para eso, existe la opción ExecStartPost.
Jaroslav Kucera
@JaroslavKucera Creo que esto lo decidirá hasta el OP ... :) Además, no estoy seguro de si ExecStartPostes la opción correcta: también se dispararía después de un inicio "normal", no solo en caso de falla, correcto ?
gf_
Me interesa por qué este voto se rechaza. ¡Por favor, alce sus voces y hable!
gf_
Porque la pregunta no es sobre otro servicio, sino la modificación del servicio existente. Sí, ExecStartPost activaría el envío de correo incluso en el inicio normal. No conozco nada que funcione solo en el reinicio.
Jaroslav Kucera
@JaroslavKucera Bueno, parece que el OP no está de acuerdo, pero por supuesto, mantén tu opinión.
gf_
2

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-failureen 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 ExecStopPostpara 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_RESULTes una variable de entorno suministrada por systemd al proceso de destino de ExecStopPost. Al verificar un successresultado, 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:

  1. /superuser/1360346/how-to-send-an-email-alert-when-a-linux-service-has-stopped
  2. /unix/422933/confusing-systemd-behaviour-with-onfailure-and-restart
  3. /unix/197636/run-an-arbitrary-command-when-a-service-fails
Antony Nguyen
fuente
-1

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

/ubuntu/814/how-to-run-scripts-on-start-up

billcyz
fuente
1
Esta pregunta no trata sobre el arranque, sino sobre el reinicio de un servicio, que puede ocurrir bastante tiempo después del arranque. Por lo tanto, no estoy seguro si su respuesta es de alguna ayuda.
gf_