Supervisor est un gestionnaire de processus pour systèmes Unix qui démarre, surveille et redémarre automatiquement vos programmes en arrière-plan. Il remplace les scripts personnalisés et les solutions fragiles basées sur cron par un système centralisé, simple à configurer et à opérer. Vous apprendrez dans ce guide à installer Supervisor, configurer des programmes, utiliser supervisorctl pour les contrôler, et exploiter les fonctionnalités avancées comme les groupes de processus et l’interface web.
Qu’est-ce que Supervisor ?
Section intitulée « Qu’est-ce que Supervisor ? »Supervisor est un système client/serveur qui surveille et contrôle des processus sur des systèmes Unix. Il a été créé pour résoudre un problème concret : garantir que des services critiques restent actifs, sans écrire de scripts rc.d complexes ni vérifier manuellement des fichiers PID.
Analogie : Supervisor est comme un chef d’équipe dans une usine. Il s’assure que chaque ouvrier (processus) est à son poste, le remplace automatiquement s’il tombe malade (crash), et tient un registre précis de ce qui se passe (logs). Le chef d’équipe ne fait pas le travail lui-même, il supervise.
Supervisor se compose de quatre éléments :
| Composant | Rôle |
|---|---|
| supervisord | Le démon (serveur) qui démarre et surveille les processus |
| supervisorctl | Le client en ligne de commande pour contrôler supervisord |
| Interface web | Interface graphique optionnelle pour monitorer les processus |
| API XML-RPC | Interface programmatique pour intégrer Supervisor à d’autres outils |
Pourquoi Supervisor plutôt que systemd ?
Section intitulée « Pourquoi Supervisor plutôt que systemd ? »Les deux outils gèrent des processus, mais ils n’ont pas le même positionnement :
| Critère | Supervisor | systemd |
|---|---|---|
| Complexité | Fichier INI simple | Unit files + directives avancées |
| Portabilité | Linux, macOS, FreeBSD, Solaris | Linux uniquement |
| Droits requis | Fonctionne sans root | Souvent root pour les services système |
| Cas d’usage | Applications utilisateur, conteneurs | Services système, boot OS |
| Interface web | Intégrée | Nécessite un outil tiers |
| Gestion des logs | Centralisée par processus | Journald |
En résumé : utilisez systemd pour les services système, et Supervisor pour vos applications, vos environnements de développement, ou vos conteneurs multi-processus.
Installation
Section intitulée « Installation »sudo apt-get updatesudo apt-get install -y supervisorLe paquet crée automatiquement le fichier /etc/supervisor/supervisord.conf et le dossier /etc/supervisor/conf.d/ pour les configurations par programme. Le service est activé au boot.
Vérification :
supervisord --version# 4.3.0sudo yum install -y epel-releasesudo yum install -y supervisorActivez le service :
sudo systemctl enable --now supervisordpip install supervisorCette méthode installe la version la plus récente depuis PyPI. Vous devrez ensuite générer la configuration manuellement :
echo_supervisord_conf > /etc/supervisord.confConfiguration : les bases
Section intitulée « Configuration : les bases »Supervisor utilise un fichier de configuration au format INI (style Windows-INI). Le fichier principal est recherché dans cet ordre :
../etc/supervisord.conf(relatif à l’exécutable)../supervisord.conf(relatif à l’exécutable)$CWD/supervisord.conf$CWD/etc/supervisord.conf/etc/supervisord.conf/etc/supervisor/supervisord.conf
Structure du fichier supervisord.conf
Section intitulée « Structure du fichier supervisord.conf »Un fichier de configuration complet contient plusieurs sections. Voici les sections essentielles avec leurs options les plus utiles :
[unix_http_server]file=/var/run/supervisor.sock ; socket Unix pour supervisorctlchmod=0700 ; permissions du socket
[supervisord]logfile=/var/log/supervisor/supervisord.logpidfile=/var/run/supervisord.pidchildlogdir=/var/log/supervisornodaemon=false ; true = premier plan (utile dans Docker)loglevel=info ; critical, error, warn, info, debug, trace
[rpcinterface:supervisor]supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]serverurl=unix:///var/run/supervisor.sock
[include]files = /etc/supervisor/conf.d/*.confLa section [include] est importante : elle permet de séparer la configuration de chaque programme dans son propre fichier, ce qui facilite la maintenance.
Configurer un programme
Section intitulée « Configurer un programme »Chaque programme supervisé est déclaré dans une section [program:nom]. Créez un fichier /etc/supervisor/conf.d/mon-app.conf :
[program:mon-app]command=/usr/bin/python3 /opt/mon-app/main.pydirectory=/opt/mon-appautostart=trueautorestart=truestartsecs=3startretries=3user=appuserstdout_logfile=/var/log/supervisor/mon-app.logstderr_logfile=/var/log/supervisor/mon-app-error.logenvironment=APP_ENV="production",LOG_LEVEL="info"Voici le rôle de chaque directive :
| Directive | Valeur par défaut | Description |
|---|---|---|
| command | (requis) | Commande à exécuter. Le programme ne doit pas se daemoniser |
| directory | (hérite de supervisord) | Répertoire de travail avant exécution |
| autostart | true | Démarre automatiquement avec supervisord |
| autorestart | unexpected | true = toujours, false = jamais, unexpected = si code de sortie inattendu |
| startsecs | 1 | Durée minimale en secondes avant de considérer le démarrage réussi |
| startretries | 3 | Nombre de tentatives avant l’état FATAL |
| user | (utilisateur de supervisord) | Compte Unix sous lequel le programme tourne |
| stdout_logfile | AUTO | Fichier de logs stdout (AUTO, NONE, ou un chemin) |
| stderr_logfile | AUTO | Fichier de logs stderr |
| environment | (vide) | Variables d’environnement au format CLÉ="valeur" |
| priority | 999 | Ordre de démarrage (les petits chiffres démarrent en premier) |
| stopsignal | TERM | Signal envoyé pour arrêter le processus |
| stopwaitsecs | 10 | Temps d’attente avant SIGKILL |
Appliquer une nouvelle configuration
Section intitulée « Appliquer une nouvelle configuration »Après avoir créé ou modifié un fichier dans /etc/supervisor/conf.d/, rechargez la configuration :
supervisorctl reread# mon-app: availableLa commande reread lit les fichiers de configuration mais n’applique rien. Pour appliquer les changements :
supervisorctl update# mon-app: added process groupLa commande update démarre les nouveaux programmes, arrête ceux qui ont été supprimés et redémarre ceux dont la configuration a changé.
Opérer avec supervisorctl
Section intitulée « Opérer avec supervisorctl »supervisorctl est l’outil principal pour interagir avec Supervisor au quotidien. Il peut fonctionner en mode interactif (shell) ou en mode commande unique.
Commandes essentielles
Section intitulée « Commandes essentielles »# Voir l'état de tous les processussupervisorctl status# mon-app RUNNING pid 12345, uptime 0:05:23# worker_00 RUNNING pid 12346, uptime 0:05:23
# Démarrer un processussupervisorctl start mon-app# mon-app: started
# Arrêter un processussupervisorctl stop mon-app# mon-app: stopped
# Redémarrer un processussupervisorctl restart mon-app# mon-app: stopped# mon-app: started
# Redémarrer tous les processussupervisorctl restart all
# Consulter les logs d'un processussupervisorctl tail mon-appsupervisorctl tail -f mon-app # suivi en temps réelsupervisorctl tail mon-app stderr # logs d'erreurRecharger la configuration
Section intitulée « Recharger la configuration »Il existe trois niveaux de rechargement :
| Commande | Effet |
|---|---|
reread | Relit les fichiers de configuration, affiche les changements détectés, ne touche à rien |
update | Applique les changements : ajoute les nouveaux programmes, retire les supprimés, redémarre les modifiés |
reload | Redémarre complètement le démon supervisord (arrête puis relance tous les processus) |
En fonctionnement normal, utilisez le couple reread + update. Réservez reload aux cas où une modification de la section [supervisord] elle-même est nécessaire.
Mode interactif
Section intitulée « Mode interactif »Lancer supervisorctl sans argument ouvre un shell interactif :
supervisorctl# supervisor> status# mon-app RUNNING pid 12345, uptime 0:05:23# supervisor> help# ... liste des commandes disponibles# supervisor> quitLancer plusieurs instances avec numprocs
Section intitulée « Lancer plusieurs instances avec numprocs »Supervisor permet de démarrer plusieurs instances identiques d’un même programme grâce à la directive numprocs. C’est utile pour les workers, les consommateurs de file d’attente, ou les traitements parallèles.
[program:worker]command=/usr/bin/python3 /opt/app/worker.pyprocess_name=%(program_name)s_%(process_num)02dnumprocs=3autostart=trueautorestart=truestdout_logfile=/var/log/supervisor/worker_%(process_num)02d.logstderr_logfile=/var/log/supervisor/worker_%(process_num)02d-error.logQuand numprocs est supérieur à 1, la directive process_name doit contenir %(process_num)s pour que chaque instance ait un nom unique. Supervisor crée alors les processus worker_00, worker_01 et worker_02.
supervisorctl status# worker_00 RUNNING pid 12350, uptime 0:02:10# worker_01 RUNNING pid 12351, uptime 0:02:10# worker_02 RUNNING pid 12352, uptime 0:02:10Les expressions Python disponibles dans les chemins et commandes sont : %(program_name)s, %(process_num)02d, %(group_name)s, %(host_node_name)s et %(here)s (répertoire du fichier de configuration).
Groupes de processus
Section intitulée « Groupes de processus »Les groupes permettent de regrouper plusieurs programmes pour les contrôler ensemble. C’est utile quand des processus sont liés fonctionnellement.
[program:api]command=/usr/bin/python3 /opt/app/api.pypriority=10autostart=trueautorestart=true
[program:worker]command=/usr/bin/python3 /opt/app/worker.pyprocess_name=%(program_name)s_%(process_num)02dnumprocs=3priority=20autostart=trueautorestart=true
[group:mon-app]programs=api,workerpriority=999Avec cette configuration, les processus sont regroupés sous le préfixe mon-app: :
supervisorctl status# mon-app:api RUNNING pid 12345, uptime 0:01:30# mon-app:worker_00 RUNNING pid 12346, uptime 0:01:30# mon-app:worker_01 RUNNING pid 12347, uptime 0:01:30# mon-app:worker_02 RUNNING pid 12348, uptime 0:01:30
# Arrêter tout le groupesupervisorctl stop 'mon-app:*'# mon-app:api: stopped# mon-app:worker_00: stopped# mon-app:worker_01: stopped# mon-app:worker_02: stoppedLa directive priority contrôle l’ordre de démarrage et d’arrêt. Les programmes avec une priorité basse démarrent en premier et s’arrêtent en dernier.
États des processus
Section intitulée « États des processus »Un processus supervisé passe par différents états au cours de sa vie. Comprendre ces états permet de diagnostiquer rapidement les problèmes.
| État | Description |
|---|---|
| STOPPED | Le processus est arrêté (manuellement ou jamais démarré) |
| STARTING | Le processus est en cours de démarrage |
| RUNNING | Le processus fonctionne depuis au moins startsecs secondes |
| BACKOFF | Le processus a démarré mais s’est arrêté trop vite (avant startsecs). Supervisor réessaye |
| STOPPING | Le processus est en cours d’arrêt |
| EXITED | Le processus s’est arrêté (volontairement ou non) depuis l’état RUNNING |
| FATAL | Le processus n’a pas pu démarrer après startretries tentatives |
| UNKNOWN | État inconnu (erreur interne de Supervisor) |
Le cycle complet :
- STOPPED → STARTING : vous lancez
startouautostart=trueau boot - STARTING → RUNNING : le processus tourne depuis
startsecssecondes - STARTING → BACKOFF : le processus s’arrête avant
startsecs - BACKOFF → STARTING : Supervisor réessaye (délai croissant entre chaque tentative)
- BACKOFF → FATAL :
startretriestentatives échouées - RUNNING → EXITED : le processus se termine
- EXITED → STARTING :
autorestartest activé et le code de sortie correspond
Un processus en état FATAL nécessite une intervention manuelle. Corrigez le problème (commande incorrecte, permissions, dépendances manquantes) puis relancez-le avec supervisorctl start.
Interface web
Section intitulée « Interface web »Supervisor intègre une interface web pour surveiller et contrôler les processus depuis un navigateur. Pour l’activer, ajoutez la section [inet_http_server] :
[inet_http_server]port=127.0.0.1:9001username=adminpassword=secretAccédez ensuite à http://127.0.0.1:9001 dans votre navigateur. L’interface permet de voir l’état de chaque processus, de les démarrer, arrêter ou redémarrer, et de consulter leurs logs.
Signaux et arrêt propre
Section intitulée « Signaux et arrêt propre »Supervisor réagit à plusieurs signaux Unix :
| Signal | Effet |
|---|---|
| SIGTERM | Arrête supervisord et tous ses processus |
| SIGINT | Identique à SIGTERM |
| SIGQUIT | Identique à SIGTERM |
| SIGHUP | Arrête tous les processus, relit la configuration, puis redémarre tout |
| SIGUSR2 | Ferme et rouvre les fichiers de logs (rotation) |
Pour un arrêt propre de vos programmes, configurez stopsignal et stopwaitsecs :
[program:api]command=/usr/bin/python3 /opt/app/api.pystopsignal=TERMstopwaitsecs=30stopasgroup=truekillasgroup=trueLes directives stopasgroup et killasgroup sont importantes pour les programmes qui créent des sous-processus (Flask en mode debug, applications multiprocessing). Elles envoient le signal à tout le groupe de processus et pas uniquement au processus parent.
Gestion des logs
Section intitulée « Gestion des logs »Supervisor centralise les logs de chaque processus supervisé. Chaque programme peut avoir un fichier dédié pour stdout et stderr.
Configuration des logs par programme
Section intitulée « Configuration des logs par programme »[program:mon-app]command=/usr/bin/python3 /opt/app/main.pystdout_logfile=/var/log/supervisor/mon-app.logstdout_logfile_maxbytes=50MBstdout_logfile_backups=10stderr_logfile=/var/log/supervisor/mon-app-error.logstderr_logfile_maxbytes=50MBstderr_logfile_backups=10redirect_stderr=false| Directive | Effet |
|---|---|
stdout_logfile | Chemin du fichier de logs stdout. AUTO = automatique, NONE = pas de log |
stdout_logfile_maxbytes | Taille max avant rotation (défaut : 50 MB). 0 = pas de rotation |
stdout_logfile_backups | Nombre de fichiers de rotation conservés (défaut : 10) |
redirect_stderr | Si true, stderr est redirigé vers stdout (un seul fichier de logs) |
Pour forcer la rotation des logs sans redémarrer, envoyez un signal SIGUSR2 à supervisord :
kill -USR2 $(supervisorctl pid)Consulter les logs avec supervisorctl
Section intitulée « Consulter les logs avec supervisorctl »# Dernières lignes du log stdoutsupervisorctl tail mon-app
# Suivi en temps réel (comme tail -f)supervisorctl tail -f mon-app
# 500 derniers octetssupervisorctl tail -500 mon-app
# Logs stderrsupervisorctl tail mon-app stderrSupervisor dans Docker
Section intitulée « Supervisor dans Docker »Supervisor est souvent utilisé dans des conteneurs Docker quand un conteneur doit gérer plusieurs processus. Bien que la bonne pratique recommande un processus par conteneur, certains cas justifient l’exception : environnements de développement, applications legacy, ou conteneurs intégrant un processus principal et un sidecar.
Exemple : application web + worker
Section intitulée « Exemple : application web + worker »Prenons un cas concret : une application web qui a besoin d’un serveur HTTP et d’un worker de traitement.
Structure du projet :
mon-projet/├── Dockerfile├── supervisord.conf├── app.py└── worker.pyDockerfile :
FROM python:3.12-slim
RUN pip install --no-cache-dir supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisord.confCOPY app.py /opt/app/app.pyCOPY worker.py /opt/app/worker.py
EXPOSE 8000
CMD ["supervisord", "-n", "-c", "/etc/supervisord.conf"]Le flag -n (ou --nodaemon) est indispensable dans Docker : il force Supervisor à rester au premier plan. Sans ce flag, supervisord se daemonise, Docker considère que le processus principal est terminé, et le conteneur s’arrête.
supervisord.conf :
[supervisord]nodaemon=truelogfile=/var/log/supervisor/supervisord.loglogfile_maxbytes=0pidfile=/var/run/supervisord.pid
[unix_http_server]file=/var/run/supervisor.sock
[rpcinterface:supervisor]supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]serverurl=unix:///var/run/supervisor.sock
[program:web]command=python3 /opt/app/app.pyautostart=trueautorestart=truestdout_logfile=/dev/stdoutstdout_logfile_maxbytes=0stderr_logfile=/dev/stderrstderr_logfile_maxbytes=0priority=10
[program:worker]command=python3 /opt/app/worker.pyautostart=trueautorestart=truestdout_logfile=/dev/stdoutstdout_logfile_maxbytes=0stderr_logfile=/dev/stderrstderr_logfile_maxbytes=0priority=20Dans un contexte Docker, redirigez les logs vers /dev/stdout et /dev/stderr avec logfile_maxbytes=0 (désactivation de la rotation, obligatoire pour les fichiers non seekable). Cela permet à docker logs de capturer la sortie de tous les processus.
Construction et exécution :
docker build -t mon-app-supervisor .
docker run -d --name mon-app mon-app-supervisor
# Vérifier les processusdocker exec mon-app supervisorctl status# web RUNNING pid 8, uptime 0:00:15# worker RUNNING pid 9, uptime 0:00:15
# Consulter les logsdocker logs mon-appDépannage
Section intitulée « Dépannage »Problèmes courants et solutions
Section intitulée « Problèmes courants et solutions »| Symptôme | Cause probable | Solution |
|---|---|---|
FATAL après démarrage | Commande invalide ou dépendance manquante | Vérifiez la commande manuellement : exécutez-la dans un terminal |
BACKOFF puis FATAL | Le processus démarre puis crash avant startsecs | Augmentez startsecs=0 temporairement pour diagnostiquer, consultez les logs stderr |
unix:///var/run/supervisor.sock no such file | supervisord n’est pas démarré | Lancez supervisord ou vérifiez le chemin du socket |
Permission denied: supervisor.sock | Mauvais droits sur le socket | Vérifiez chmod dans [unix_http_server] ou lancez avec les bons droits |
SPAWNERR: can't find command | Chemin de la commande incorrect | Utilisez un chemin absolu dans command= |
| Logs vides | redirect_stderr=true mais logs lus sur stderr | Consultez stdout_logfile, ou séparez stdout et stderr |
| Processus zombie | Sous-processus non récupérés | Ajoutez stopasgroup=true et killasgroup=true |
Commandes de diagnostic
Section intitulée « Commandes de diagnostic »# Vérifier que supervisord tournesupervisorctl pid# 12340
# Voir les logs détaillés de supervisordtail -50 /var/log/supervisor/supervisord.log
# Voir les logs d'un processus en erreursupervisorctl tail mon-app stderr
# Tester la commande manuellement/usr/bin/python3 /opt/app/main.py
# Vérifier la configurationsupervisord -c /etc/supervisord.conf --test 2>&1 || echo "Erreur de configuration"Bonnes pratiques
Section intitulée « Bonnes pratiques »Configuration
Section intitulée « Configuration »- Un fichier par programme dans
/etc/supervisor/conf.d/plutôt que tout danssupervisord.conf - Chemins absolus pour
command,stdout_logfileetdirectory - Utilisateur dédié avec
user=pour ne pas exécuter les processus en root - Variables d’environnement avec
environment=plutôt que des scripts wrapper
Opérations
Section intitulée « Opérations »- Utilisez
reread+updateplutôt quereloadpour appliquer les changements sans tout redémarrer - Surveillez les processus en état FATAL : ils ne redémarreront pas seuls
- Configurez la rotation des logs (
stdout_logfile_maxbytes,stdout_logfile_backups) pour éviter de saturer le disque - Ajustez
startsecsà une valeur réaliste : trop bas génère de faux positifs, trop haut retarde la détection de problèmes
Sécurité
Section intitulée « Sécurité »- Ne jamais exposer l’interface web (
inet_http_server) sur un réseau non sécurisé - Protéger le fichier
supervisord.confen lecture seule pour les utilisateurs non privilégiés (il peut contenir des mots de passe en clair) - Utiliser le socket Unix (
unix_http_server) avec des permissions restreintes (chmod=0700) - Préférer le hachage SHA-1 pour les mots de passe :
password={SHA}hash_hex
À retenir
Section intitulée « À retenir »- Supervisor est un gestionnaire de processus simple et éprouvé, idéal pour les applications utilisateur et les conteneurs multi-processus
- Le fichier de configuration est au format INI, avec une section
[program:x]par programme supervisé - Les programmes supervisés ne doivent jamais se daemoniser : Supervisor doit rester le processus parent
supervisorctlpermet de démarrer, arrêter, redémarrer les processus et de consulter leurs logs- La directive
numprocspermet de lancer plusieurs instances d’un même programme - Les groupes (
[group:x]) regroupent des processus pour les contrôler ensemble - Dans Docker, utilisez toujours le flag
-n(nodaemon) et redirigez les logs vers/dev/stdout - Un processus en état FATAL nécessite une intervention manuelle : diagnostic puis
supervisorctl start
Prochaines étapes
Section intitulée « Prochaines étapes »Ressources
Section intitulée « Ressources »- Site officiel : supervisord.org
- Code source : github.com/Supervisor/supervisor
- Documentation configuration : supervisord.org/configuration.html
- Plugins tiers : supervisord.org/plugins.html