<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mathieu Agopian &#187; mod_wsgi</title>
	<atom:link href="http://mathieu.agopian.info/blog/category/mod_wsgi/feed/" rel="self" type="application/rss+xml" />
	<link>http://mathieu.agopian.info/blog</link>
	<description>Un blog utilisant WordPress</description>
	<lastBuildDate>Tue, 31 Aug 2010 15:48:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>lancer gunicorn avec supervisord</title>
		<link>http://mathieu.agopian.info/blog/2010/08/lancer-gunicorn-avec-supervisord/</link>
		<comments>http://mathieu.agopian.info/blog/2010/08/lancer-gunicorn-avec-supervisord/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 15:48:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[système]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[supervisord]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=337</guid>
		<description><![CDATA[Après avoir mis en place une méthode pour lancer gunicorn avec runit, voici un second article pour lancer ce même gunicorn (qui poutre du poney, rappelons-le), mais avec un outil que je trouve à l&#8217;utilisation bien plus pratique : supervisord Pourquoi supervisord et pas runit ? Après l&#8217;avoir utilisé sans aucun soucis depuis quelques temps sur [...]]]></description>
			<content:encoded><![CDATA[<p>Après avoir mis en place une méthode pour <a title="Lancer gunicorn avec runit" href="http://mathieu.agopian.info/blog/2010/02/lancer-gunicorn-avec-runit/" target="_self">lancer gunicorn avec runit</a>, voici un second article pour lancer ce même <a title="Site officle de Green Unicorn" href="http://gunicorn.org/" target="_self">gunicorn</a> (qui poutre du poney, rappelons-le), mais avec un outil que je trouve à l&#8217;utilisation bien plus pratique : <a title="Site officiel de supervisord" href="http://supervisord.org/index.html" target="_blank">supervisord</a></p>
<h3>Pourquoi supervisord et pas runit ?</h3>
<p>Après l&#8217;avoir utilisé sans aucun soucis depuis quelques temps sur le serveur de secours de notre site web, je trouve que supervisord est plus convivial à utiliser, et plus &laquo;&nbsp;clair&nbsp;&raquo; à mettre en place.</p>
<p>Plus convivial à utiliser parce qu&#8217;il a un client CLI qui permet d&#8217;interagir directement avec les processus monitorés, mais il y a aussi les mêmes fonctionnalités par le biais d&#8217;une interface web fort pratique.</p>
<p>Plus &laquo;&nbsp;clair&nbsp;&raquo; à mettre en place parce qu&#8217;il se lance grâce à un simple script d&#8217;init, et qu&#8217;on peut faire la configuration de tous ses processus à monitorer dans un seul et même fichier de configuration, au lieu d&#8217;avoir un répertoire et des liens symboliques à gérer (certains préfèrent peut-être cette modularité, mais personnellement je trouve ça beaucoup plus pénible à maintenir).</p>
<h4>Installer supervisord</h4>
<p>Etant donné que supervisord est en python, il est possible de l&#8217;installer avec un simple</p>
<pre>$ pip install supervisor</pre>
<p>Pour les <em>old-school</em> qui ne profitent pas encore de la puissance et de l&#8217;ergonomie de ce magnifique outil de Ian Bicking, il est possible de remplacer <em>pip</em> par <em>easy_install</em> (même si je vous conseille plutôt de faire un <em>easy_install pip</em> puis de vous passer de <em>easy_install</em> par la suite!).</p>
<h4>Configurer supervisord</h4>
<p>On le configure en deux temps : une première configuration de supervisord lui-même, puis l&#8217;ajout des processus qu&#8217;on veut qu&#8217;il monitore.</p>
<p>Dans le fichier <em>/etc/supervisord.conf</em> :</p>
<pre>; configuration de supervisord lui-meme
[unix_http_server]
file=/tmp/supervisor.sock   ; chemin vers le fichier socket

[inet_http_server]
port=192.168.0.21:9001      ; adresse ip _LOCALE_ de la machine pour la connection web

[supervisord]
logfile=/var/log/supervisord.log ; fichier de log principal de supervisord

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; connection pour le client CLI

; liste des processus qu'on veut confier a supervisord
[program:gu-www]
command=/path/to/venv/bin/python /path/to/venv/bin/gunicorn_django -b localhost:8080 --log-file=/path/to/log/gunicorn_gu-www.log --workers=3
directory=/folder/containing/settings/file/
user=www-data
autostart=true
autorestart=true
startsecs=10
redirect_stderr=true
stdout_logfile=/path/to/log/supervisor_gu-www.log</pre>
<p>Bien entendu, faites en sortes que l&#8217;utilisateur <em>www-data</em> ai accès en écriture aux fichiers de log <em>gunicorn_gu-www.log</em> configuré où le processus échouera lors de son lancement.</p>
<p><strong><span style="color: #ff0000;"><span style="text-decoration: underline;">ATTENTION:</span></span></strong> comme indiqué dans le commentaire pour la ligne de configuration <em>inet_http_server</em> il faut absolument faire en sorte que l&#8217;adresse ne soit pas accessible à tout le monde! En effet il est possible de redémarrer ou tout simplement stopper les processus par cette interface! Vous pouvez désactiver complètement cette possibilité en supprimant ces deux lignes, il n&#8217;y aura alors pas de moyen de contrôler supervisord par une page web.</p>
<p>La commande indiquée pour information lance <em>gunicorn_django</em> avec dans un environnement virtuel (ce que vous devriez faire vous aussi!). Il n&#8217;est pas nécessaire d&#8217;indiquer le chemin vers le fichier <em>settings.py</em> dans les options de <em>gunicorn_django</em> étant donné que le processus sera lancé directement dans le répertoire le contenant (si vous le configurez correctement avec le paramètre <em>directory</em> comme indiqué ci-dessus).</p>
<p><strong><span style="color: #ff0000;"><span style="text-decoration: underline;">ATTENTION:</span></span></strong> il faut absolument que <em>gunicorn_django</em> soit lancé en <em>foreground</em> (en tâche principale, pas en arrière-plan/<em>background/</em>démon/<em>daemon</em>), ce qui est le cas par défaut si vous n&#8217;avez pas explicitement dit le contraire dans votre fichier de configuration (ou en paramètre de la commande) de <em>gunicorn_django</em>.<br />
En effet c&#8217;est <em>supervisord</em> qui se charge de le faire : si le processus est lancé en arrière-plan, <em>supervisord</em> ne peut pas prendre la main dessus et le contrôler ni le monitorer, et va essayer de le lancer plusieurs fois d&#8217;affilée pensant qu&#8217;il échoue à chaque fois.</p>
<h4>Lancer supervisord et le relancer à chaque reboot</h4>
<p>Il suffit pour cela de créer un script de démarrage dans <em>/etc/init.d/</em> et de le faire se  lancer à chaque démarrage.</p>
<p>Dans <em>/etc/init.d/supervisord</em> :</p>
<pre>#! /bin/sh
### BEGIN INIT INFO
# Provides:          supervisord
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

# Author: Dan MacKinlay
# Based on instructions by Bertrand Mathieu
# http://zebert.blogspot.com/2009/05/installing-django-solr-varnish-and.html

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="supervisord"
NAME=supervisord
DAEMON=supervisord
MANAGE=supervisorctl
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (&gt;= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

case "$1" in
  start)
    $DAEMON
        ;;
  stop)
    $MANAGE shutdown
        ;;
  reload|force-reload)
    $MANAGE reload
    ;;
  restart)
    $MANAGE restart
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" &gt;&amp;2
        exit 3
        ;;
esac</pre>
<p>Ce script contient des commentaires en début de fichier qui permettent de le faire se lancer automatiquement à chaque démarrage :</p>
<pre>$ chmod a+x /etc/init.d/supervisord
$ update-rc.d supervisord defaults</pre>
<p>Cette commande devrait indiquer qu&#8217;elle a créé tous les liens symbolique nécessaire pour lancer ce script à chaque démarrage du serveur.<br />
Il ne reste plus qu&#8217;à lancer <em>supervisord</em> maintenant et vérifier que notre site est accessible :</p>
<pre>$ /etc/init.d/supervisord start</pre>
<h4>Monitorer et contrôler ses processus</h4>
<p>Soit en utilisant le client CLI :</p>
<pre>$ supervisorctl</pre>
<p>Soit en accédant à la page web dont on a configuré l&#8217;adresse dans le paramètre <em>inet_http_server</em> dans le fichier de configuration de <em>supervisord</em>. De là vous pouvez redémarrer vos processus, les arrêter, visualiser le contenu du fichier de log&#8230;</p>
<h4>Un soucis?</h4>
<ul>
<li>Pensez à regarder dans les fichiers de log indiqués dans les paramètres pour voir si il y a des indications sur le problème</li>
<li>Vérifiez que la commande configuré dans /etc/<em>supervisord.conf</em> se lance correctement manuellement, et que le processus est bien en <em>foreground</em></li>
<li>Faites un tour sur l&#8217;excellente documentation du <a title="Site officiel du projet supervisord" href="http://supervisord.org/" target="_self">projet supervisord</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2010/08/lancer-gunicorn-avec-supervisord/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>lancer gunicorn avec runit</title>
		<link>http://mathieu.agopian.info/blog/2010/02/lancer-gunicorn-avec-runit/</link>
		<comments>http://mathieu.agopian.info/blog/2010/02/lancer-gunicorn-avec-runit/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 10:37:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[système]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[gunicorn]]></category>
		<category><![CDATA[mod_proxy]]></category>
		<category><![CDATA[runit]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=214</guid>
		<description><![CDATA[ATTENTION votre serviteur a fait le test pour vous sur une ubuntu: après avoir installé runit et runit-run, le système ne démarre plus. Pour suivre les étapes de ce billet, il ne faut pas installer runit-run, qui ne doit être installé que lorsque l&#8217;on souhaite remplacer totalement le système d&#8217;initialisation (et cela demande plus de configuration qu&#8217;une [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000;"><strong><span style="text-decoration: underline;">ATTENTION</span><span style="font-weight: normal;"> votre serviteur a fait le test pour vous sur une ubuntu: après avoir installé <em>runit</em> et <em>runit-run</em>, le système ne démarre plus. Pour suivre les étapes de ce billet, il ne faut <span style="text-decoration: underline;">pas</span> installer <em>runit-run</em>, qui ne doit être installé que lorsque l&#8217;on souhaite remplacer totalement le système d&#8217;initialisation (et cela demande plus de configuration qu&#8217;une simple installation du paquet).</span></strong></span></p>
<p><span style="color: #ff0000;"><strong><span style="font-weight: normal;">Pour les malheureux qui ont fait les frais de la première version de ce billet (demandant d&#8217;installer <em>runit-run</em>), je ne peux que m&#8217;excuser platement, et vous fournir la méthode &laquo;&nbsp;au secours rescue moi!&nbsp;&raquo;: <a title="Récuperer son installation ubuntu" href="http://www.tenshu.fr/ubuntu/recuperer-une-installation-avec-un-cd-ubuntu/" target="_self">récuperer une installation avec un cd ubuntu</a>. Une fois chrooté sur la partition root, il vous restera à désinstaller le paquet fautif et redémarrer:</span></strong></span><br />
<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ aptitude purge runit-run</span></p>
<h6><span style="color: #ff0000;"><span style="color: #000000;">Edité le 2010/02/10 à 20:58</span></span></h6>
<hr />Pour faire suite au précédent billet <a title="Recette d'installation et d'utilisation de gunicorn avec django" href="/blog/2010/02/gunicorn-un-server-wsgi-ultra-simple-a-utiliser-et-configurer/" target="_self">gunicorn: un server wsgi ultra simple à utiliser et configurer</a>, voici une recette rapide pour lancer automatiquement (et monitorer) gunicorn avec <a title="Page officielle du project runit" href="http://smarden.org/runit/" target="_self">runit</a>.</p>
<h3>Pourquoi runit et pas sysvinit, inittab, upstart, &#8230;</h3>
<p>Je vous laisse consulter la page <a title="Bénéfices de runit par rapport aux autres systèmes" href="http://smarden.org/runit/benefits.html" target="_self">benefits</a> sur le site officiel pour vous faire une idée. Pour les personnes ne parlant pas anglais, voici un bref résumé:</p>
<ol>
<li>Un répertoire par service, contenant un script <em>run</em></li>
<li>Un environnement d&#8217;exécution propre et prédictible pour chaque processus</li>
<li>Service de logging (optionnel) qui sera lancé en même temps que le processus, et en couvrira toute la durée de vie (redémarrages compris!)</li>
<li>Très peu encombrant, efficace&#8230; et peut complètement remplacer le système d&#8217;initialisation de votre linux</li>
</ol>
<h3>Utiliser runit avec le système d&#8217;initialisation actuel</h3>
<p>Pour nous faciliter la vie, et ne pas avoir à modifier/importer de nombreux scripts de démarrage pour tous les démons et services déjà installés, nous allons utiliser runit &laquo;&nbsp;avec&nbsp;&raquo; le système d&#8217;initialisation actuel.</p>
<h4>Installer runit</h4>
<pre class="brush:shell">$ aptitude install runit</pre>
<p><strong><span style="color: #ff0000;"><span style="text-decoration: underline;">ATTENTION:</span></span></strong> Si vous installez aussi <em>runit-run</em>, il vous faut absolument configurer votre système (<a title="Méthode à suivre pour remplacer init" href="http://smarden.org/runit/replaceinit.html" target="_self">﻿How to replace init</a>), et ce, avant de rebooter (sinon votre système ne démarrera pas, et vous serez contraint à utiliser une méthode de récupération, comme celle présentée en tête de ce billet).</p>
<h4>Créer un répertoire pour le service gunicorn et son script de lancement</h4>
<pre class="brush:shell">$ mkdir /etc/sv/gu-monprojet
$ vi /etc/sv/gu-monprojet/run</pre>
<p>Et voici le contenu du script run</p>
<pre class="brush:shell">#!/bin/bash
source /path/to/venv/bin/activate # activer le virtualenv
cd /path/to/django/project
exec gunicorn_django -b localhost:8080 --workers=3</pre>
<p>Avec la version de gunicorn utilisée pour l&#8217;écriture de cet article, il est nécessaire d&#8217;être dans le répertoire du projet django (là ou se situe le fichier <em>settings.py</em>) pour lancer <em>gunicorn_django</em>.</p>
<p>Dans une future version (la modification est dans le <em>trunk</em> à l&#8217;heure de l&#8217;écriture) il suffira d&#8217;indiquer le chemin vers le fichier <em>settings.py</em> comme paramètre à la commande <em>gunicorn_django</em>.</p>
<p>Enfin, ne pas oublier de rajouter les droits d&#8217;exécution sur le script qu&#8217;on vient de créer:</p>
<pre class="brush:shell">$ chmod a+x /etc/sv/gu-monprojet</pre>
<h4>Indiquer à runit qu&#8217;il doit lancer le script</h4>
<p>Pour celà, un simple lien symbolique, et dans les secondes qui suivent le script sera lancé:</p>
<pre class="brush:shell">$ ln -s /etc/sv/gu-monprojet /etc/service/</pre>
<h3>Et c&#8217;est tout!</h3>
<p>Il suffit maintenant d&#8217;en profiter en allant sur http://localhost:8080, en configurant apache pour proxiser les requêtes directement dessus (cf le billet <a title="Recette d'installation et d'utilisation de gunicorn avec django" href="/blog/2010/02/gunicorn-un-server-wsgi-ultra-simple-a-utiliser-et-configurer/" target="_self">gunicorn: un server wsgi ultra simple à utiliser et configurer</a>), ou encore en utilisant la commande <em>sv</em> pour gérer le service gunicorn:</p>
<pre class="brush:shell">$ sv status gu-monprojet
$ sv check gu-monprojet
$ sv up gu-monprojet
$ sv down gu-monprojet
$ sv restart gu-monprojet
$ sv hup gu-monprojet
...</pre>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2010/02/lancer-gunicorn-avec-runit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>gunicorn: un server wsgi ultra simple à utiliser et configurer</title>
		<link>http://mathieu.agopian.info/blog/2010/02/gunicorn-un-server-wsgi-ultra-simple-a-utiliser-et-configurer/</link>
		<comments>http://mathieu.agopian.info/blog/2010/02/gunicorn-un-server-wsgi-ultra-simple-a-utiliser-et-configurer/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 16:08:46 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[gunicorn]]></category>
		<category><![CDATA[mod_proxy]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=198</guid>
		<description><![CDATA[Deux billets le même jour, c&#8217;est fête! Voici une recette simple pour installer, configurer et utiliser gunicorn avec apache et django. Installer gunicorn Pour installer gunicorn dans son environnement virtuel: $ pip install -E /path/to/venv install gunicorn Configurer Apache en proxy Apache servira les fichiers statiques, et &#171;&#160;proxisera&#160;&#187; toutes les autres requêtes directement à gunicorn [...]]]></description>
			<content:encoded><![CDATA[<p>Deux billets le même jour, c&#8217;est fête!</p>
<p>Voici une recette simple pour installer, configurer et utiliser <a title="Page officielle du projet gunicorn" href="http://github.com/benoitc/gunicorn" target="_self">gunicorn</a> avec <a title="Page officielle du serveur web Apache" href="http://www.apache.org/" target="_self">apache</a> et <a title="Page officielle du projet Django, framework web en python" href="http://www.djangoproject.com/" target="_self">django</a>.</p>
<h3>Installer gunicorn</h3>
<p>Pour installer gunicorn dans son environnement virtuel:</p>
<pre>$ pip install -E /path/to/venv install gunicorn</pre>
<h3>Configurer Apache en proxy</h3>
<p>Apache servira les fichiers statiques, et &laquo;&nbsp;proxisera&nbsp;&raquo; toutes les autres requêtes directement à gunicorn qui sera lancé en local sur le port 8080:</p>
<pre>&lt;VirtualHost *:80&gt;
ServerName example.com
ServerAlias www.example.com

DocumentRoot /path/to/django/project

&lt;Proxy *&gt;
    Order deny,allow
    Allow from all
&lt;/Proxy&gt;

# laisser apache servir les fichiers statiques
ProxyPass /robots.txt !
ProxyPass /favicon.ico !
ProxyPass /static/ !

# proxiser toutes les autres requêtes vers gunicorn
ProxyPass / http://localhost:8080/

# robots.txt et favicon.ico sont dans /path/to/django/project/static/
Alias /robots.txt /path/to/django/project/static/robots.txt
Alias /favicon.ico /path/to/django/project/static/favicon.ico

&lt;Directory /path/to/django/project&gt;
    Order deny,allow
    Allow from all
    Options -Indexes
&lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre>
<p>Pour que le tout fonctionne correctement, il faut activer les modules <em>mod_proxy</em> et <em>mod_proxy_html</em> (et en option <em>mod_cache</em>):</p>
<pre>$ a2enmod proxy proxy_http cache</pre>
<p>Puis de redémarrer le server Apache:</p>
<pre>$ /etc/init.d/apache2 restart</pre>
<h3>Lancer gunicorn</h3>
<p>Il suffit de se placer dans le répertoire du projet django (avec le virtualenv activé), puis de taper:</p>
<pre>$ gunicorn_django -b localhost:8080 --workers=2</pre>
<p>Un ordre d&#8217;idée pour le calcul des <em>workers</em>: un de plus que le nombre de CPUs de la machine.</p>
<h3>Conclusion</h3>
<p>On peut alors se créer un script (a placer dans /etc/init.d) et l&#8217;activer pour qu&#8217;il se lance automatiquement au démarrage avec la commande <em>update-rc.d</em> (sous Debian), ou utiliser <a title="runit, un remplacement pour sysvinit" href="http://smarden.org/runit/" target="_self">runit</a> (jamais testé, peut-être un futur billet?).</p>
<p>Encore mieux, remplacer Apache par Nginx! (jamais testé non plus, et sûrement un futur billet <img src='http://mathieu.agopian.info/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ).</p>
<p>On peut difficilement faire plus simple!</p>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2010/02/gunicorn-un-server-wsgi-ultra-simple-a-utiliser-et-configurer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django, sqlite et mod_wsgi, attention au piège!</title>
		<link>http://mathieu.agopian.info/blog/2009/03/django-sqlite-et-mod_wsgi-attention-au-piege/</link>
		<comments>http://mathieu.agopian.info/blog/2009/03/django-sqlite-et-mod_wsgi-attention-au-piege/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 14:34:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=111</guid>
		<description><![CDATA[Tout d&#8217;abord, je tiens à préciser que le problème qui suit n&#8217;est pas limité à l&#8217;utilisation de django ou de mod_wsgi. Le contexte Utilisation de SQLite pour un projet django déployé sur mod_wsgi: # settings.py DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = '/opt/mysite/mysite.db' Et voici les permissions sur le système de fichier: -rw-rw-rw- 1 ohan ohan 29696 [...]]]></description>
			<content:encoded><![CDATA[<p>Tout d&#8217;abord, je tiens à préciser que le problème qui suit n&#8217;est pas limité à l&#8217;utilisation de django ou de mod_wsgi.</p>
<h3>Le contexte</h3>
<p>Utilisation de <em>SQLite</em> pour un projet django déployé sur mod_wsgi:</p>
<pre># settings.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = '/opt/mysite/mysite.db'</pre>
<p>Et voici les permissions sur le système de fichier:</p>
<pre>-rw-rw-rw- 1 ohan ohan 29696 2009-03-14 13:30 mysite.db</pre>
<p>Tous les répertoires parents sont eux en <em>755</em> (lecture et exécution), ce qui ne devrait donc poser aucun problème, même pour l&#8217;utilisateur utilisé par les processus apache/mod_wsgi.</p>
<h3>Le problème</h3>
<p>Lors de la première tentative d&#8217;accès à la base de donnée (par exemple en accédant à l&#8217;administration django), une erreur <em>500 INTERNAL SERVER ERROR</em> est renvoyée, et dans le fichier de log d&#8217;apache:</p>
<pre>OperationalError: unable to open database file</pre>
<h3>La solution</h3>
<p>Lors de l&#8217;accès à un fichier de base de données, <em>SQLite</em> va créer un fichier journal qui lui servira (entre autres) à gérer les accès à cette base. Plus d&#8217;informations sur la page expliquant les méthodes de vérouillage: <a title="La gestion du lock pour les bases de données sqlite" href="http://www.sqlite.org/lockingv3.html" target="_self">locking in sqlite v3</a>.</p>
<p>Pour créer ce fichier, il faut donc que l&#8217;utilisateur puisse écrire dans le répertoire parent.</p>
<pre>chmod a+rw /opt/mysite</pre>
<p>Ce problème ne devrait se présenter que lors d&#8217;un déploiement en environnement de production pour un projet qui utilise <em>SQLite</em>, ou sur un environnement de test si, comme moi, vous préférez tester sur apache directement, et non sur le <em>runserver.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2009/03/django-sqlite-et-mod_wsgi-attention-au-piege/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django svn et mod_wsgi, attention au piège!</title>
		<link>http://mathieu.agopian.info/blog/2009/02/django-svn-et-mod_wsgi-attention-au-piege/</link>
		<comments>http://mathieu.agopian.info/blog/2009/02/django-svn-et-mod_wsgi-attention-au-piege/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 21:34:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[mod_wsgi]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=35</guid>
		<description><![CDATA[Une erreur de débutant qui peut être fastidieuse à debug...]]></description>
			<content:encoded><![CDATA[<h3>Scénario</h3>
<p>Notre cher utilisateur <em>biboul</em> se décide à installer la version de développement de django, que nous appellerons django-trunk, comme indiqué sur la page <a title="Comment installer Django" href="http://docs.djangoproject.com/en/dev/topics/install/#installing-development-version" target="_self">How To Install Django</a>.</p>
<p>Il lance donc les commandes suivantes:</p>
<pre>biboul@laptop:~$ svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk
biboul@laptop:~$ ln -s <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/django-trunk/django /usr/lib/python2.5/site-packages/django
biboul@laptop:~$ ln -s <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/django-trunk/django/bin/django-admin.py /usr/local/bin</pre>
<p>Il a bien entendu</p>
<ol>
<li><a title="Guide d'installation rapide de mod_wsgi" href="http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide" target="_self">configuré</a> son serveur apache pour utiliser le module WSGI</li>
<li><a title="Guide de configuration rapide de mod_wsgi" href="http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide" target="_self">testé</a> avec le script wsgi &laquo;&nbsp;hello world&nbsp;&raquo; que la configuration était bonne</li>
<li><a title="Django avec mod_wsgi" href="http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango" target="_self">modifié</a> le script wsgi de manière à utiliser son application django <em>mysite</em></li>
</ol>
<h3>Le problème</h3>
<p>Lors de la première requête à son application <em>mysite</em>, une belle &laquo;&nbsp;<em>500 Internal Server Error</em>&nbsp;&raquo; s&#8217;affiche, avec les messages d&#8217;erreurs suivants dans le fichier <em>/var/log/apache2/error_log</em>:</p>
<pre>...  mod_wsgi (pid=5803): Target WSGI script '/opt/tcs/tcs.wsgi' cannot be loaded as Python module.
...  mod_wsgi (pid=5803): Exception occurred processing WSGI script '/opt/tcs/tcs.wsgi'.
...  Traceback (most recent call last):
...       File "/opt/tcs/tcs.wsgi", line 6, in &lt;module&gt;
...           import django.core.handlers.wsgi
...  ImportError: No module named django.core.handlers.wsgi</pre>
<p>Mais pourquoi donc, alors qu&#8217;un <em>import django.core.handlers.wsgi</em> fonctionne correctement, que ce soit dans l&#8217;interpréteur ou dans le shell django?</p>
<h3>La réponse</h3>
<p>Tout simplement parce que le répertoire <em>django-trunk</em> (dont notre cher utilisateur <em>biboul</em> a fait un lien symbolique dans le répertoire<em> site-packages</em>) n&#8217;est pas accessible à un utilisateur différent, si il n&#8217;est pas dans le même <em>group</em>.<br />
Or, par défaut et sur la plupart des distributions Linux, les processus <em>apache</em> sont lancé avec un utilisateur limité (<em>www-data</em>, <em>www</em> ou encore <em>apache</em>).</p>
<h3>La solution</h3>
<p>Un simple <em>chmod 755</em> des répertoires parents au répertoire <em>django-trunk</em> est suffisant pour régler ce problème.<br />
Une autre solution, plus propre et sécurisée, serait de placer le répertoire <em>django-trunk</em> dans le répertoire <em>/opt</em>, et de modifier les liens symboliques pour utiliser ce nouvel emplacement.</p>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2009/02/django-svn-et-mod_wsgi-attention-au-piege/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
