systemd

Iniciar un servicio mediante systemd

En este caso se trata de una Raspberry Pi que controla unos paneles de leds que muestran, además de la fecha y la hora, algunos mensajes de información provenientes del controlador domótico mediante el protocolo MQTT, tales como la temperatura de distintas estancias, o la música que se está reproduciendo en ese momento (Y sí, os habéis fijado bien. La fecha viene en Esperanto. Qué le vamos a hacer…). El dispositivo cuenta además con un sensor de luz, el cual le permite, además de regular la luminosidad de los leds en función de la luz ambiente, proporcionar al sistema información sobre el nivel de luminosidad real de la estancia, permitiendo un control preciso de persianas y luces regulables.

Aspecto del reloj con matriz de leds en la parte superior de la librería de mi dormitorio, junto a algunos libros y colecciones de pelis en viejos archivadores de CD’s. Todo un compendio de mis pequeñas pasiones 😉

Para que el dispositivo funcione de manera autónoma, el programa deberá arrancar automáticamente cuando se encienda la placa, lo cual se puede lograr de varias maneras. Una de ellos, seguramente la más conocida, consiste en añadir la ruta al ejecutable en el archivo /etc/rc.local, aunque también es posible iniciar tareas utilizando el servicio crontab. En ambos casos tenemos un pequeño problema, y es que si el programa se cuelga o experimenta una salida inesperada debida a cualquier excepción no convenientemente capturada, todo el dispositivo se detiene dejando de funcionar.

Para salir al paso, una solución consiste en ejecutar el programa como un servicio. En el  caso que nos ocupa vamos a utilizar el sistema systemd, el cual presenta, entre otras, la gran ventaja de que si se produce un error y el progama se detiene, él mismo se reinicia automáticamente. Algo que a los manazas que vamos dejando rastros de programas mal depurados nos viene que ni de perlas. También es un sistema bastante robusto y que nos permite ajustar las condiciones adecuadas para la ejecución del probrama.

Lo primero que necesitamos es un archivo de script que contenga las instrucciones de inicio de nuestro programa. Si fuera necesario pasar parámetros para el inicio este archivo sería un lugar adecuado para especificarlos. En nuestro caso, es una simple llamada a la ejecución de un script Python:

nano /home/pi/mqtt-matrix/start.sh

#!/bin/bash
#
python3 /home/pi/mqtt-matrix/mqtt-matrix.py

Lo siguiente será la creación del archivo de unidad de servicio. Éste contendrá el nombre con el que queremos que systemd reconozca a nuestro servicio. Aunque sería improbable, no está de más comprobar que no vamos a darle un nombre que ya se encuentra en uso. Para ello, basta con echar un vistazo al contenido de la carpeta que suele contener los archivos de unidad de servicio:

cd /etc/systemd/system/
ls

También podemos probar este comando más específico y que resulta de lo más molón:

sudo systemctl list-unit-files --type=service

En mi caso, como el programa que pretendo ejecutar está en el archivo mqtt-matrix.py, he decicido que el servicio se llame mqtt-matrix.service y listos. Así que creamos el archivo en cuestión:

sudo nano /etc/systemd/system/mqtt-matrix.service

[Unit]
Description=mqtt-matrix
Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/home/pi/mqtt-matrix/start.sh
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

El archivo que hemos creado contiene las opciones más comunes, la mayoría de las cuales resultan bastante autoexplicativas. Además, podríamos especificar el usuario y el grupo bajo el cual se va a ejecutar nuestro servicio. Si no se especifica nada, por defecto se ejecutará con permisos de administrador, que es exactamente lo que deseamos, por ser uno de los requisitos del modo en el que accedemos a los pines de nuestra raspberry, así que lo dejamos tal cual.

Y ya está. A continuación enumeramos varios de los comandos más utilizados para manejar los servicios systemd

Recargar los archivos de servicio después de alguna modificación

sudo systemctl daemon-reload

Iniciar el servicio

sudo systemctl start mqtt-matrix.service

Detener el servicio

sudo systemctl stop mqtt-matrix.service

Reiniciar el servicio

sudo systemctl restart mqtt-matrix.service

Comprobar el estado del servicio

Además, nos proporciona información adicional, tal como:

  • Avisarnos si tenemos errores en la sintaxis del archivo, aunque el servicio no esté en ejecución
  • Indicarnos la ruta del ejecutable
  • Indicarnos la ubicación del archivo de servicio si no está donde esperábamos
sudo systemctl status mqtt-matrix.service

Y, lo más importante, teniendo en cuenta de qué va todo esto, indicarle al sistema que queremos que el servicio arranque automáticamente al inicio

sudo systemctl enable mqtt-matrix.service

O bien, deshabilitar el arranque al inicio

sudo systemctl disable mqtt-matrix.service
Publicado por David en Domótica, Linux, 0 comentarios