Contactez-nous

Gestion des processus (systemd, supervisor)

Apprenez à gérer de manière robuste vos applications Spring Boot (JAR exécutables) en tant que services système en utilisant systemd ou supervisor pour le démarrage, l'arrêt et le redémarrage automatique.

Pourquoi gérer un JAR Spring Boot comme un processus ?

Lancer une application Spring Boot via un simple java -jar mon-application.jar est pratique pour le développement, mais insuffisant pour un environnement de production. En production, une application doit être fiable, démarrer automatiquement après un redémarrage du serveur, redémarrer en cas de crash inattendu, et ses logs doivent être correctement gérés. De plus, elle devrait idéalement s'exécuter sous un utilisateur dédié avec des privilèges limités pour des raisons de sécurité.

Les gestionnaires de processus comme systemd (le standard sur de nombreuses distributions Linux modernes) et supervisor (un système de contrôle de processus populaire et multi-plateforme) répondent à ces besoins. Ils permettent de configurer un JAR exécutable Spring Boot comme un service ou un programme géré, assurant ainsi sa robustesse et sa bonne intégration dans le cycle de vie du système d'exploitation.

Utiliser un gestionnaire de processus offre plusieurs avantages clés :

  • Démarrage au boot : L'application est lancée automatiquement lorsque le serveur démarre.
  • Redémarrage automatique : En cas d'arrêt inattendu (crash, erreur mémoire), le gestionnaire peut redémarrer l'application.
  • Gestion des logs : Redirection et gestion centralisée des flux de sortie standard (stdout) et d'erreur standard (stderr).
  • Contrôle standardisé : Commandes unifiées pour démarrer, arrêter, redémarrer et vérifier le statut du service (ex: systemctl start myapp, supervisorctl stop myapp).
  • Gestion des utilisateurs : Possibilité de faire tourner le processus sous un utilisateur et groupe spécifiques non-root.
  • Gestion des dépendances : (Pour systemd notamment) Possibilité de définir des dépendances avec d'autres services (ex: démarrer après la base de données).

Utilisation de systemd

systemd est le système d'initialisation et le gestionnaire de services utilisé par défaut sur la plupart des distributions Linux récentes (Debian, Ubuntu, CentOS, Fedora, etc.). Il fonctionne sur la base de fichiers de configuration appelés "unit files", généralement placés dans /etc/systemd/system/.

Pour gérer une application Spring Boot avec systemd, vous devez créer un fichier de service, par exemple mon-application.service :

[Unit]
Description=Mon Application Spring Boot
# S'assurer que le réseau est prêt avant de démarrer
After=network.target

[Service]
# Utilisateur et groupe sous lesquels lancer l'application (créer cet utilisateur au préalable!)
User=monappuser
Group=monappgroup

# Chemin vers le répertoire de travail de l'application
WorkingDirectory=/opt/mon-application

# Variables d'environnement (optionnel, ex: pour activer un profil Spring)
# Environment="SPRING_PROFILES_ACTIVE=prod"

# Commande pour lancer le JAR exécutable
# Assurez-vous que 'java' est dans le PATH de l'utilisateur ou utilisez le chemin complet (/usr/bin/java)
ExecStart=/usr/bin/java -jar /opt/mon-application/mon-application.jar

# Code de sortie indiquant un arrêt normal (SIGTERM = 143)
# Important pour que systemd comprenne un arrêt initié par 'systemctl stop'
SuccessExitStatus=143

# Redémarrer en cas d'échec
Restart=on-failure
# Délai avant redémarrage
RestartSec=5

[Install]
# Permet d'activer le service pour qu'il démarre au boot
WantedBy=multi-user.target

Quelques points clés de ce fichier :

  • [Unit] : Métadonnées et dépendances. Description est informative, After spécifie les dépendances de démarrage.
  • [Service] : Définit comment le service est exécuté. User/Group est crucial pour la sécurité. WorkingDirectory définit le répertoire courant pour l'application. ExecStart contient la commande de lancement. SuccessExitStatus=143 est important car Spring Boot s'arrête avec ce code lorsqu'il reçoit un signal SIGTERM (envoyé par systemctl stop), cela évite que systemd ne considère l'arrêt comme un échec. Restart=on-failure assure le redémarrage automatique en cas de crash.
  • [Install] : Définit comment le service est activé via systemctl enable. WantedBy=multi-user.target est typique pour les services standards.

Une fois le fichier créé (par exemple, dans /etc/systemd/system/mon-application.service), vous pouvez gérer le service avec les commandes systemctl :

# Recharger la configuration systemd après avoir créé/modifié le fichier
sudo systemctl daemon-reload

# Activer le service pour qu'il démarre au boot
sudo systemctl enable mon-application.service

# Démarrer le service manuellement
sudo systemctl start mon-application.service

# Arrêter le service
sudo systemctl stop mon-application.service

# Redémarrer le service
sudo systemctl restart mon-application.service

# Voir le statut du service (logs récents inclus)
sudo systemctl status mon-application.service

