Skip to main content

10 Hintergrund-Prozesse (Supervisor)

Hintergrund-Prozesse via Supervisor

Wenn dein Projekt einen Prozess braucht, der dauerhaft im Hintergrund laeuft (z.B. Symfony Messenger, Laravel Queue-Worker, ein Node.js-Daemon, ein eigener Watcher), kannst du ihn per Supervisor starten lassen. Der Prozess startet dann automatisch mit dem Container und wird bei Absturz neu gestartet — du musst nichts weiter tun.

Cron vs. Supervisor — Cron startet einen Prozess zu festen Zeitpunkten und laesst ihn nach getaner Arbeit sterben. Supervisor startet einen Prozess einmal und haelt ihn dauerhaft am Leben. Fuer Job-Queues (Messenger, Sidekiq, RQ etc.) willst du Supervisor.


Wo liegen die Config-Dateien?

Per SSH in deinen Container einloggen und dann:

cd ~/www/.webunit/supervisor.d/

Dieses Verzeichnis gehoert dir und ist vor Web-Zugriff geschuetzt (https://deine-domain/.webunit/... liefert 403).

Pro Prozess legst du eine <name>.conf-Datei an. Der Dateiname ist egal, die Endung .conf ist Pflicht.


Erstes Beispiel: Symfony Messenger

Datei: ~/www/.webunit/supervisor.d/messenger.conf

[program:messenger-consume]
command=/usr/local/bin/php /var/www/current/bin/console messenger:consume async --time-limit=3600 --memory-limit=256M
autostart=true
autorestart=true
stdout_logfile=/var/www/.webunit/logs/messenger.log
stderr_logfile=/var/www/.webunit/logs/messenger.err

Aktivieren:

webunit-supervisor reload

Status pruefen:

webunit-supervisor status

Ausgabe:

apache2                          RUNNING   pid 56, uptime 0:01:38
sshd                             RUNNING   pid 57, uptime 0:01:38
messenger-consume                RUNNING   pid 129, uptime 0:00:05

Fertig — der Worker laeuft, wird bei Container-Restart automatisch gestartet und bei Absturz neu gestartet.


Weitere Beispiele

Laravel Queue-Worker

[program:laravel-queue]
command=/usr/local/bin/php /var/www/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stdout_logfile=/var/www/.webunit/logs/queue.log
stderr_logfile=/var/www/.webunit/logs/queue.err

Node.js-Daemon

[program:my-node-daemon]
command=/usr/bin/node /var/www/current/daemon.js
directory=/var/www/current
environment=NODE_ENV="production",PORT="4000"
autostart=true
autorestart=true
stdout_logfile=/var/www/.webunit/logs/node.log
stderr_logfile=/var/www/.webunit/logs/node.err

Mehrere Worker parallel

Manche Queue-Systeme profitieren von mehreren parallelen Workern. Supervisor kennt dafuer numprocs:

[program:messenger-consume]
command=/usr/local/bin/php /var/www/current/bin/console messenger:consume async --time-limit=3600
numprocs=3
process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
stdout_logfile=/var/www/.webunit/logs/messenger_%(process_num)02d.log
stderr_logfile=/var/www/.webunit/logs/messenger_%(process_num)02d.err

Das startet 3 Instanzen: messenger-consume_00, _01, _02.

Einfacher Bash-Loop (zum Testen)

[program:testworker]
command=/bin/bash -c "while true; do date; sleep 5; done"
autostart=true
autorestart=true
stdout_logfile=/var/www/.webunit/logs/testworker.log
stderr_logfile=/var/www/.webunit/logs/testworker.err

Kommandos

Alle Kommandos rufst du im Container-SSH ohne sudo auf.

Kommando Was es macht
webunit-supervisor reload Liest *.conf neu ein und startet neue/geaenderte Programme. Sanitize-Check laeuft vorher.
webunit-supervisor status Zeigt Status aller Programme (deine + apache2 + sshd).
webunit-supervisor restart <name> Startet ein Programm neu.
webunit-supervisor tail <name> Zeigt letzte Zeilen von stdout.
webunit-supervisor tail-err <name> Zeigt letzte Zeilen von stderr.
webunit-supervisor validate Prueft nur die Configs, ohne Reload.
webunit-supervisor help Alle Kommandos.

restart und tail auf apache2 oder sshd werden abgelehnt — das sind System-Prozesse.


Config-Format (Kurz-Referenz)

Wichtige Direktiven fuer [program:...]:

Direktive Bedeutung
command= Vollstaendiger Pfad zum Binary + Argumente. Kein sudo.
directory= Arbeitsverzeichnis vor dem Start.
environment=KEY="value",KEY2="value2" Zusaetzliche Umgebungsvariablen.
autostart=true Beim Container-Start automatisch starten.
autorestart=true Nach Absturz neu starten.
startsecs=1 Sekunden Wartezeit, bis der Start als erfolgreich gilt.
startretries=3 Nach so vielen Fehl-Starts aufgeben und FATAL markieren.
stopsignal=TERM Signal zum Stoppen (TERM, INT, KILL).
stopwaitsecs=10 Wartezeit auf sauberes Beenden, bevor KILL.
stdout_logfile=<pfad> Datei fuer stdout. Standard sind Dateien unter /var/www/.webunit/logs/.
stderr_logfile=<pfad> Datei fuer stderr.
stdout_logfile_maxbytes=50MB Rotate nach 50 MB (Standard).
stdout_logfile_backups=10 Anzahl rotierter Backups (Standard 10).
numprocs=N N parallele Instanzen des Programms.
process_name=%(program_name)s_%(process_num)02d Namensschema bei numprocs>1.

Vollstaendige Referenz: http://supervisord.org/configuration.html#program-x-section-values


Was NICHT erlaubt ist

Der Sanitize-Check beim reload blockt:

  • user=root oder user=0 — Programme laufen als Container-User.
  • umask=... — greift zu tief in Prozess-Umgebung ein.
  • stopasuser=root oder stopasuser=0 — analog.
  • Programm-Namen apache2, sshd, supervisord — reserviert fuer System-Prozesse.
  • Andere Sektionen als [program:...], [group:...] oder [eventlistener:...] — die anderen (z.B. [supervisord]) wuerden die globale Container-Config beeinflussen.

Bei Fehlern zeigt webunit-supervisor validate (oder reload) genau welche Zeile in welcher Datei das Problem ist:

FEHLER: /var/www/.webunit/supervisor.d/messenger.conf:3 — user=root ist nicht erlaubt (nur Container-User)

Logs

  • stdout / stderr deiner Prozesse landen in den Dateien, die du in der Config angibst. Empfehlung: /var/www/.webunit/logs/<name>.log.
  • Rotation: Supervisor rotiert automatisch bei 50 MB, haelt 10 Backups. Aendern via stdout_logfile_maxbytes= und stdout_logfile_backups=.
  • Live mitlesen: webunit-supervisor tail <name> (stdout) bzw. tail-err (stderr) — zeigt die letzten ~1000 Zeilen.
  • Selbst gucken: tail -f /var/www/.webunit/logs/messenger.log.
  • Web-Zugriff geblockt: /.webunit/* liefert immer 403, deine Logs sind also nicht von aussen einsehbar.

Was passiert bei Container-Neubau?

Deine ~/www/.webunit/supervisor.d/-Configs bleiben erhalten (liegen im /var/www-Volume). Nach dem Neubau starten sie automatisch mit dem Container.

Die generierte README.txt im Verzeichnis kommt nur einmal beim allerersten Container-Start rein — wenn du sie loeschst, wird sie nicht neu geschrieben.


Troubleshooting

Prozess ist im Status FATAL

webunit-supervisor status zeigt FATAL. Das heisst Supervisor hat den Prozess mehrfach versucht zu starten und aufgegeben. Ursache findest du in stderr:

webunit-supervisor tail-err <name>

Typische Fehler:

  • Falscher Pfad im command=
  • Fehlende Berechtigungen auf einer Datei
  • Datenbank nicht erreichbar
  • Node-Modules / vendor/ nicht installiert

Fix, dann:

webunit-supervisor restart <name>

Prozess ist im Status EXITED

Er ist normal beendet (Exit-Code 0), Supervisor startet ihn aber nicht neu. Vermutlich hast du autorestart=false oder der Command endet tatsaechlich (z.B. time-limit bei Messenger). Bei Messenger ist das gewollt — autorestart=true startet ihn dann wieder.

webunit-supervisor: command not found

Das kann eigentlich nicht passieren — das Binary liegt im PATH. Wenn doch, ist entweder dein Container aelter als 2026-09-03 (dann sag uns Bescheid, wir rebuilden) oder der PATH ist in deinem .bashrc ueberschrieben.

Config aendert sich nicht

Nach dem Editieren einer .conf musst du explizit reload fahren. Supervisor sieht Datei-Aenderungen nicht von allein.

webunit-supervisor reload

"Sanitize-Check fehlgeschlagen — Reload abgebrochen"

Der Reload wird abgebrochen wenn irgendeine deiner .conf einen Fehler hat. Fix die betroffene Datei (die genaue Zeile steht in der Fehlermeldung), dann nochmal reload.