Control Interface (gunicornc)¶
Gunicorn provides a control interface similar to birdc for the BIRD routing daemon. This allows you to inspect and manage a running Gunicorn instance via a Unix socket.
Overview¶
The control interface consists of two parts:
- Control Socket Server - Runs in the arbiter process, accepts commands via Unix socket
- gunicornc CLI - Interactive client that connects to the control socket
Quick Start¶
Start Gunicorn with Control Socket¶
By default, Gunicorn creates a control socket at gunicorn.ctl in the current directory:
gunicorn -w 4 myapp:app
Or specify a custom path:
gunicorn --control-socket /tmp/myapp.ctl -w 4 myapp:app
Connect with gunicornc¶
# Connect to default socket (./gunicorn.ctl)
gunicornc
# Connect to custom socket
gunicornc -s /tmp/myapp.ctl
# Run a single command
gunicornc -c "show workers"
# Output as JSON (for scripting)
gunicornc -c "show stats" -j
Interactive Mode¶
When run without the -c flag, gunicornc enters interactive mode with readline support:
$ gunicornc
Connected to gunicorn.ctl
Type 'help' for available commands, 'quit' to exit.
gunicorn> show workers
PID AGE BOOTED LAST_BEAT
----------------------------------------
12345 1 yes 0.2s ago
12346 2 yes 0.1s ago
12347 3 yes 0.3s ago
Total: 3 workers
gunicorn> worker add 2
{
"added": 2,
"previous": 3,
"total": 5
}
gunicorn> quit
Commands¶
Show Commands¶
| Command | Description |
|---|---|
show all |
Overview of all processes (arbiter, web workers, dirty workers) |
show workers |
List HTTP workers with status |
show dirty |
List dirty workers and apps |
show config |
Show current effective configuration |
show stats |
Show server statistics |
show listeners |
Show bound sockets |
help |
Show available commands |
Worker Management¶
| Command | Description |
|---|---|
worker add [N] |
Spawn N workers (default 1) |
worker remove [N] |
Remove N workers (default 1) |
worker kill <PID> |
Gracefully terminate specific worker |
Dirty Worker Management¶
| Command | Description |
|---|---|
dirty add [N] |
Spawn N dirty workers (default 1) |
dirty remove [N] |
Remove N dirty workers (default 1) |
Per-App Worker Limits
When using dirty add, workers only load apps that haven't reached their
worker limits. If all apps are at their limits, no new workers will be spawned.
The response will include a reason field explaining this.
Server Control¶
| Command | Description |
|---|---|
reload |
Graceful reload (equivalent to SIGHUP) |
reopen |
Reopen log files (equivalent to SIGUSR1) |
shutdown [graceful\|quick] |
Shutdown server (SIGTERM or SIGINT) |
Example Session¶
$ gunicornc
Connected to gunicorn.ctl
Type 'help' for available commands, 'quit' to exit.
gunicorn> show all
ARBITER (master)
PID: 12345
WEB WORKERS (4)
PID AGE BOOTED LAST_BEAT
--------------------------------------
12346 1 yes 0.05s ago
12347 2 yes 0.04s ago
12348 3 yes 0.03s ago
12349 4 yes 0.02s ago
DIRTY ARBITER
PID: 12350
DIRTY WORKERS (2)
PID AGE APPS
--------------------------------------------------
12351 1 MLModel
ImageProcessor
12352 2 MLModel
gunicorn> show stats
Uptime: 2h 15m 30s
PID: 12345
Workers current: 4
Workers target: 4
Workers spawned: 6
Workers killed: 2
Reloads: 1
gunicorn> worker add
{
"added": 1,
"previous": 4,
"total": 5
}
gunicorn> dirty add 1
{
"success": true,
"operation": "add",
"requested": 1,
"spawned": 1,
"total_workers": 3,
"target_workers": 3
}
gunicorn> quit
Configuration¶
Settings¶
| Setting | CLI Flag | Default | Description |
|---|---|---|---|
control_socket |
--control-socket |
gunicorn.ctl |
Unix socket path |
control_socket_mode |
--control-socket-mode |
0o600 |
Socket file permissions |
control_socket_disable |
--no-control-socket |
False |
Disable control socket |
Example Configuration¶
# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 4
# Control socket settings
control_socket = "/var/run/gunicorn/myapp.ctl"
control_socket_mode = 0o660 # Allow group access
Scripting¶
Use the -j flag for JSON output when scripting:
#!/bin/bash
# Get current worker count
workers=$(gunicornc -c "show stats" -j | jq -r '.workers_current')
echo "Current workers: $workers"
# Scale up if needed
if [ "$workers" -lt 8 ]; then
gunicornc -c "worker add $((8 - workers))"
fi
Security¶
The control socket uses filesystem permissions for access control:
- Default mode:
0o600(owner only) - No authentication: Relies on filesystem permissions
- Unix socket only: No TCP/remote access
To allow group access:
control_socket_mode = 0o660
To disable the control socket entirely:
gunicorn --no-control-socket myapp:app
Protocol¶
The control interface uses a JSON-based protocol with length-prefixed framing:
+----------------+------------------+
| Length (4B BE) | JSON Payload |
+----------------+------------------+
Request Format¶
{
"id": 1,
"command": "show workers"
}
Response Format¶
{
"id": 1,
"status": "ok",
"data": { ... }
}
Error Response¶
{
"id": 1,
"status": "error",
"error": "Unknown command: foo"
}
Troubleshooting¶
Cannot connect to socket¶
Error: Connection refused
- Check that Gunicorn is running
- Verify the socket path is correct
- Check socket file permissions
Permission denied¶
Error: Permission denied
- Check that you have read/write access to the socket file
- The socket is created with mode
0o600by default (owner only)
Socket not found¶
Error: No such file or directory
- Gunicorn creates the socket relative to the working directory by default
- Use an absolute path with
--control-socket /path/to/socket.ctl - Check if
--no-control-socketwas specified