Pi Awesome

Reference and guides to build kick ass raspberry pi projects.

View the Project on GitHub codingforentrepreneurs/Pi-Awesome

Gunicorn & Supervisor

In this post we setup supervisor to run gunicorn. In this one, we’re going to dive in a little deeper and create a more resilient method for running this application.

via a development server. Now we’re going to setup supervisor to use gunicorn as a production-ready web server gateway interface (wsgi).

Current Status

My app Supervisor config (project.supervisor.conf)

[program:flaskapp]
user=pi
directory=/home/pi/app
command=/home/pi/app/bin/gunicorn wsgi:app
 
autostart=true
autorestart=true
stdout_logfile=/var/log/www/flaskapp/stdout.log
stderr_logfile=/var/log/www/flaskapp/stderr.log

As mentioned in the linked post above, we have the correct permissions for each folder listed above.

This line /home/pi/app/bin/gunicorn wsgi:app does not cover the possible configuration we might need for gunicorn. So we’re going to convert it to run off a bash script called run.sh located right in our project directory (/home/pi/app). This means my supervisor configuration won’t have to change when my gunicorn configuration does.

1. Create run.sh

I create a bash script as my entry command for running my python web application.

In my case, the root of my application is on /home/pi/app so that’s where I’ll store it: /home/pi/app/run.sh

#!/bin/bash

exec /home/pi/app/bin/gunicorn --pid /home/pi/app/flaskapp.pid  --bind 0.0.0.0:8000 wsgi:app

Let’s break this down:

2. Update /etc/supervisor/conf.d/project.supervisor.conf

[program:flaskapp]
user=pi
directory=/home/pi/app
command=sh run.sh
 
autostart=true
autorestart=true
stdout_logfile=/var/log/www/flaskapp/stdout.log
stderr_logfile=/var/log/www/flaskapp/stderr.log

The only change is command=sh run.sh

3. Reread and Update supervisor

sudo supervisorctl reread
sudo supervisorctl update

4. Revisiting Process ID File (PID)

What was the point of adding --pid /home/pi/app/flaskapp.pid to our run.sh?

There’s a few questions that come to mind that pid can help solve:

There are likely many other questions that come to mind but to me these are the questions I get the most often.

How to check what’s running on any PORT?
sudo lsof -i :8011

or

sudo lsof -i :8000

If there is a process running, this command will show it. Just change 8011 or 8000 to the port number you want to review. If you have nginx listening on PORT 80 you could try sudo lsof -i :80 to see if it’s actually listening.

Here’s an example response:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
gunicorn 4892   pi    5u  IPv4  62193      0t0  TCP localhost:8000 (LISTEN)
gunicorn 4895   pi    5u  IPv4  62193      0t0  TCP localhost:8000 (LISTEN)

If you wanted to stop/kill one of these processes, you can just run kill <pid> like:

kill 4892

You can also use the --pid /home/pi/app/flaskapp.pid to do this with less steps:

kill $(cat /home/pi/app/flaskapp.pid)

cat /home/pi/app/flaskapp.pid will yield the contents of the file (as you may know). $(cat /home/pi/app/flaskapp.pid) yeilds the contents of the file as an argument to a command.

If you have supervisor setup correctly, a new flaskapp.pid file should so up almost right away. This is because we have our supervisor config to include autorestart=true.

Pretty neat huh?

5. Standard Supervisor control commands for our app

sudo supervisorctl status 
sudo supervisorctl status flaskapp
sudo supervisorctl start flaskapp
sudo supervisorctl stop flaskapp
sudo supervisorctl restart flaskapp