Cómo crear un servicio de systemd para una aplicación con Spring Boot

Escrito por el .
gnu-linux java planeta-codigo
Enlace permanente Comentarios

La mayoría de distribuciones Linux ya usan systemd como gestor y supervisor de los servicios del sistema. Creando un descriptor podremos gestionar un servicio propio con los mismos comandos de systemd que usamos para cualquier otro servicio del sistema.

Linux

Java

Habiendo creado una aplicación o microservicio, por ejemplo con Spring Boot, necesitaremos que se inicie con el sistema y una forma de gestionarlo para detenerlo, reiniciarlo y que se reinicie en caso de salida abrupta.

systemd es el gestor de servicios que han adoptado la mayoría de distribuciones importantes como Debian, CentOS, RHEL, openSUSE, incluso Ubuntu después de abandonar su propio gestor de servicios Upstart. Podemos usar systemd para que gestione como servicio una aplicación propia. Para ello deberemos crear un archivo unit que describa el servicio y sus dependencias con otros servicios para que se inicie correctamente, él y sus dependencias.

Los servicios se definen en archivos de texto denominados unit que tienen un formato similar a los archivos .desktop que a su vez están inspirados en los archivos .ini de Windows. En la documentación de los archivos unit de systemd se detalla con amplitud los archivos unit de systemd, tienen tres secciones:

  • [Unit]: contiene información genérica independiente del tipo de servicio como descripción, requerimientos, deseos o orden de inicio.
  • [Service]: define el tipo de servicio, los comandos de preinicio, inicio, postinicio, parada, postparada, condiciones reinicio y más parámetros comentados en la documentación de los sevicios de systemd.
  • [Install]: esta sección es usada al habilitar o deshabilitar un servicio en el sistema con el comando systemctl, pudiendo por ejemplo que se inicie este servicio cuando otro se inicie siendo otra forma de declarar dependencias. De este modo se puede indicar que un servicio tiene otros como dependencia pero también se puede indicar que un servicio se inicie cuando otro lo haga.

Usando la aplicación del Ejemplo de API REST en Java con JAX-RS y Spring Boot, crearé un archivo unit de systemd para que se inicie con el sistema y se reinicie en caso de fallo. Primeramente deberemos crear los archivos que definen el servicio para systemd y sus dependencias si las tienen. En los siguientes ejemplos spring-boot-jaxrs.service es una aplicación de Spring Boot con una interfaz REST que simplemente devuelve el mensaje indicado por parámetro con la fecha en la dirección http://localhost:8080/message?message=Hola. spring-boot-jaxrs-postgres.service es el mismo servicio pero que tiene una dependencia sobre un contenedor de Docker con una base PostgreSQL, aunque la aplicación Spring Boot no hace uso de la base de datos PostgreSQL sirve para observar que si se inicia el servicio de la aplicación Java también se inicia el servicio de la base de datos si no estuviera ya en ejecución. postgres.service es el servicio de la base de datos PostgreSQL en un contenedor de Docker y que tiene como dependencia el servicio de Docker.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Unit]
Description=Spring Boot application

[Service]
Restart=always
ExecStart=/usr/bin/java -jar /var/apps/SpringBootJaxrs-0.0.1-SNAPSHOT.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
spring-boot-jaxrs.service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Unit]
Description=Spring Boot application
Requires=postgres.service
After=postgres.service

[Service]
Restart=always
ExecStart=/usr/bin/java -jar /var/apps/SpringBootJaxrs-0.0.1-SNAPSHOT.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
spring-boot-jaxrs-postgres.service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Unit]
Description=PostgreSQL container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a postgres
ExecStop=/usr/bin/docker stop -t 5 postgres

[Install]
WantedBy=multi-user.target
postgres.service

La instalación de la aplicación y de los servicios de systemd en el sistema se realizan copiando archivos, cambiando algunos permisos y usando los comandos de systemd para gestionar los servicios. Los mensajes de salida que emite el servicio se obtienen con el comando journalctl -u spring-boot-jaxrs.service.

Los archivos unit propios deben ser ubicados en el directorio /etc/systemd/system/, siendo el directorio /usr/lib/systemd/system/ donde se ubican los instalados por los paquetes del sistema. Iniciado el servicio con el comando sudo systemctl start spring-boot-jaxrs.service, si queremos habilitarlo con el inicio del sistema usamos el comando sudo systemctl enable spring-boot-jaxrs.service. Para ver el estado del servicio usamos el comando sudo systemctl status spring-boot-jaxrs.service.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
./gradlew build
sudo mkdir /var/apps
sudo cp build/libs/SpringBootJaxrs-0.0.1-SNAPSHOT.jar /var/apps
sudo cp misc/spring-boot-jaxrs.service /etc/systemd/system
sudo cp misc/spring-boot-jaxrs-postgres.service /etc/systemd/system
sudo cp misc/postgres.service /etc/systemd/system
sudo chmod ugo+x /etc/systemd/system/spring-boot-jaxrs.service
sudo chmod ugo+x /etc/systemd/system/spring-boot-jaxrs-postgres.service
sudo chmod ugo+x /etc/systemd/system/postgres.service
sudo systemctl daemon-reload
install.sh
1
2
3
4
5
6
7
8
9
sudo systemctl start docker.service
docker run --name postgres postgres

sudo systemctl start spring-boot-jaxrs.service
sudo systemctl status spring-boot-jaxrs.service
sudo systemctl stop spring-boot-jaxrs.service
sudo systemctl start spring-boot-jaxrs-postgres.service
sudo systemctl status spring-boot-jaxrs-postgres.service
sudo systemctl stop spring-boot-jaxrs-postgres.service
manage.sh

En los enlaces de referencia hay documentación más detallada tanto para gestionar los servicios con systemd como también documentación de sus archivos unit.

Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
sudo systemctl start spring-boot-jaxrs.service


Comparte el artículo: