<?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; système</title>
	<atom:link href="http://mathieu.agopian.info/blog/category/systeme/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>MySQL, mysqldump et PHP : convertir de latin1 vers utf8</title>
		<link>http://mathieu.agopian.info/blog/2010/03/mysql-mysqldump-et-php-convertir-de-latin1-vers-utf8/</link>
		<comments>http://mathieu.agopian.info/blog/2010/03/mysql-mysqldump-et-php-convertir-de-latin1-vers-utf8/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 06:38:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[système]]></category>
		<category><![CDATA[technique]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[charset]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[iso-8859-1]]></category>
		<category><![CDATA[latin1]]></category>
		<category><![CDATA[mysqldump]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=262</guid>
		<description><![CDATA[Cet article à pour but de vous éviter, à vous lecteur, de vivre la perte de neurones (et le gain de cheveux blancs) que j&#8217;ai subit dernièrement, à investiguer des soucis de charset dans une base de donnée MySQL (et l&#8217;affichage sur une page web par le biais de PHP). Je tiens à préciser que [...]]]></description>
			<content:encoded><![CDATA[<p>Cet article à pour but de vous éviter, à vous lecteur, de vivre la perte de neurones (et le gain de cheveux blancs) que j&#8217;ai subit dernièrement, à investiguer des soucis de charset dans une base de donnée MySQL (et l&#8217;affichage sur une page web par le biais de PHP).</p>
<p>Je tiens à préciser que je ne suis pas un expert MySQL, et encore moins un expert en encoding, et certaines définitions ou mots utilisés dans cet article peuvent ne pas être utilisés à bon escient. Le fond et la méthode présentée ont par contre été vérifiés et testés!</p>
<h3>Introduction à l&#8217;encoding</h3>
<p>Je ne parlerais pas ici de ASCII ou Unicode (normes utilisées pour stocker les données), mais du jeu de caractères utilisé pour <em>encoder</em> ces données (et les afficher de manière lisible pour un être humain).  Pour commencer, quelques définitions:</p>
<ol>
<li><a title="Page Wikipedia sur l'encoding (en français)" href="http://fr.wikipedia.org/wiki/Charset" target="_self">encoding</a> =  character set = charset : jeu de caractères utilisé pour représenter des données</li>
<li><a title="Page Wikipedia sur l'UTF8 (en français)" href="http://fr.wikipedia.org/wiki/Utf8">utf8</a> = UTF-8 : un encoding qui associe un caractère à chaque &laquo;&nbsp;codepoint&nbsp;&raquo; <a title="Page wikipedia sur Unicode (en Français)" href="http://fr.wikipedia.org/wiki/Unicode" target="_self">Unic﻿ode</a> (particularité: tous les caractères hors <em>latin1</em> sont stockés sur deux octets)</li>
<li><a title="Page Wikipedia sur le Latin1 (en français)" href="http://fr.wikipedia.org/wiki/Latin1" target="_self">latin1</a> = latin-1 = ISO-8859-1 : un encoding qui associe un caractère à chaque octet de la table <a title="Page wikipédia sur ASCII (en français)" href="http://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange" target="_self">ASCII</a></li>
</ol>
<p>Pour résumer, chaque caractère peut être stocké sur le disque en Unicode (ou en ASCII, beaucoup plus limité). Il est ensuite <em>encodé</em> (traduit, représenté) avec un jeu de caractères pour être affichable et lisible par un être humain.</p>
<p>Historiquement, pour les pays occidentaux, l&#8217;encodage était fait en latin1 (caractères latins avec ses accentuations). De nos jours, de plus en plus d&#8217;applications se tournent vers Unicode et l&#8217;encodage en UTF-8 qui permet de représenter l&#8217;ensemble des caractères utilisés universellement (il n&#8217;est donc pas limité aux caractères latins, mais inclut par exemple les caractères cyrilliques, chinois&#8230;).</p>
<h4>Charset utilisé par les tables et les champs</h4>
<p>Pour consulter l&#8217;encodage utilisé par défaut pour une table ou un champ particulier :</p>
<pre class="brush:sql">mysql&gt; SHOW CREATE TABLE bar;
+-------+-------------------------------+
| Table | Create Table                  |
+-------+-------------------------------+
| bar   | CREATE TABLE `bar` (
  `id` int(11) default NULL,
  `firstname` char(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+-------+-------------------------------+
1 row in set (0.00 sec)</pre>
<p><strong>ATTENTION : </strong>les charset définits au niveau de la base de donnée, de la table et du champ sont des &laquo;&nbsp;default charset&nbsp;&raquo;. Il est tout à fait possible d&#8217;avoir une table avec un champ dont le contenu est en <em>latin1</em>, puis changer le <em>DEFAULT CHARACTER SET</em> à <em>utf8</em> pour ce champ. Toutes les données existantes seront toujours en <em>latin1</em>, par contre toutes les nouvelles données <span style="text-decoration: underline;">entrées en </span><span style="text-decoration: underline;"><em>utf8</em></span> seront en <em>utf8</em>. On est alors confronté au pire des problèmes : des charsets différents au sein d&#8217;une table pour un même champ.</p>
<h4>Charset utilisé par le serveur, la database, les tables, les champs, le client, la connexion, les résultats&#8230;</h4>
<p>Les encodages utilisés par le client, la connexion, le serveur, et l&#8217;affichage des résultats sont consultable par la commande suivante:</p>
<pre class="brush:sql">mysql&gt; SHOW VARIABLES WHERE variable_name like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)</pre>
<p>Dans cet exemple, le client, la connexion, la database et les résultats sont tous en <em>utf8</em>. Il n&#8217;y a que le serveur lui-même qui est en <em>latin1</em> par défaut.  Pour configurer le client, la connexion et les résultats, on peut soit utiliser la commande</p>
<pre class="brush:sql">mysql&gt; SET NAMES utf8;</pre>
<p>Soit configurer les variables décrites dans le paragraphe suivant :</p>
<h4>Les variables de configuration</h4>
<p>Elles peuvent être définies au niveau du fichier <em>/etc/mysql/my.cnf</em> (peut être situé à un autre endroit selon la distribution):</p>
<pre class="brush:text">[mysqld]
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci # utilisé pour les comparaisons

[mysqldump]
default-character-set=utf8

[mysql]
default-character-set=utf8</pre>
<h3>L&#8217;encoding du terminal: attention au piège!</h3>
<p>Quels que soit les charsets (par défaut) que vous avez configurés, il faut savoir que c&#8217;est le charset du terminal (si vous êtes en ligne de commande sur <em>mysql</em> par exemple) qui sera utilisé lors d&#8217;un <em>UPDATE</em> ou <em>INSERT</em> dans une table.</p>
<p>Ainsi, même si vous avez tout configuré (y compris le <em>SET NAMES)</em> pour être en <em>latin1</em>, lors d&#8217;une insertion dans une table, si votre terminal est en <em>utf8</em> la donnée sera stockée en <em>utf8</em>.</p>
<p>Reportez-vous à <a title="Tester le charset de son terminal" href="http://www.tuteurs.ens.fr/faq/utf8.html#test" target="_self">cette astuce</a> pour tester le charset (<em>latin1</em> ou <em>utf8</em>) de votre terminal. Il faut <strong><span style="text-decoration: underline;">ABSOLUMENT</span><span style="font-weight: normal;"> que votre client ai le même encoding que votre terminal pour éviter les <a title="Lien en anglais: comment utiliser encoding et collation correctement" href="http://forge.mysql.com/w/images/b/b6/How_to_Use_Charsets_and_Collations_Properly.pdf" target="_self">conflits</a> (à partir de la page 21).</span></strong></p>
<h3>Détecter le charset utilisé pour un champ</h3>
<p>Commençons par une astuce pour différencier une donnée stockée en <em>utf8</em> de <em>latin1 <span style="font-style: normal;">:</span></em></p>
<pre class="brush:sql">mysql&gt; select firstname, length(firstname) from bar;
+-----------+-------------------+
| firstname | length(firstname) |
+-----------+-------------------+
| dédé    |                 6 |
+-----------+-------------------+
1 row in set (0.00 sec)</pre>
<p>6 octets pour stocker 4 caractères ? C&#8217;est de l&#8217;<em>utf8 </em>! Les accents sont stockés sur deux octets. Si ça avait été du <em>latin1</em>, la longueur de la donnée aurait été de 4 octets.</p>
<h3><strong>Mais alors, je peux demander à MySQL de convertir mes données ?</strong></h3>
<p><strong></strong>Oui, mais pour savoir où aller, il faut savoir d&#8217;où on vient: avant de demander à MySQL de convertir une donnée, il faut connaitre son encodage actuel, et surtout dans quel encodage MySQL croit que ces données sont.</p>
<p>Il faut bien garder en tête que lorsqu&#8217;on parle du charset d&#8217;une table, d&#8217;un champ, d&#8217;une base de donnée&#8230; on parle du charset <span style="text-decoration: underline;">par défaut</span>, et donc du charset que le serveur va utiliser pour insérer/retourner des données. Cela n&#8217;a aucune incidence sur l&#8217;encodage utilisé auparavant pour les données.</p>
<ul>
<li>charset du serveur égal au charset du client : aucune conversion n&#8217;est faite</li>
<li>charset du serveur en <em>latin1</em>, charset du client en <em>utf8</em> : la donnée va être encodée en <em>utf8</em> (même si elle l&#8217;était déjà =&gt; problème de double encoding)</li>
<li>charset du serveur en <em>utf8</em>, charset du client en <em>latin1</em> : la donnée va être encodée en <em>latin1</em></li>
</ul>
<h3>Mes données sont stockées en <em>utf8</em> et MySQL ne le sait pas!</h3>
<p>Symptôme: quand on affiche le <em>length</em> d&#8217;une donnée avec des caractères accentués, ça donne un nombre d&#8217;octets plus grands que le nombre de caractères. La donnée est donc en <em>utf8</em>.  Par contre, le serveur, la db, la table, le champ&#8230; sont configurés pour être en <em>latin1</em>. Et quand on essaie de faire un <em>SET NAMES utf8</em>, la donnée s&#8217;affiche avec des &laquo;&nbsp;Ã©&nbsp;&raquo; : dans ce cas, c&#8217;est une donnée stockée en <em>utf8</em>, mais qui est interprétée comme du <em>latin1</em> par MySQL, qui va donc l&#8217;encoder une seconde fois en <em>utf8</em> (problème de double encoding).</p>
<h4>La solution :</h4>
<p>Le serveur pense que les données sont en <em>latin1</em> et on sait qu&#8217;elles sont en <em>utf8</em> (notre charset final souhaité). Il suffit de</p>
<ol>
<li>faire un dump de la base dans un fichier en <em>latin1</em> pour qu&#8217;il n&#8217;y ai aucune conversion (pas de double encoding)
<ul>
<pre class="brush:bash">$ mysqldump -u &lt;user&gt; -p&lt;pass&gt; --default-character-set=latin1 foo bar &gt; temp.sql</pre>
</ul>
</li>
<li>modifier ce fichier pour y faire disparaitre toute trace de &laquo;&nbsp;latin1&#8243;
<ul>
<pre class="brush:bash">$ cat temp.sql | sed 's/SET NAMES latin1/SET NAMES utf8/g' &gt; tmp
$ cat tmp | sed 's/CHARSET=latin1/CHARSET=utf8/g' &gt; temp.sql</pre>
</ul>
</li>
<li>configurer la table, la base de donnée et le serveur pour qu&#8217;ils soient en &laquo;&nbsp;default charset <em>utf8</em>&nbsp;&raquo; (cf le chapitre sur les variables de configuration)</li>
<li>réimporter les données dedans
<ul>
<pre class="brush:bash">$ mysql -u &lt;user&gt; -p&lt;pass&gt; foo &lt; temp.sql</pre>
</ul>
</li>
</ol>
<h3>Mes données sont stockées en <em>latin1</em> et MySQL le sait, mais je les veux en <em>utf8</em></h3>
<p>Vu que le serveur sait que ses données sont en <em>latin1</em>, il suffit de lui demander de nous les fournir en <em>utf8</em> :</p>
<ol>
<li>faire un dump de la base dans un fichier en <em>utf8</em> pour qu&#8217;il y ai une conversion automatique à partir de <em>latin1</em>
<ul>
<pre class="brush:bash">$ mysqldump -u &lt;user&gt; -p&lt;pass&gt; --default-character-set=utf8 foo bar &gt; temp.sql</pre>
</ul>
</li>
<li>modifier ce fichier pour y faire disparaitre toute trace de &laquo;&nbsp;latin1&#8243;
<ul>
<pre class="brush:bash">$ cat temp.sql | sed 's/SET NAMES latin1/SET NAMES utf8/g' &gt; tmp
$ cat tmp | sed 's/CHARSET=latin1/CHARSET=utf8/g' &gt; temp.sql</pre>
</ul>
</li>
<li>configurer la table, la base de donnée et le serveur pour qu&#8217;ils soient en &laquo;&nbsp;default charset utf8&#8243; (cf le chapitre sur les variables de configuration)</li>
<li>réimporter les données dedans
<ul>
<pre class="brush:bash">$ mysql -u &lt;user&gt; -p&lt;pass&gt; foo &lt; temp.sql</pre>
</ul>
</li>
</ol>
<h3>Et PHP dans tout ça? Avant ça marchait, maintenant j&#8217;ai des ﻿﻿� !</h3>
<p>Ce cher PHP (hint: passez à <a title="Page du framework web Django" href="http://www.djangoproject.com/" target="_self">Django</a>! c&#8217;est bien plus beau!) ne prends pas en compte les configurations mises au niveau du serveur (ou du fichier de configuration) pour son encoding!</p>
<p>Par défaut la commande <em>mysql_connect</em> va toujours utiliser le charset <em>latin1</em> : vous pouvez en avoir la preuve avec la commande <em>mysql_client_encoding</em>.</p>
<p>PHP va donc vous fournir des données interprétées en <em>latin1</em> alors qu&#8217;elles sont en <em>utf8</em>, d&#8217;où les caractères � non valides.</p>
<p>Il suffit alors d&#8217;utiliser la commande <em>mysql_set_charset(&#8216;utf8&#8242;, $connection)</em> sur la connexion ouverte avec <em>mysql_connect</em>.</p>
<p><span style="text-decoration: underline;">Faites bien attention</span> d&#8217;avoir définit <em>utf8</em> pour l&#8217;encoding de vos pages HTML soit par une balise <em>meta</em> dans votre entête de page, ou en ayant configuré votre serveur web pour servir les pages en <em>utf8</em>. Un moyen simple de vérifier ça est d&#8217;afficher les informations de la page.</p>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2010/03/mysql-mysqldump-et-php-convertir-de-latin1-vers-utf8/feed/</wfw:commentRss>
		<slash:comments>0</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>Linux: savoir si le processeur est 32bits ou 64bits</title>
		<link>http://mathieu.agopian.info/blog/2009/09/linux-savoir-si-le-processeur-est-32bits-ou-64bits/</link>
		<comments>http://mathieu.agopian.info/blog/2009/09/linux-savoir-si-le-processeur-est-32bits-ou-64bits/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 07:16:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[système]]></category>

		<guid isPermaLink="false">http://mathieu.agopian.info/blog/?p=146</guid>
		<description><![CDATA[Voici une astuce rapide pour savoir si le processeur d&#8217;une machine donnée supporte le 64bits: Il suffit de vérifier si le flag lm est présent dans les informations de /proc/cpuinfo: $ cat /proc/cpuinfo &#124; grep lm flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 [...]]]></description>
			<content:encoded><![CDATA[<p>Voici une astuce rapide pour savoir si le processeur d&#8217;une machine donnée supporte le 64bits:</p>
<p>Il suffit de vérifier si le flag <em>lm</em> est présent dans les informations de <em>/proc/cpuinfo</em>:</p>
<pre>$ cat /proc/cpuinfo | grep lm
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe <strong>lm</strong> constant_tsc pebs
bts pni monitor ds_cpl est cid cx16 xtpr lahf_lm</pre>
<p>Le flag <em>lm</em> signifie &laquo;&nbsp;long mode&nbsp;&raquo;, comme on peut le voir dans les sources du noyau (<em>include/asm-i386/cpufeature.h</em>):</p>
<pre>#define X86_FEATURE_LM          (1*32+29) /* Long Mode (x86-64) */</pre>
<p>Vous trouverez une liste de tous les flags sur le <a href="http://gagravarr.livejournal.com/138575.html" target="_self">blog de Nick Burch</a> (en anglais).</p>
]]></content:encoded>
			<wfw:commentRss>http://mathieu.agopian.info/blog/2009/09/linux-savoir-si-le-processeur-est-32bits-ou-64bits/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
