How to Perform a Graceful uWSGI Reload for Django Applications via Bash Script


2 views

When managing a Django application with uWSGI and Nginx, you might need to reload configurations without causing downtime. While /etc/init.d/nginx reload works smoothly for Nginx, uWSGI requires a different approach for a graceful reload.

uwsgi.reload Might Not Work /h2>

Calling uwsgi.reload() in Python or using restart uwsgi in bash often only affects the current worker process. This is insufficient when hosting multiple sites under a single uWSGI instance.

uWSGI provides a graceful reload mechanism through its master FIFO pipe. Here's how to implement it:

# First, ensure your uWSGI configuration includes:
# master-fifo = /path/to/your/fifo.sock
# Then send the reload command:
echo r > /path/to/your/fifo.sock

Here's a complete bash script that handles both Nginx and uWSGI reloads gracefully:

#!/bin/bash

# Reload Nginx
/etc/init.d/nginx reload

# Graceful uWSGI reload
UWSGI_FIFO="/path/to/your/fifo.sock"
if [ -p "$UWSGI_FIFO" ]; then
    echo r > "$UWSGI_FIFO"
    echo "Sent graceful reload signal to uWSGI"
else
    echo "uWSGI FIFO not found at $UWSGI_FIFO"
    exit 1
fi

If you need to trigger this from Django:

import subprocess

def graceful_reload():
    try:
        # Reload Nginx
        subprocess.run(['/etc/init.d/nginx', 'reload'], check=True)
        
        # Graceful uWSGI reload
        with open('/path/to/your/fifo.sock', 'w') as fifo:
            fifo.write('r')
        return True
    except Exception as e:
        print(f"Reload failed: {str(e)}")
        return False

After sending the reload signal, check your uWSGI logs for confirmation. You should see messages like:

gracefully (RE)spawned uWSGI worker

Another common method is using touch-reload:

# In your uWSGI config:
touch-reload = /path/to/trigger/file

# Then trigger reload by:
touch /path/to/trigger/file

When managing Django applications with uWSGI, many developers face a common challenge: how to reload uWSGI gracefully without affecting all running processes. The standard approaches like restart uwsgi or uwsgi.reload() in Python often only affect the calling process rather than all hosted sites.

uWSGI provides several methods for graceful reloads:

  • Sending SIGHUP to the master process
  • Using the --touch-reload option
  • Employing the uWSGI signal framework

Here's a robust bash script solution that properly reloads all uWSGI processes:

#!/bin/bash
# Gracefully reload uWSGI without restarting all processes
UWSGI_PID=$(cat /var/run/uwsgi.pid)

if [ -f "$UWSGI_PID" ]; then
    kill -HUP $UWSGI_PID
    echo "uWSGI reload signal sent successfully"
else
    echo "uWSGI pid file not found at /var/run/uwsgi.pid"
    exit 1
fi

For Django applications that need to trigger reloads programmatically:

import os
import signal

def graceful_uwsgi_reload():
    try:
        with open('/var/run/uwsgi.pid') as f:
            pid = int(f.read())
        os.kill(pid, signal.SIGHUP)
        return True
    except Exception as e:
        print(f"Failed to reload uWSGI: {str(e)}")
        return False

For more control over the reload behavior, consider these uWSGI configuration options:

[uwsgi]
master = true
processes = 4
touch-reload = /path/to/reload.trigger
lazy-apps = true

After sending the reload signal, verify it worked by checking the uWSGI logs:

tail -f /var/log/uwsgi.log | grep -i "reload"

You should see messages indicating successful worker respawning without master process restart.

  • Permission issues: Ensure your script has rights to read the pid file and send signals
  • Missing master process: The master process must be running for graceful reload to work
  • Configuration errors: Verify lazy-apps is set correctly for your use case