Supervises a configured set of long-running processes and presents them in a multi-pane TUI
dashboard — start them, watch each one's live output in its own pane, and let them restart on
their own. Think foreman/honcho with a built-in terminal UI, built on symfony/process and
symfony/tui.
It also knows how to run one messenger:consume worker per transport (--workflow), so you can
supervise a whole async pipeline with a single command instead of hand-starting a worker per queue.
composer require survos/supervisor-bundlesymfony/messenger is optional — only the --workflow queue discovery needs it; the supervisor
works as a generic process runner without it.
Create supervisor.yaml in your project root:
processes:
api:
cmd: ['php', 'bin/console', 'app:serve', '-v']
restart: always
worker:
cmd: ['php', 'bin/console', 'messenger:consume', 'async', '%verbosity%', '--time-limit=3600', '--memory-limit=512M']
restart: always
one-shot:
cmd: ['php', 'bin/console', 'app:warmup']
restart: never
ring_buffer_lines: 5000 # scrollback kept per process
follow_by_default: true # panes auto-scroll to the newest lineThen run the dashboard:
php bin/console survos:supervisor # ./supervisor.yaml (or bundle config)
php bin/console survos:supervisor -c deploy.yaml # an explicit config
php bin/console survos:supervisor --no-tui # stream prefixed lines instead of the TUIThe TUI enables mouse reporting while it is running. The scroll wheel moves through the selected process's log even while the process sidebar has keyboard focus. Scrolling down to the tail restores follow mode. Mouse reporting is disabled automatically when the dashboard exits.
Instead of a config file, point it at a transport code and it runs one supervised
messenger:consume per matching transport — discovered from the messenger transport registry, so it
needs no knowledge of how the queues were defined:
# Every transport named "dataset" or "dataset.*" → dataset.raw, dataset.normalize, dataset.enrich, …
php bin/console survos:supervisor --workflow=dataset
php bin/console survos:supervisor -w dataset --no-tuiThis is the one-command way to run and monitor an async workflow: the supervisor is both the runner (it spawns the consumers) and the monitor (each consumer's output in its own pane).
The supervisor's own verbosity flows down to the processes it spawns. In a cmd, the placeholder
%verbosity% expands to whatever the supervisor was started with:
| you run | %verbosity% becomes |
|---|---|
survos:supervisor |
(nothing — arg dropped) |
survos:supervisor -v |
-v |
survos:supervisor -vv |
-vv |
survos:supervisor -vvv |
-vvv |
survos:supervisor -q |
-q |
--workflow uses the placeholder for its generated consumers, so -w asset -vv gives you
very-verbose workers without any config. It matters for messenger:consume in particular: it only
reports per-message activity (received / handler / ack) from -vv upward, so at -v a slow queue
and a stuck queue look identical in the dashboard.
At normal verbosity the argument is dropped entirely rather than passed as an empty string — an
empty argv element is a real argument to the child (messenger:consume async '' would read it as a
second, nameless transport). You lose nothing by running workers at normal: monolog's
ConsoleHandler maps normal verbosity to Level::Warning, so $logger->error()/->warning() and
$io->error() still reach the pane, and errors survive even -q.
Commands that don't take console verbosity flags simply omit the placeholder.
Per process:
| key | default | meaning |
|---|---|---|
cmd |
(required) | argv array, e.g. ['php','bin/console','…'] |
restart |
never |
never · on-failure · always |
cwd |
(project dir) | working directory |
env |
{} |
extra environment variables |
autostart |
true |
start with the supervisor (vs. start it manually later) |
backoff |
— | restart backoff: initial (1.0s), max (30.0s), multiplier (2.0) |
Top level:
| key | default | meaning |
|---|---|---|
ring_buffer_lines |
5000 |
scrollback retained per process |
follow_by_default |
true |
panes follow the tail on launch |
| option | shortcut | description |
|---|---|---|
--config |
-c |
path to a supervisor YAML (default ./supervisor.yaml, then bundle config) |
--workflow |
-w |
supervise one messenger:consume per transport matching this code |
--no-tui |
disable the TUI; stream prefixed output lines to stdout |
MIT