Como crear un servicio con Systemd

Este es uno de los capítulos del tutorial Trabajando con Systemd. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

En los anteriores capítulos de este tutorial hemos visto que era Systemd y que eran las unidades. Además hemos visto como podíamos conocer el estado de las unidades y como podíamos gestionarlas. Sin embargo, para poder sacar todo el partido a Systemd, es necesario que aprendamos a crear nuestras propias unidades. Y en particular, en este capítulo del tutorial te mostrará como crear un servicio con Systemd.

Aunque de buenas a primeras pueda sonar como algo complejo, la realidad es que es una operación bastante trivial. Al final nos puede ser de gran utilidad para tener nuestro propio servicio funcionando, para hacer cualquier cosa que nos podamos imaginar.

En particular, para ver que veas lo fácil que resulta crear un servicio, vamos a crear un servidor de páginas web.

Como crear un servicio con Systemd

Como crear un servicio con Systemd

Como he comentado en la introducción para que veas lo sencillo que resulta crear un servicio, vamos a crear un servidor de páginas web. Para ello, parte de un sencilllo ejemplo que puedes encontrar en GitHub.

Este servidor lo único que hace es devolverte una sencilla página web, en función de la dirección que introduzcas. Sin embargo, esto no es mas que un ejemplo, lo importante es crear un servicio con Systemd.

¿Porque crear un servicio? Si te limitas a ejecutar este sencillo script con python3 sample.py, te darás cuenta que necesitas ejecutarlo cada vez que quieras tener la aplicación funcionando. ¿Pero que sucede cuando apagas o reinicias tu equipo o VPS? Simplemente tu aplicación muere.

La ventaja de convertir tu aplicación en un servicio es que no te tienes que preocupar de arrancar tu servicio cuando inicies el ordenador, el sistema ya se preocupa por ti. Simplemente, conforme vimos en el segundo capítulo del tutorial, te tienes que preocupar de tener habilitado el servicio.

Al queso… como crear un servcio con Systemd

Para ello, crearemos el siguiente archivo /lib/systemd/system/sample.service con el contenido que indico a continuación,

[Unit]
Description=Ejemplo
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=lorenzo
ExecStart=/usr/bin/env python3 /home/lorenzo/temporal/sample/sample.py

[Install]
WantedBy=multi-user.target

Recuerda que debes sustituir mi usuario lorenzo por el tuyo, así como la ruta donde has puesto el script en Python.

Y ya lo tienes… ¿Sencillo no?. Así de primeras suena todo a chino, pero vamos a desgranarlo.

Desgranando nuestro servicio

Vamos punto por punto, para dejar claro cada uno de los elementos en que consiste,

  • Description. Aquí puedes introducir la definición o descripción del servicio. Esta información es la que aparecerá en el log y en la salida del comando systemctl status. Es decir, que tiene que ser suficientemente descriptiva para ti.
  • After. Esta directiva indica que nuestro servicio tiene que iniciarse después de que la red esté lista. En el caso de que tuvieramos que esperar a que estuvira listo MariaDB, la directiva sería tal como After=mysqld.service. También podemos encadenar varios servicios, separados por espacio, por ejemplo
After=syslog.target network.target sshd.service
  • ExecStart. Aquí debe figrurar la ruta al ejecutable, así como los parámetros necesarios para que arranque.
  • Type. Permite configurar el inicio de nuestro servicio. Así tenemos,
    • simple. El proceso empieza con ExecStart y es el principal proceso del servicio.
    • forking. En este caso se lanza un proceso hijo, que se convierte en el proceso principal.
    • oneshot. El proceso termina antes de comenzar con las siguientes unidades.
    • dbus. Las siguientes unidades empezarán cuando el proceso principal tegan el D-Bus.
    • notify. En este caso depende de un mensaje de notificación enviado por sd_notify.
    • idle. La ejecución del servicio se retraza hasta que todos los trabajos han terminado.
  • Restart. Por defecto Systemd, no reinicia tu servicio en caso de que este caiga, por la razón que sea. Sin embargo, a ti lo que te interesa es que tu servicio siempre esté en funcionamiento. Para lograr esto, tienes que poner la directiva Restart=always. Otra opción es utilizar Restart=on-failure, en cuyo caso solo se reinicializará si el servicio se ha parado por fallo.
  • RestartSec. Te permite definir el tiempo que debe transcurrir hasta que se intente poner de nuevo en marcha tu servicio. Por defecto, Systemd, trata de levantar el servicio, transcurrido 100 ms. Con esta directiva, tu puedes establecer el tiempo en segundos. Sin embargo, es interesante que dejes como mínimo un segundo para no forzar la máquina.
  • StartLimitBurst y StartLimitIntervalSec. Estos dos parámetros te permitirán definir cuantos intentos StartLimtBurs y en que intervalo StartLimitIntervalSec, vas a permitir para que se restablezca el servicio. Por defecto, Systemd permite 4 intentos en 10 segundos. Por supuesto estableciendo RestartSec=3 nunca se alcanzarán estos valores.
  • StartLimitIntervalSec=0, obligará a Systemd a reiniciar el servicio tantas veces como sea necesario.
  • WantedBy. Esto equivale al runlevel. Establece el objetivo (Target) u objetivos bajo los que el servicio debería ser iniciado.

Objetivos o Targets

Los objetivos existentes los puedes ver en la siguiente tabla,

Runlevel Objetivo Descripción
0 poweroff.target Apagado del sistema
1 rescue.target Shell de rescate
2 multi-user.target Sistema no gráfico
3 multi-user.target Sistema no gráfico
4 multi-user.target Sistema no gráfico
5 multi-user.target Sistema gráfico
6 reboot.target Apagado y reinicio

Para conocer cual es el objetivo definido por defecto, tienes que ejecutar la siguiente orden,

systemctl get-default

En mi portátil devuelve graphical.target.

Sin embargo, hay mas objetivos, a parte de los indicados anteriormente. Si quieres conocer todos los objetivos que hay preestablecidos, ejecuta la orden,

systemctl list-units --type target

En mi caso el resultado fue el siguiente,

UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
basic.target           loaded active active Basic System
bluetooth.target       loaded active active Bluetooth
cryptsetup.target      loaded active active Local Encrypted Volumes
getty.target           loaded active active Login Prompts
graphical.target       loaded active active Graphical Interface
local-fs-pre.target    loaded active active Local File Systems (Pre)
local-fs.target        loaded active active Local File Systems
multi-user.target      loaded active active Multi-User System
network-online.target  loaded active active Network is Online
network.target         loaded active active Network
nss-lookup.target      loaded active active Host and Network Name Lookups
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target           loaded active active Paths
remote-fs.target       loaded active active Remote File Systems
slices.target          loaded active active Slices
sockets.target         loaded active active Sockets
sound.target           loaded active active Sound Card
swap.target            loaded active active Swap
sysinit.target         loaded active active System Initialization
time-sync.target       loaded active active System Time Synchronized
timers.target          loaded active active Timers

Poniendo en marcha el servicio

Ahora que tenemos unas ligeras nociones de quien es quien en el archivo de configuración de nuestro servicio, y ya hemos creado nuestro servicio, tan solo nos queda ponerlo en marcha.

Esto se hace conforme vimos en el capítulo sobre gestionar servicios en Systemd. Así para iniciar nuestro servicio, simplemente,

sudo systemctl start sample

para detenerlo

sudo systemctl stop sample

También recuerda que vimos que para que nuestro servicio se iniciara con el sistema, teníamos que ejecutar la orden,

sudo systemctl enable sample

Y con esto tenemos las operaciones básicas y necesarias para gestionar el servicio que acabamos de crear.

Conclusiones

Con esto ya tienes unas nociones básicas de como crear un servicio en Systemd. Ten en cuenta que esto no son mas que unas pinceladas de todas las posibilidades que nos ofrece Systemd. Pero creo que es suficiente para crear un servicio con Systemd.


Mas información,