procman
A foreman-like process supervisor written in Rust. Reads a procman.yaml, spawns all listed commands, multiplexes their output with name prefixes, and tears everything down cleanly when any child exits or a signal arrives.
Usage
cargo install --path .
procman run — run all commands
Bare procman with no subcommand is equivalent to procman run.
procman serve — accept dynamic commands via a FIFO
&
Runs all procman.yaml commands and listens on a named FIFO for dynamically added commands. The FIFO is created automatically and removed on exit.
procman start — send a command to a running server
Opens the FIFO for writing and sends a JSON message. Fails immediately if no server is listening.
procman stop — gracefully shut down a running server
Sends a shutdown command to the server via the FIFO. The server logs the request and terminates cleanly.
Scripted service bringup
The serve/start pattern enables imperative orchestration — start a supervisor, wait for dependencies to become healthy, then add dependent services:
&
while ; do ; done
An advisory flock on procman.yaml prevents multiple instances from managing the same file simultaneously.
procman.yaml Format
web:
env:
PORT: "3000"
run: serve --port $PORT
migrate:
run: db-migrate up
once: true
api:
depends:
- process_exited: migrate
- url: http://localhost:3000/health
code: 200
poll_interval: 0.5
timeout_seconds: 30
run: api-server start
setup:
depends:
- path: /tmp/ready.flag
run: post-setup-task
- Each top-level key is a process name.
run(required): the command to execute (parsed with POSIX shell quoting).env(optional): per-process environment variables.once(optional): iftrue, the process exits cleanly on success (code 0) without triggering supervisor shutdown.depends(optional): list of dependencies that must be satisfied before the process starts.- HTTP health check:
url+code(expected status), with optionalpoll_intervalandtimeout_seconds. - File exists:
pathto a file that must exist. - Process exited:
process_exitednames aonce: trueprocess that must complete successfully before this process starts.
- HTTP health check:
Behavior
- All children share a process group.
- stderr is merged into stdout per-process.
- Output is prefixed with the process name, right-aligned and padded.
- Per-process logs are written to
./procman-logs/<name>.log(directory is recreated each run). - A combined
./procman-logs/procman.logcontains the full interleaved formatted output (same as stdout). - On SIGINT or SIGTERM, all children receive SIGTERM. After a 2-second grace period, remaining processes are sent SIGKILL.
- procman exits with the first child's exit code.
License
MIT