Understanding Supervisor’s directory Configuration: Why Celery Doesn’t Inherit Working Directory and How to Fix It


1 views

When configuring Supervisor to manage Celery processes, many developers encounter an unexpected behavior - the working directory specified in Supervisor's configuration doesn't seem to take effect. Despite setting the directory parameter in the program section of supervisord.conf, running pwd within the Celery process shows the root directory (/).

[program:celery_worker]
command=/path/to/celery -A project worker
directory=/path/to/project
autostart=true
autorestart=true

This happens because Celery, when started, may change its working directory internally. Supervisor does properly set the initial working directory, but some applications (including Celery) subsequently modify this during their initialization process.

Here are several approaches to ensure your Celery workers run in the correct directory:

1. Using Celery's --workdir Parameter

The most straightforward solution is to use Celery's built-in --workdir option:

[program:celery_worker]
command=/path/to/celery -A project worker --workdir=/path/to/project
autostart=true
autorestart=true

2. Wrapping with a Shell Script

For more complex setups, create a wrapper script:

#!/bin/bash
cd /path/to/project
exec /path/to/celery -A project worker

Then configure Supervisor to use this script:

[program:celery_worker]
command=/path/to/wrapper_script.sh
autostart=true
autorestart=true

3. Combining Supervisor directory and Celery --workdir

For maximum reliability, use both approaches:

[program:celery_worker]
command=/path/to/celery -A project worker --workdir=/path/to/project
directory=/path/to/project
autostart=true
autorestart=true

To confirm your Celery worker is running in the correct directory, add this to your task:

import os

@app.task
def check_working_dir():
    return {'working_directory': os.getcwd()}

Call this task and verify the output matches your expected directory.


When configuring Supervisor to manage Celery processes, many developers encounter a puzzling behavior: the directory parameter in supervisord.conf appears to have no effect on the working directory of the spawned process. Running pwd inside the script typically returns / instead of the specified directory.

Supervisor's directory option serves a specific purpose in the process lifecycle:


[program:my_celery_worker]
command=/path/to/celery -A project worker
directory=/path/to/project

The directory parameter sets the working directory before the command executes, but certain applications (like Celery) may subsequently change it during initialization.

Celery has its own workdir concept because:

  • It needs to resolve relative paths in configuration
  • It manages multiple worker processes that might need different working directories
  • It provides process isolation between different task queues

Here are three ways to ensure proper working directory behavior:

1. Using Celery's built-in workdir


[program:celery_worker]
command=/path/to/celery -A project worker --workdir=/path/to/project

2. Wrapping with shell script


#!/bin/sh
cd /path/to/project
exec /path/to/celery -A project worker

3. Combining both approaches


[program:celery_worker]
command=/path/to/wrapper_script.sh
directory=/path/to/project

To verify the working directory at different stages:


# In your Python code:
import os
print("Current directory:", os.getcwd())

# In your bash wrapper:
echo "Starting in: $(pwd)"

The Supervisor directory parameter is still crucial for:

  • Resolving relative paths in the command itself
  • Managing log file locations
  • Setting environment variables via .env files