Linux: cómo hacer que un servicio se reinicie automáticamente si rompe

19/11/2020
Artículo original

Este post está patrocinado por Eduardo Diaz Comellas de la empresa Ultreia Comunicaciones, especializados en administración de sistemas UNIX/Linux, comunicaciones e infraestructuras TIC. Eduardo ha donado 50€ para el banco de alimentos en mi iniciativa "¿Te he ayudado? Ayúdame a ayudar a otros". ¡Muchas gracias Eduardo! ¿Y tú, a qué esperas para echar un cable?

Logo de SystemDMuchos de los servicios que se instalan en Linux vienen configurados para reiniciarse automáticamente en caso de fallo. Sin embargo, en muchas otras ocasiones esto no es así y, si el servicio falla, queda detenido y por lo tanto deja de funcionar hasta que lo levantamos "a mano".

Podemos lograr que si un servicio rompe por algún motivo (y de vez en cuando lo hará) que se reinicie automáticamente cuando ocurra. De este modo aseguramos la continuidad del servicio.

Vamos a ver cómo hacerlo en sistemas Linux que utilizan systemd (Ubuntu, openSUSE, CentOS, Debian, Fedora, Mint...).

systemd es un proceso que incorporan muchos Linux modernos, que sustituye al antiguo init.d y que se ocupa de arrancar, detener y habilitar/deshabilitar servicios, teniendo en cuenta dependencias, programaciones temporales y logging.

Lo primero es localizar el archivo .service que gobierna el funcionamiento del servicio en cuestión.

Para ello debemos buscar el archivo nombre-servicio.service (siendo nombre-servicio el nombre del servicio que nos interesa, obviamente) en la carpeta /etc/systemd/system/multi-user.target.wants (la parte multi-user se refiere a que son servicios que se reinician al llegar al runlevel 2).

Este archivo es el que vamos a editar.

Nota 1: Si el servicio está habilitado y gestionado por systemd tiene que estar ahí. Si no estuviera, quizá es que el servicio no se encuentra activado, por lo que podríamos activarlo usando sudo systemctl enable nombre-servicio.service.

Nota 2: Este archivo, en realidad, es un symlink (enlace simbólico) que apunta a /lib/systemd/system/nombre-sericio.service así que, si queremos, podemos editar este último, pues son el mismo archivo.

La mera existencia de este archivo consigue que el servicio se reinicie automáticamente tras un reinicio del sistema, así que si no lo tenemos ahí tenemos un problema también en este caso.

Si queremos que el servicio se reinicie tras haber "cascado" por algún motivo, podemos editar ese archivo (con el editor nano por ejemplo o editándolo en local y subiéndolo por SSH, yo uso WinSCP al contectarme desde Windows). Se trata de un archivo de texto plano con secciones y parejas de clave/valor.

Una vez abierto, buscamos el apartado [Service] y vemos si tiene una propiedad Restart establecida o no. Para que el servicio se reinicie solo debemos establecerla así:

[Service]
Restart=on-failure
RestartSec=3

Con esto lo que conseguimos es que, si "rompe", se esperen 3 segundos (RestartSec) y acto seguido se vuelva a lanzar automáticamente. Los valores posibles los tienes aquí.

Si el servicio tuviese un problema muy gordo y rompiese todo el rato, se podría iniciar un bucle tonto de reinicios que no lleva a nada (porque se reinicia y vuelve a romper, y así todo el tiempo). Por ello, es una buena idea limitar el número máximo de reinicios seguidos para evitar este tipo de situaciones.

Para lograrlo, dentro del mismo archivo debemos buscar la sección [Unit], generalmente la primera, y añadir estos dos valores:

StartLimitIntervalSec=60
StartLimitBurst=5

Con esto lograremos que si el servicio se reinicia más de 5 veces (StartLimitBurst) en 60 segundos (StartLimitIntervalSec) , no lo siga intentando, ya que claramente algo grave está pasando.

Una vez tocado y guardado ese archivo es buena idea forzar que se recargue el servicio:

sudo systemctl daemon-reload
sudo systemctl restart nombre-servicio.service

de modo que se apliquen los nuevos cambios.

Puedes probar si funciona bien el reinicio localizando el proceso y matándolo. Podemos buscar su proceso y matarlo:

ps -ef | grep nombre-servicio

Que nos dará su información y obtendremos su identificador de proceso. Ahora lo podemos "matar" con:

sudo kill-9 idProcesoServicio

siendo idProcesoServicio el identificador obtenido en el paso anterior.

Al cabo de unos segundos (3 que le hemos configurado más lo que tarde en levantarse) deberíamos ver de nuevo el servicio en marcha, ya que systemd lo levantará de nuevo.

¡Espero que te sea util!