Resque in operations: starting, stopping, and killing workers
Resque Series — part 1 of 3
- You are here — Infra: starting, stopping, killing
- Diagnosis via console
- Mass manipulation of jobs and workers
Why this series exists — I spent a long time working on projects that used Sidekiq, and during that process I compiled my notes into the Sidekiq series. I then ended up joining a project that uses Resque — that generated new notes, which I kept in the same structure as the ones I’d already written for Sidekiq. The operational problems are the same (queues that fill up, batch-failing jobs, deployments that need to drain workers), but the tools differ quite a bit. This series is the mirror of that one for topics that translate well: infra, diagnosis, and mass manipulation, with the equivalent commands in Resque. Where a topic has a direct parallel, I’ll link to the corresponding post in the Sidekiq series.
The first important model difference: Resque is process-per-job, Sidekiq is thread-per-job. Each Resque worker listens to one or more queues and, when it picks up a job, forks a child process that executes the job and exits. This changes how you start, drain, and kill — because there are always two related processes (the parent worker and the child that is executing).
API documentation: github.com/resque/resque.
Starting Resque
1
QUEUE=* bundle exec rake resque:work
QUEUE=*makes the worker consume all queues that exist in Redis.QUEUE=critical,high,defaultlistens in priority order — drainscriticalbefore touchinghigh.
Starting multiple workers on a single machine:
1
COUNT=5 QUEUE=* bundle exec rake resque:workers
In the background with a PID file (useful for kill later):
1
PIDFILE=./tmp/pids/resque.pid BACKGROUND=yes QUEUE=* bundle exec rake resque:work
In production this lives in systemd or foreman, but for a VPS or test environment BACKGROUND=yes + PIDFILE covers the need.
Unlike Sidekiq, there is no
-C config/sidekiq.yml. Concurrency in Resque comes from starting N processes (not threads), so the “configuration” is how manyrake resque:workprocesses you have running.
Draining gracefully (QUIT — recommended)
1
kill -QUIT $(cat tmp/pids/resque.pid)
QUIT is the polite signal: the worker waits for the current job to finish (in the child process), then exits cleanly. The moral equivalent of sidekiqctl stop from part 1 of the Sidekiq series — preserves idempotency if the worker is in the middle of a non-atomic operation.
If you don’t have the PID file, you can extract it via ps:
1
2
ps -ef | grep '[r]esque' | grep -v 'master' | awk '{print $2}'
kill -QUIT $(ps -ef | grep '[r]esque' | grep -v 'master' | awk '{print $2}')
The [r]esque trick is the classic way to prevent grep itself from appearing in the results.
Killing the child but keeping the worker (TERM/USR1)
Because Resque forks per job, you can kill only the running job without bringing down the parent worker:
1
2
3
4
5
# TERM on the worker: kills the child immediately AND shuts down the worker
kill -TERM $(cat tmp/pids/resque.pid)
# USR1 on the worker: kills the child immediately, but the worker stays up and picks the next job
kill -USR1 $(cat tmp/pids/resque.pid)
USR1 is the right tool for “this specific job is stuck and holding the worker, but I don’t want to take down the infrastructure”. The job becomes a failure, the worker returns to the loop.
Pausing without killing (USR2 / CONT)
1
2
3
4
5
# USR2: stops picking up new jobs (doesn't end the current one, just won't pick up the next)
kill -USR2 $(cat tmp/pids/resque.pid)
# CONT: resumes picking up jobs
kill -CONT $(cat tmp/pids/resque.pid)
This pair is Resque’s equivalent of Sidekiq::ProcessSet#quiet! that appears in part 3 of the Sidekiq series. Useful for deployment: USR2 all workers, wait for in-progress jobs to finish, deploy, CONT to resume.
Last resort (KILL)
1
kill -9 $(cat tmp/pids/resque.pid)
KILL (-9) kills the worker and orphans any child process in execution — those children become zombie processes until init reaps them, and the running job disappears without becoming a failure (because the worker had no time to register it). Use only when:
QUITis stuck and not responding- The worker is consuming memory without doing anything visible
- There is a fire and bringing it down is more important than preserving state
Signal summary
| Signal | Effect |
|---|---|
QUIT |
Finishes in-progress jobs, then exits (graceful) |
TERM |
Kills the child immediately and exits |
USR1 |
Kills the child immediately, keeps the worker running |
USR2 |
Stops picking up new jobs (pause) |
CONT |
Resumes picking up jobs (resume) |
KILL (-9) |
Kills the worker, orphans children |
Next in the series
Resque diagnosis via console — Resque.info, queue counts, worker listing and what each one is doing.