cmd / procman
procman is a process manager for local development on macOS.
It is open source.
Install:
go install github.com/croaky/procman@main
Define processes in Procfile.dev. For example:
clock: bundle exec ruby cmd/clock.rb
esbuild: ./bin/build-js --watch
queues: bundle exec ruby cmd/queues.rb
web: bundle exec ruby cmd/web.rb
Run processes by name, comma-delimited:
procman esbuild,web
There are no options or flags.
procman multiplexes process output:
esbuild | bundling js/app.ts, css/app.css
esbuild | watching...
web | Listening on http://0.0.0.0:3000
procman runs until it receives SIGINT (Ctrl+C), SIGTERM, or
SIGHUP. When one process exits, procman sends SIGINT to the others,
waits 5 seconds, and sends SIGKILL to any process that remains. It
runs one process per definition and does not load .env.
File watching
Add # watch: PATTERNS to restart a process when files change:
clock: bundle exec ruby cmd/clock.rb # watch: lib/**/*.rb
esbuild: ./bin/build-js --watch
queues: bundle exec ruby cmd/queues.rb # watch: lib/**/*.rb
web: bundle exec ruby cmd/web.rb # watch: lib/**/*.rb,ui/views/**/*.haml
Patterns are relative to the directory containing Procfile.dev.
Globs support * (single directory) and ** (recursive).
Separate patterns with commas.
procman ignores paths in .gitignore, so build output does not consume
watch descriptors.
On file changes, procman sends SIGINT, waits for exit, and restarts
the process. It debounces changes with a 100ms window and serializes
restarts per process.
Kill a process on a port
When a process outlives procman and holds its port, a script on
$PATH clears it:
kill-pid-on-port 3000
#!/bin/bash
set -euo pipefail
lsof -n -i :"$1" | grep LISTEN | awk '{ print $2 }' | xargs kill
lsof -ti :3000 | xargs kill is shorter, but -ti returns every
process on the port, clients included. grep LISTEN limits it to the
server.