fmx — In-Container Service Manager¶
fmx is a small CLI tool that lives inside every Frappe Manager container. While fm is the host-side tool you use to create, start, and manage benches from your terminal, fmx is what controls the individual processes running inside a bench — the web server, workers, scheduler, and socket server.
You will not normally need fmx for day-to-day development. It becomes useful when you want to restart a single service without touching the whole bench, drain workers safely before a database migration, or debug a process that is stuck.
How it fits in¶
Your terminal
│
▼
fm (host CLI)
│ docker exec / compose exec
▼
frappe container
│
▼
fmx (in-container CLI)
│ Unix socket (supervisord)
▼
supervisord → frappe · short-worker · long-worker · schedule · socketio
fm manages Docker containers. fmx manages the supervisor-controlled processes inside one of those containers. Every bench shares the same container image, so fmx is always available.
Running fmx¶
From the host, pass a command through fm shell:
Or open an interactive shell first, then run fmx directly:
Tip
The fmx binary lives in the container's PATH, so no special path is needed once you are inside the shell.
Services fmx controls¶
| Name | What it is |
|---|---|
frappe |
Gunicorn web server (serves HTTP requests) |
short-worker |
RQ worker for short background jobs |
long-worker |
RQ worker for long-running jobs |
schedule |
Frappe scheduler (triggers recurring tasks) |
socketio |
Socket.IO server (realtime / desk notifications) |
Commands¶
fmx status — see what is running¶
Shows the supervisor state of every service and the live RQ worker status — suspend flag, queue depths, and registered workers.
Adds per-process detail: PID, uptime, current job per worker, and queue assignments. Useful when a queue has an unexpected backlog or a process looks stuck.
fmx start — start services¶
# Start everything
fmx start
# Start only the scheduler
fmx start schedule
# Start a specific process instance within a service
fmx start short-worker -p short-worker_1
fmx stop — stop services¶
# Stop everything immediately (running jobs are interrupted)
fmx stop
# Stop only the workers, leave web running
fmx stop short-worker long-worker
# Stop a single process instance
fmx stop long-worker -p long-worker_1
Draining workers before stopping¶
If workers may be processing jobs you cannot afford to lose (email sends, report generation, file imports), drain them first:
This sets a Redis suspend flag so workers stop picking up new jobs, then waits up to 5 minutes for every worker to become idle before stopping them.
# Extend the wait window for long-running jobs
fmx stop --drain-workers --drain-workers-timeout 600
# Speed up polling on busy systems
fmx stop --drain-workers --drain-workers-poll 10
fmx restart — restart services¶
This is the most-used fmx command. It stops and then starts the targeted services in parallel.
Workers are killed via SIGUSR1 (RQ's warm-shutdown signal). Any in-flight job may be interrupted. Fine for development where speed matters.
Workers stop picking up new jobs, fmx waits for all current jobs to finish, then restarts. No job is lost.
The safest production deploy sequence:
- Suspend workers — they stop accepting new jobs
- Wait for in-flight jobs to finish
- Run
bench migrate --skip-failing - Restart all services
Aborts cleanly if the migration fails.
Same as above but sets maintenance_mode=1 in common_site_config.json for each phase, so Frappe serves its built-in maintenance page to users. Always cleared on completion — even if something crashes mid-way.
Restart only specific services¶
Tuning the kill window¶
# Give workers up to 30 seconds to honour the shutdown signal before force-killing
fmx restart --worker-kill-timeout 30 --worker-kill-poll 2
fmx rq — manage RQ workers directly¶
For manual maintenance windows where you want to pause workers without restarting anything:
# Stop workers from picking up new jobs
fmx rq suspend
# Check suspend state and queue depths
fmx rq status
# Verbose: show active job per worker
fmx rq status --verbose
# Resume — workers start processing again immediately
fmx rq resume
When fmx rq suspend is useful
Before running a manual SQL migration or patching a custom app, suspend workers first so no background job touches the database while you are making changes.
Choosing a restart strategy¶
| Situation | Command |
|---|---|
| Dev environment, quick reload | fmx restart |
| Code push, no DB changes, keep jobs safe | fmx restart --drain-workers |
| Code push with DB migration | fmx restart --drain-workers --migrate |
| Production deploy with maintenance page | fmx restart --drain-workers --migrate --maintenance-mode drain --maintenance-mode migrate |
| Single broken worker, leave rest alone | fmx restart short-worker |
| System broken, fastest possible recovery | fmx restart (don't drain) |
Global options¶
| Flag | Description |
|---|---|
--verbose / -v |
More detail in status output |
--debug |
Show full stack traces on errors |
--version |
Print fmx version |
Where fmx comes from¶
fmx is built into the ghcr.io/rtcamp/frappe-manager-frappe Docker image — you do not install it separately. Its source code lives at Docker/frappe/fmx/ inside the Frappe Manager repository.
It communicates with each supervisor instance through a Unix socket at /fm-sockets/{service}.sock inside the container. The fm-sockets Docker volume is shared between the frappe container and other service containers so they can all be managed through the same interface.
VSCode integration¶
When you use fm code mybench to open a bench in VS Code, the generated .vscode/tasks.json includes an fm-kill-port task that runs:
This stops the Gunicorn web server before the VS Code debugger attaches — necessary because the debugger needs to bind to port 80 itself.