Im looking for something better than sudo restart projectname
every time I issue a git pull origin master
, which pulls down my latest changes to a Django project. This restart
command, I believe, is related to Upstart, which I use to start/top my Gunicorn server process.
This restart causes a brief outage. Users hitting the web server (nginx) will get a 500, because Gunicorn is still restarting. In fact, it seems to restart instantly, but it takes a few seconds for pages to load.
Any ideas on how to make this seamless? Ideally, I'd like to issue my git pull
and Gunicorn reloads automatically.
For a graceful reload, you should instead use Upstart's
reload
command, e.g.:According to the initctl (Upstart) manpage,
reload
will send aHUP
signal to the process:...which for Gunicorn will trigger a graceful restart (see FAQ).
Maybe not a direct answer to the question, but for those who are just looking for a way to restart
gunicorn
web server, you can usekillall gunicorn
and then execute a command to start gunicorn again. For example:Note:
killall gunicorn
will terminate all gunicorn processes immediately so make sure you understand what you are doing.For those not using supervisord: what Rob said, it works with ps as well,
You can tell Gunicorn to reload gracefully using the
HUP
signal like so:(see the FAQ for details)
I use Supervisor to control my Gunicorn server, which allows me to use this (slightly hacky) way of reloading Gunicorn after a deploy:
You could obviously achieve something similar with
pidof
, orps
.This is actually run from a Fabric script, so I don't even have to logon to the server at all.
Systemd, gunicorn & Ubuntu
Here is the one-liner, if you are running your gunicorn service with systemd.
Details step by step
Since the gunicorn docs tell that the correct way to gracefully reload the workers is by using
kill -HUP <Main PID>
, where<Main PID>
is the process id of the master process, we extract the master PID using systemctl, and runkill -HUP <Main PID>
.1) Get info about the process from systemd using the name of the service
where
gunicorn
is the name of the service, located at/etc/systemd/system/
.Example output:
2) Get the process ID (PID) of the main gunicorn process
The sed command works like follows:
sed 's/<search this>/<replace with this>/g'
s
means for the substitute command, andg
means that search the whole input globally.-n
flag tells sed not to print every line (or actually, not to print anything.)p
at the end tells sed to print the matched line..*Main PID: \(.*\)$
, which is a regular expression pattern, which has following parts:.*
matches any character (.
) zero or more times (*
). Then we search forMain PID:
followed by any characters, repeated zero or more times (.*
). To capture all characters after theMain PID:
-text, we enclose the.*
into parenthesis, which are escaped with backslashes:\(.*\)
.$
indicates line end.\1
, which means the first captured set of characters.Example output:
3) Get rid of the extra characters
Pipe the output to cut. The
cut -f1 -d' '
means, that-d
determines the delimiter, which is the characted just after the-d
. Since the delimiter is space, we enclose that in quotes.-f
means just that cutting is made using the delimiter (and not by bytes), and-f1
means that we want to take out the first element of the list.Example output:
4) Use the Main PID
Piping to xargs means just running the command with arguments from the pipe on the left hand side. Since we are piping just the Main PID to xargs,
is basically just the same thing as
which translates into
Edit
A little more robust solution would be to use
cut -f1 -d$'\n'
orgrep -m1 ""
in front ofcut -f1 -d' '
, to pick just the first line of the match. I can't figure out any circumstances, where there would be two matches for theMain PID:
, though.We run Gunicorn under Supervisor, but this is the simplest, cleanest way we've found to gracefully reload Gunicorn when it gets confused: