[Solved]-Mod_wsgi: Reload Code via Inotify – not every N seconds

4👍

Preliminaries.

Developers can use runserver or mod_wsgi. Using runserver has the
benefit that you it easy for debugging, mod_wsgi has the benefit that
you don’t need to start the server first.

But you do, the server needs to be setup first and that takes a lot of effort. And the server needs to be started here as well though you can configure it to start automatically at boot.

If you are running on port 80 or 443 which is usually the case, the server can be started only by the root. If it needs to be restarted you will have to ask the super user’s help again. So ./manage.py runserver scores heavily here.

mod_wsgi has the benefit, that you know the URL:
https://dev-server/system-name/myurl/

Which is no different from the dev server. By default it starts on port 8000 so you can access it as http://dev-server:8000/system-name/myurl/. If you wanted to use SSL with the development server you can use a package such as django-sslserver or you can put nginx in front of django development server.

With runserver you don’t know the port. Use case: You want to link from >an internal wiki to a dev-system ….

With runserver, the port is well defined as mentioned above. And you can make it listen on a different port for exapmle with:

 ./manage.py runserver 0.0.0.0:9090

Note that if you put development server behind apache (as a reverse proxy) or NGINX, restarting problems etc that I have mentioned above do not apply here.

So in short, for development work, what ever you do with mod_wsgi can be done with the django development server (aka ./manage.py runserver).

Inotify

Here we are getting to the main topic at last. Assuming you have installed inotify-tools you could type this into your shell. You don’t need to write a script.

  while inotifywait -r -e modify .; do sudo kill -2 yourpid ; done

This will result in the code being reloaded when …

… using daemon mode with a single process you can send a SIGINT
signal to the daemon process using the ‘kill’ command, or have the
application send the signal to itself when a specific URL is
triggered.
ref: http://modwsgi.readthedocs.io/en/develop/user-guides/frequently-asked-questions.html#application-reloading

alternatively

while inotifywait -r -e modify .; do touch wsgi.py ; done

when

… using daemon mode, with any number of processes, and the process
reload mechanism of mod_wsgi 2.0 has been enabled, then all you need
to do is touch the WSGI script file, thereby updating its modification
time, and the daemon processes will automatically shutdown and restart
the next time they receive a request.

In both situations we are using the -r flag to tell inotify to monitor subdirectories. That means each time you save a .css or .js file apache will reload. But without the -r flag changes to python code in subfolders will be undetected. To have the best of both worls, remove css, js, images etc with the --exclude directive.

What about when your IDE saves an auto backup file? or vim saves the .swp file? That too will cause a code reload. So you would have to exclude those file types too.

So in short, it’s a lot of hard work to reproduce what the django development server does free of charge.

👤e4c5

3👍

You can use inotify hooktables to run any command you want depending on a i-notify signal (here’s my source link: http://terokarvinen.com/2016/when-files-change-take-action-inotify-hookable).

After looking the tables you can just reload the code of apache.

For your specific problem, it should be something like:

inotify-hookable --watch-directories sources/ --recursive --on-modify-command './code_reload.sh'

In the previous link, the command to execute was just a simple touch flask/init.wsgi

So, the whole code (adding ignored files was):

inotify-hookable --watch-directories flask/ --recursive  --ignore-paths='flask/init.wsgi' --on-modify-command 'touch flask/init.wsgi'

As stated here: Flask + mod_wsgi automatic reload on source code change, if you have enabled WSGIScriptReloading, you can just touch that file. It will cause the entire code to reload (not just the config file). But, if you prefer, you can set any other script to reload the code.

After googling a bit, it seems to be a pretty standard solution for that problem and I think that you can use it for your application.

Leave a comment