# Voir les logs complets du service via journald
sudo journalctl -u mon-application.service -f

Utilisation de supervisor

supervisor est un système de contrôle de processus écrit en Python. Il est souvent utilisé pour gérer des applications non-système ou dans des environnements où systemd n'est pas la norme. Il se compose d'un démon (supervisord) et d'un client en ligne de commande (supervisorctl).

La configuration de supervisor se fait via des fichiers INI-like, souvent placés dans /etc/supervisor/conf.d/. Pour notre application Spring Boot, on pourrait créer mon-application.conf :

[program:mon-application]
; Nom unique du programme géré par supervisor

; Commande pour lancer l'application
command=/usr/bin/java -jar /opt/mon-application/mon-application.jar

; Répertoire de travail
directory=/opt/mon-application

; Utilisateur sous lequel lancer le processus
user=monappuser

; Démarrer automatiquement au lancement de supervisord
autostart=true

; Redémarrer automatiquement si le processus se termine de manière inattendue
autorestart=true
; (Alternative: autorestart=unexpected)

; Signal envoyé pour arrêter le processus (TERM est le défaut de Spring Boot)
stopsignal=TERM

; Temps d'attente après l'envoi de stopsignal avant d'envoyer SIGKILL
stopwaitsecs=10

; Fichier pour rediriger la sortie standard (stdout)
stdout_logfile=/var/log/supervisor/mon-application-stdout.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10

; Fichier pour rediriger la sortie d'erreur (stderr)
stderr_logfile=/var/log/supervisor/mon-application-stderr.log
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10

; Variables d'environnement (optionnel)
; environment=SPRING_PROFILES_ACTIVE="prod",OTHER_VAR="value"

Explication des directives courantes :

  • [program:mon-application] : Définit une section pour notre programme.
  • command : La commande exacte à exécuter.
  • directory : Le répertoire de travail.
  • user : L'utilisateur pour l'exécution.
  • autostart, autorestart : Contrôlent le démarrage et le redémarrage.
  • stopsignal : Le signal utilisé pour arrêter le processus (TERM correspond à SIGTERM).
  • stdout_logfile, stderr_logfile : Configuration de la journalisation des sorties, avec gestion de la rotation.
  • environment : Permet de passer des variables d'environnement.

Après avoir créé ou modifié le fichier de configuration, utilisez supervisorctl pour informer supervisord des changements et gérer le programme :

# Lire les nouveaux fichiers de configuration
sudo supervisorctl reread

# Appliquer les changements (ajoute les nouveaux programmes)
sudo supervisorctl update

# Démarrer le programme
sudo supervisorctl start mon-application

# Arrêter le programme
sudo supervisorctl stop mon-application

# Redémarrer le programme
sudo supervisorctl restart mon-application

# Voir le statut de tous les programmes ou d'un programme spécifique
sudo supervisorctl status
sudo supervisorctl status mon-application

# Voir les derniers logs (stdout ou stderr)
sudo supervisorctl tail mon-application stdout
sudo supervisorctl tail mon-application stderr -f

Considérations et bonnes pratiques

Que vous choisissiez systemd ou supervisor, plusieurs bonnes pratiques s'appliquent :

  • Utilisateur dédié : Toujours créer et utiliser un utilisateur système non-privilégié (par exemple, monappuser) pour exécuter votre application Spring Boot. Ne jamais l'exécuter en tant que root. Assurez-vous que cet utilisateur a les permissions nécessaires sur le fichier JAR et le répertoire de travail.
  • Gestion des logs : Configurez Spring Boot pour logger sur la console (stdout/stderr). Les gestionnaires de processus se chargeront de capturer ces flux et de les rediriger vers les journaux système (journald pour systemd) ou des fichiers dédiés (supervisor). Configurez la rotation des logs pour éviter de saturer l'espace disque.
  • Configuration externalisée : Utilisez les mécanismes de Spring Boot (profils, application.properties/yml externes, variables d'environnement) pour gérer la configuration. Les variables d'environnement peuvent être définies directement dans les fichiers de configuration de systemd ou supervisor.
  • Arrêt gracieux : Assurez-vous que le gestionnaire de processus envoie un signal `SIGTERM` (c'est généralement le cas par défaut, ou configurable via `stopsignal=TERM` pour supervisor) et que systemd est configuré avec `SuccessExitStatus=143`. Cela permet à Spring Boot d'exécuter ses routines d'arrêt proprement (fermer les connexions, terminer les tâches en cours).
  • Health Checks : Le redémarrage automatique sur crash est utile, mais idéalement, il faudrait intégrer des vérifications de santé (via l'endpoint Actuator /health par exemple) pour déclencher des redémarrages plus intelligents ou alerter en cas de non-réponse, bien que cela dépasse souvent la configuration de base du gestionnaire de processus lui-même.

Le choix entre systemd et supervisor dépend souvent de votre environnement et de vos préférences. systemd est plus intégré au système d'exploitation sur les distributions modernes, tandis que supervisor peut être plus simple à configurer pour des applications spécifiques ou dans des contextes non-Linux.