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 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.

. 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 . 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.

. 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.

. Permite configurar el inicio de nuestro servicio. Así tenemos, 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.

. 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 . Otra opción es utilizar , 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 .

. 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 . 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.

y . Estos dos parámetros te permitirán definir cuantos intentos y en que intervalo , vas a permitir para que se restablezca el servicio. Por defecto, Systemd permite 4 intentos en 10 segundos. Por supuesto estableciendo nunca se alcanzarán estos valores. StartLimitIntervalSec=0 , obligará a Systemd a reiniciar el servicio tantas veces como sea necesario.

, 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,