<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.fedora-fr.org/metal3d/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Metal3d - Fedogeek</title>
  <link>http://blog.fedora-fr.org/metal3d/</link>
  <atom:link href="http://blog.fedora-fr.org/metal3d/feed/rss2" rel="self" type="application/rss+xml"/>
  <description>Blog de Patrice Ferlet (aka Metal3d) - Blog spécifique à Fedora, son administration, développer, jouer, créer sur Fedora...</description>
  <language>fr</language>
  <pubDate>Mon, 04 Mar 2013 09:16:15 +0100</pubDate>
  <copyright>http://creativecommons.org/licenses/by/2.5/</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Pool de thread avec limite de parallélisation</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Pool-de-thread-avec-limite-de-parall%C3%A9lisation</link>
    <guid isPermaLink="false">urn:md5:a92c77f717778e4f6edbabe105f42a79</guid>
    <pubDate>Sat, 02 Mar 2013 17:37:00 +0100</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>développement</category><category>python</category><category>thread</category>    
    <description>&lt;p&gt;Je travaillais cette semaine sur un script python qui récupérait des
centaines de milliers de données depuis un serveur. Pour gagner en temps de
calcul, j'ai décidé de faire des threads. Limitant la taille de mes tâches
parallèles à un nombre spécifique, le script bloquait... car j'utilisais des
fonctions threadées qui lançaient récursivement d'autres threads. Sauf que la
Queue que j'utilisais pour faire le pool se bloquait si trop de threads se
lançaient en même temps attendant indéfiniment que quelqu'un veuille bien lire
la Queue... J'ai alors trouvé ma solution, et je la partage avec vous. Je vous
explique le problème, je vous montre un exemple, et ensuite on voit la
solution.&lt;/p&gt;    &lt;p&gt;J'ai cherché un peu partout sur le net, et je n'ai pas trouvé de solution à
mon problème. Ainsi, pour vous montrer ce qui coince, je vous ai préparé un
exemple de script très simple. Le script suivant lance 5 Threads qui eux même
vont en créer... Pour limiter le nombre de tâche parallèles je passe par une
classe assez connue (depuis python recipes) qui utilise la classe Queue avec
une limite de taille.&lt;/p&gt;
&lt;p&gt;Chaque fois qu'on ajoute une tâche dans la classe, la Queue est remplie...
les workers vont alors lire en boucle dans cette dernière pour lancer la tâche
et les arguments stoqués. Tant que la Queue est remplie, il faut attendre que
quelqu'un la lise... sinon l'appel à &amp;quot;put&amp;quot; reste bloqué.&lt;/p&gt;
&lt;p&gt;Voici la classe de base que j'ai utilisée (et modifié):&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;Edit&lt;/ins&gt;: J'ai beaucoup joué avec ma classe et j'ai fait quelques
corrections, notamment en ce qui concerne l'ajout d'arguments, vous pouvez
suivre les fixes sur le gist suivant: &lt;a href=&quot;https://gist.github.com/metal3d/5075460&quot; title=&quot;https://gist.github.com/metal3d/5075460&quot;&gt;https://gist.github.com/metal3d/507...&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;python python&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# -*- encoding: utf-8 -*-&lt;/span&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# file threadingpoolbad.py&lt;/span&gt;
 
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;logging&lt;/span&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;threading&lt;/span&gt; &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; Thread
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt; &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt;
 
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;class&lt;/span&gt; ThreadPool:
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;class&lt;/span&gt; _ThreadQueue&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;Thread&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, pool, &lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args, &lt;span style=&quot;color: #66cc66;&quot;&gt;**&lt;/span&gt;kwargs&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Get tasks queue then launch thread &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;super&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;ThreadPool._ThreadQueue, &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;.&lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args, &lt;span style=&quot;color: #66cc66;&quot;&gt;**&lt;/span&gt;kwargs&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt; = pool.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;daemon&lt;/span&gt; = &lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; run&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Read tasks from limited size queue, then launch task &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
            &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;:
                &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# read bloking Queue ..&lt;/span&gt;
                task,args = &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;try&lt;/span&gt;:
                    task&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;Exception&lt;/span&gt;, e:
                    &lt;span style=&quot;color: #dc143c;&quot;&gt;logging&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;exception&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;e&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;Error&amp;quot;&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;finally&lt;/span&gt;:
                    &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;task_done&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, num=&lt;span style=&quot;color: #ff4500;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Create a limited pool with &amp;quot;num&amp;quot; threads &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt; = &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;for&lt;/span&gt; _ &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;._ThreadQueue&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; add_task&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, target, args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Write in unlimited size queue which will be
        read in &amp;quot;run&amp;quot; method of a thread
        Block if tasks Queue is full !
        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;put&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target, args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; wait_completion&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Wait for tasks to be completed &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Voilà comment utiliser cette classe:&lt;/p&gt;
&lt;pre class=&quot;python python&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;time&lt;/span&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; threadingpoolbad &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; ThreadPool
 
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool, num=&lt;span style=&quot;color: #ff4500;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
    num += &lt;span style=&quot;color: #ff4500;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;num is %d&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #66cc66;&quot;&gt;%&lt;/span&gt; num
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;if&lt;/span&gt; num &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #ff4500;&quot;&gt;5&lt;/span&gt;:
        pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;q, num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #dc143c;&quot;&gt;time&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff4500;&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#create a pool of 2 threads, launch test function&lt;/span&gt;
pool = ThreadPool&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff4500;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Jusqu'ici tout va bien... mais admettons que j'ajoute 5 ou 6 appels à
add_task:&lt;/p&gt;
&lt;pre class=&quot;python python&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# ...&lt;/span&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#create a pool of 2 threads, launch test function&lt;/span&gt;
pool = ThreadPool&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff4500;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Si vous lancez le test... ça coince. Pour arrêter le script faites CTRL+Z
puis &amp;quot;kill %%&amp;quot;.&lt;/p&gt;
&lt;p&gt;Tout le souci se trouve entre deux méthodes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add_tasks qui tente d'écrire dans une queue, l'appel à &amp;quot;put&amp;quot; bloque si la
Queue &amp;quot;tasks&amp;quot; est pleine&lt;/li&gt;
&lt;li&gt;dans &amp;quot;run&amp;quot; on libère un espace au moment où la fonction &amp;quot;task&amp;quot; est
terminée&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or, dans notre exemple, la fonction &amp;quot;test&amp;quot; ne libère pas la queue de suite,
car elle écrit dans la Queue via add_task... mais comme d'autres threads sont
aussi en cours, la Queue est pleine et aucun espace n'est libre. On se retrouve
en attente indéfinie...&lt;/p&gt;
&lt;p&gt;Pour la plupart des scripts, vous n'allez pas vous retrouver dans cette
situation, mais voilà... pour moi c'est arrivé.&lt;/p&gt;
&lt;p&gt;Comment corriger le souci ? revoir l'algo ? c'est dommage... tout
ce qui nous manque c'est de pouvoir écire dans la Queue sans limite, mais
limiter quand même le nombre de threads.&lt;/p&gt;
&lt;p&gt;La classe Queue peut tout à fait ne pas bloquer, et avoir une taille
indéfinie. Si on lui passe un entier en argument de constructeur elle se limite
à bloquer sa taille max à ce nombre. Mais si on ne lui donne pas de paramètres,
ou &amp;quot;0&amp;quot; ou un nombre négatif, alors sa taille est illimitée.&lt;/p&gt;
&lt;p&gt;Or, je veux tout de même limiter le nombre de process simultanés. Tout ce
dont j'ai besoin c'est de ne pas bloquer l'insert de tâches... vous me
suivez ?&lt;/p&gt;
&lt;p&gt;C'est alors très simple ! il suffit de gérer tout ça avec 2 Queue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une qui n'est pas limitée, elle gardera toutes les taches à lancer, quelque
soit le nombre&lt;/li&gt;
&lt;li&gt;une qui va limiter le nombre de thread, celle-ci sera limité à nombre qui
correspond au nombre de threads. C'est quasiement le même fonctionnement que la
classe de threadingpoolbad.py&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On y va:&lt;/p&gt;
&lt;pre class=&quot;python python&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# -*- encoding: utf-8 -*-&lt;/span&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#file threadingpool.py&lt;/span&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;logging&lt;/span&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;threading&lt;/span&gt; &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; Thread
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt; &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt;
 
 
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;class&lt;/span&gt; ThreadPool:
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;class&lt;/span&gt; _ThreadQueue&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;Thread&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, pool, &lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args, &lt;span style=&quot;color: #66cc66;&quot;&gt;**&lt;/span&gt;kwargs&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Get task and pool Queue. Then launch thread.
            &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;super&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;ThreadPool._ThreadQueue, &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;.&lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args, &lt;span style=&quot;color: #66cc66;&quot;&gt;**&lt;/span&gt;kwargs&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt; = pool.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt; = pool.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;daemon&lt;/span&gt; = &lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; run&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Run unlimited while Queues are not joined &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
            &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;:
                &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# reinsert the nonblocking queue &lt;/span&gt;
                &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# in blocking queue, that should block&lt;/span&gt;
                &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;# if &amp;quot;tasks&amp;quot; queue is full&lt;/span&gt;
                &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;put&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
                &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#and read this queue...&lt;/span&gt;
                task,args = &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;try&lt;/span&gt;:
                    task&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;*&lt;/span&gt;args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;Exception&lt;/span&gt;, e:
                    &lt;span style=&quot;color: #dc143c;&quot;&gt;logging&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;exception&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;e&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;finally&lt;/span&gt;:
                    &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;task_done&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
                    &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;task_done&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #0000cd;&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, num=&lt;span style=&quot;color: #ff4500;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Create the thread queue with &amp;quot;num&amp;quot; thread in parallel&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt; = &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt; = &lt;span style=&quot;color: #dc143c;&quot;&gt;Queue&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
        &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;for&lt;/span&gt; _ &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
            &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;._ThreadQueue&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; add_task&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;, target, args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Write in unlimited size queue which will be
        read in &amp;quot;run&amp;quot; method of a thread
        That should not block !
        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;put&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target, args&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
 
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; wait_completion&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
        &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Wait for the all threads to be completed &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;pool&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #008000;&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;tasks&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous voyez ici les deux queues, &amp;quot;tasks&amp;quot; et &amp;quot;pool&amp;quot;. La première est limitée,
l'autre non.&lt;/p&gt;
&lt;p&gt;Et cette fois ci, ça marche: j'ai bien deux threads qui tournent mais je ne
bloque plus lors de l'appel à &amp;quot;add_task&amp;quot;:&lt;/p&gt;
&lt;pre class=&quot;python python&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;time&lt;/span&gt;
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;from&lt;/span&gt; threadingpool &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;import&lt;/span&gt; ThreadPool
 
&lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool, num=&lt;span style=&quot;color: #ff4500;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;:
    num += &lt;span style=&quot;color: #ff4500;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;print&lt;/span&gt; &lt;span style=&quot;color: #483d8b;&quot;&gt;&amp;quot;num is %d&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #66cc66;&quot;&gt;%&lt;/span&gt; num
    &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;if&lt;/span&gt; num &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #ff4500;&quot;&gt;5&lt;/span&gt;:
        pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;q, num&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #dc143c;&quot;&gt;time&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff4500;&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
 
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#create a pool of 2 threads, launch test function&lt;/span&gt;
pool = ThreadPool&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff4500;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
pool.&lt;span style=&quot;color: black;&quot;&gt;add_task&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;target=&lt;span style=&quot;color: #dc143c;&quot;&gt;test&lt;/span&gt;, args=&lt;span style=&quot;color: black;&quot;&gt;(&lt;/span&gt;pool,&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et voilà ! Désormais, mes 120 000 tâches que j'ai à lancer ne se
bloquent plus, elles se placent en file l'attente et j'ai bien un nombre limité
de tâches en parallèle.&lt;/p&gt;
&lt;p&gt;Je ne vous montre pas mon script d'import, mais croyez moi, la récursion
(bien contrôlée) est énorme, et avoir résolut mon problème a été un soulagement
énorme.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.fedora-fr.org/metal3d/post/Pool-de-thread-avec-limite-de-parall%C3%A9lisation#comment-form</comments>
      <wfw:comment>http://blog.fedora-fr.org/metal3d/post/Pool-de-thread-avec-limite-de-parall%C3%A9lisation#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.fedora-fr.org/metal3d/feed/atom/comments/999</wfw:commentRss>
      </item>
    
  <item>
    <title>Coloriser la sortie d'un programme</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Coloriser-la-sortie-d-un-programme</link>
    <guid isPermaLink="false">urn:md5:b9711b7f470d178ad798fe12f2784ab3</guid>
    <pubDate>Mon, 18 Feb 2013 12:08:00 +0100</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>bash</category><category>script</category><category>sed</category><category>shell</category><category>terminal</category>    
    <description>&lt;p&gt;Développant sur Google Appengine en ce moment, en python, j'utilise les logs
à foison. Ces logs sont pratique et ont un niveau d'information (WARNING, INFO,
ERROR...). Mais la lisibilité n'est pas forcément adaptée, car en effet les
logs sont simplement des lignes de texte. C'est alors qu'une idée m'a frappée
(sans gravité, j'ai pas eut mal): et si je colorisai la sortie. Ma méthode
fonctionne pour à peu près tous les programmes que vous utilisez dans un
terminal, et peut être adaptée à pas mal de situations&lt;/p&gt;    &lt;p&gt;L'idée est simple, il suffit de rediriger les sorties du programme dans un
descripteur qui va modifier la sortie. Avant tout, laissez moi vous expliquer
comment coloriser du texte dans un terminal (si vous ne savez pas comment),
puis comment utiliser `sed` avec la subtilité. Enfin, on va passer par une
commande `exec` qui va opérer notre transformation.&lt;/p&gt;
&lt;p&gt;Premier point, les couleurs dans un terminal.&lt;/p&gt;
&lt;p&gt;Bash (ou d'autres shell) permet de coloriser une chaine de caractères. Le
principe étant de donner un caractère spécial, puis un code couleur, puis la
chaine.&lt;/p&gt;
&lt;p&gt;Ainsi, pour coloriser en rouge, en entre la séquence &amp;quot;\033[31m&amp;quot; puis la
chaine. Il faut juste comprendre cela:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\033 =&amp;gt; caractère qui prévient qu'on va changer de couleur, de poids de
fonte...&lt;/li&gt;
&lt;li&gt;[ =&amp;gt; on va donner une couleur&lt;/li&gt;
&lt;li&gt;33 =&amp;gt; code couleur du rouge&lt;/li&gt;
&lt;li&gt;m =&amp;gt; terminé&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cette séquence retourne un caractère spécial&lt;/strong&gt; c'est
important de bien le comprendre, car en réalité toute la subtilité de ce que
nous allons faire repose sur ce principe. Ce caractère est invisible, il est
interprété par le terminal pour changer la couleur.&lt;/p&gt;
&lt;p&gt;Cela ne suffit pas, il faudra que le terminal sache gérer les caractères
échapés, je parle du &amp;quot;\033&amp;quot;. La commande &amp;quot;echo&amp;quot; sait bien le faire:&lt;/p&gt;
&lt;pre&gt;
echo -e &amp;quot;\033[31mEt hop une couleur&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Le souci, c'est que là votre console passe en rouge... et ne revient pas au
mode &amp;quot;normal&amp;quot;. Pour cela, on utilise la couleur &amp;quot;0&amp;quot;&lt;/p&gt;
&lt;pre&gt;
echo -e &amp;quot;\033[0mOn revient à la normale&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Pour faire plus simple, on peut directement activer la couleur, entrer la
chaine, puis revenir à la normale:&lt;/p&gt;
&lt;pre&gt;
echo -e &amp;quot;\033[31mHoulla une erreur en rouge\033[0m&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Les couleurs qu'on va utiliser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;31 rouge =&amp;gt; pour les erreurs&lt;/li&gt;
&lt;li&gt;33 orange =&amp;gt; pour les warnings&lt;/li&gt;
&lt;li&gt;34 bleu =&amp;gt; pour les infos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bien, passons à `sed`. Cet outil permet de faire des opération sur du texte
assez facilement en utilisant une syntaxe proche du perl. Ainsi, la commande
&amp;quot;s&amp;quot; de sed permet de &amp;quot;substituer&amp;quot; du texte, comprennez &amp;quot;le remplacer&amp;quot;&lt;/p&gt;
&lt;p&gt;Dans une commande sed &amp;quot;s&amp;quot;, le caractère &amp;quot;&amp;amp;&amp;quot; correspond à la chaine
trouvée. Ainsi, pour remplacer &amp;quot;WARNING&amp;quot; en &amp;quot;toto-WARNING-fin&amp;quot; on fera:&lt;/p&gt;
&lt;pre&gt;
echo &amp;quot;WARNING there is an error&amp;quot; | sed 's/WARNING/toto-&amp;amp;-fin/'
#affiche: toto-WARNING-fin there is an error
&lt;/pre&gt;
&lt;p&gt;Bon, vous avez compris, il faut remplacer maintenant &amp;quot;WARNING&amp;quot; en
&amp;quot;\033[33mWARNING\033[0m&amp;quot;. Sauf que voilà, sed ne sait pas utiliser le mode
&amp;quot;échappé&amp;quot;. Cela n'est rien, on va récupérer le caractère que retourne &amp;quot;echo -e&amp;quot;
pour le placer dans la chaine de remplacement. Voilà un exemple:&lt;/p&gt;
&lt;pre&gt;
NORMAL=$(echo -e &amp;quot;\033[0m&amp;quot;)
ORANGE=$(echo -e &amp;quot;\033[33m&amp;quot;)

echo &amp;quot;WARNING there is an error&amp;quot; | sed &amp;quot;s/WARNING/$ORANGE&amp;amp;$NORMAL/&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Simple en fait, relisez bien vous allez comprendre.&lt;/p&gt;
&lt;p&gt;Bien, reste à faire ça pour toutes les lignes de sortie d'un programme.
Reprenons notre exemple avec GAE, j'ai des message &amp;quot;WARNING, INFO et
ERROR&amp;quot;.&lt;/p&gt;
&lt;p&gt;Le souci, c'est que la sortie est &amp;quot;en continue&amp;quot;, mais on va utiliser une
commande qui va gérer une redirection de flux: exec&lt;/p&gt;
&lt;p&gt;Si vous ne le savez pas, un shell utilise des descripteurs connus: 1 =
sortie standard, 2 = sortie d'erreur. Si je redirige une sortie dans un de ces
flux, il sera traité de différente manières.&lt;/p&gt;
&lt;p&gt;Pour rediriger dans un flux, on utilise la séquence &amp;quot;N&amp;gt;&amp;amp;M&amp;quot; où N est
le flux d'entrée, et M le flux où on redirige. Ainsi:&lt;/p&gt;
&lt;pre&gt;
#on redirige la sortie normale dans le flux d'erreur
echo &amp;quot;pouet pouet&amp;quot; 1&amp;gt;&amp;amp;2 
#1 est utilisé par défaut, donc cela fait la même chose:
echo &amp;quot;pouet pouet&amp;quot; &amp;gt;&amp;amp;2 

#Par exemple
echo &amp;quot;pouet pouet&amp;quot;  2&amp;gt;fichier_erreur 1&amp;gt;fichier_normal 1&amp;gt;&amp;amp;2
#ici, le fichier_normal ne contien rien, par contre fichier_erreur 
#contient pouet pouet
&lt;/pre&gt;
&lt;p&gt;OK, même si cela reste obscure pour certains, ne paniquez pas... suivez
juste le reste de mon article.&lt;/p&gt;
&lt;p&gt;&amp;quot;exec&amp;quot; peut ouvrir un descripteur, simplement en lançant &amp;quot;exec 3&amp;gt; ...&amp;quot; On
aura alors un nouveau flux portant le numéro 3.&lt;/p&gt;
&lt;p&gt;Donc:&lt;/p&gt;
&lt;pre&gt;
exec 3&amp;gt;fichier
echo &amp;quot;pouet pouet&amp;quot; &amp;gt;&amp;amp;3
&lt;/pre&gt;
&lt;p&gt;ici, on redirige le flux 3 dans un fichier, donc en écrivant dans le flux,
on écrit dans un fichier...&lt;/p&gt;
&lt;p&gt;Autre subtilité des shells: &amp;quot;&amp;gt;(une commande)&amp;quot; (surtout pas d'espace après
le &amp;gt;) la commande entre parenthèse est considéré comme un fichier&lt;/p&gt;
&lt;p&gt;Ainsi:&lt;/p&gt;
&lt;pre&gt;
exec 3&amp;gt; &amp;gt;(sed 's/toto/pouet/g')
echo &amp;quot;j'ai pas toto mais j'aime truc&amp;quot; &amp;gt;&amp;amp;3
echo &amp;quot;toto toto :)&amp;quot; &amp;gt;&amp;amp;3
&lt;/pre&gt;
&lt;p&gt;Vous comprennez ce qu'il se passe: tout ce que j'écris dans le &amp;quot;descripteur
3&amp;quot; passe dans la commande &amp;quot;sed...&amp;quot; Ha... on y arrive !&lt;/p&gt;
&lt;pre&gt;
NORMAL=$(echo -e &amp;quot;\033[0m&amp;quot;)
ORANGE=$(echo -e &amp;quot;\033[33m&amp;quot;)
RED=$(echo -e &amp;quot;\033[31m&amp;quot;)
BLUE=$(echo -e &amp;quot;\033[34m&amp;quot;)

exec 3&amp;gt; &amp;gt;(sed &amp;quot;s/WARNING/$ORANGE&amp;amp;$NORMAL/g;   s/ERROR/$RED&amp;amp;$NORMAL/g; s/INFO/$BLUE&amp;amp;$NORMAL/g&amp;quot; )

ma_commande &amp;gt;&amp;amp;3

&lt;/pre&gt;
&lt;p&gt;Et voilà ! Toute mes sorties de &amp;quot;ma_commande&amp;quot; passerons dans le flux
&amp;quot;3&amp;quot; et on verra un remplacement de mot par ce même mot en couleur.&lt;/p&gt;
&lt;p&gt;Si &amp;quot;ma_commande&amp;quot; utilise les flux de sortie d'erreur, vous pouvez carrément
faire:&lt;/p&gt;
&lt;pre&gt;
ma_commande 1&amp;gt;&amp;amp;2 2&amp;gt;&amp;amp;3
&lt;/pre&gt;
&lt;p&gt;Alors, ici, on utilise des couleurs, mais vous pouvez utiliser cette
technique pour mettre des balises XML, mettre le texte en minscule, ou
rediriger dans d'autre descripteurs... en gros la méthode est ouverte à pas mal
de variantes.&lt;/p&gt;
&lt;p&gt;Voilà pour aujourd'hui !&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.fedora-fr.org/metal3d/post/Coloriser-la-sortie-d-un-programme#comment-form</comments>
      <wfw:comment>http://blog.fedora-fr.org/metal3d/post/Coloriser-la-sortie-d-un-programme#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.fedora-fr.org/metal3d/feed/atom/comments/995</wfw:commentRss>
      </item>
    
  <item>
    <title>Vim en moteur de slide - Vroom</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Vim-en-moteur-de-slide-Vroom2</link>
    <guid isPermaLink="false">urn:md5:7189b8a84e4daeb8008aa57c9951a4eb</guid>
    <pubDate>Thu, 02 Aug 2012 11:49:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Multimedia</category>
        <category>bash</category><category>perl</category><category>slide</category><category>terminal</category><category>vim</category>    
    <description>&lt;p&gt;Si vous suivez un peu mon blog, vous connaissez mon adoration pour le
terminal de commande, vim et tout outil fonctionnant en mode console. J'ai
toujours trouvé plus clair ce fonctionnement que de passer par des outils
graphiques pour la moindre action. Aujourd'hui, c'est un outil de présentation
(un slide si vous préférez) que j'ai découvert. Ça va vite, c'est pratique,
c'est fonctionnel et ça marche avec Vim... En clair, ça a tout pour me plaire.
Laissez-moi vous présenter &amp;quot;vroom&amp;quot;&lt;/p&gt;    &lt;p&gt;Vroom est un package Perl installable aisément avec cpan. Il est fourni avec
un exécutable qui va vous permettre de créer rapidement un slide fonctionnant
en mode console. Ça peut paraitre fou de faire un slide en mode console, et
pourtant l'intérêt est là. Car en ayant simplement du texte vous vous forcez à
rendre &amp;quot;lisible&amp;quot; le slide.&lt;/p&gt;
&lt;p&gt;Il est clair que ce genre de slide est plutôt ciblé pour les présentations
de technologies de développement. Vroom a par ailleurs la possibilité
d'exécuter du code contenu dans un slide, ce qui vous permet de montrer un
petit bout de code et de l'exécuter afin de présenter le résultat.&lt;/p&gt;
&lt;p&gt;Quoiqu'il en soit, commençons par l'installer.&lt;/p&gt;
&lt;p&gt;Je vous l'ai dit, Vroom est un package Perl. De ce fait, on utilise CPAN
pour installer le paquet:&lt;/p&gt;
&lt;pre&gt;
su -c &amp;quot;cpan install Vroom&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Acceptez toutes les questions proposées à l'installation. En quelques
secondes vous allez avoir l'outil installé sur votre poste.&lt;/p&gt;
&lt;p&gt;Vous pouvez maintenant créer un répertoire quelque part, ici j'utiliserai
&amp;quot;~/slidetuto/&amp;quot; pour des raisons pratiques. La suite logique est la
suivante:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on créer un répertoire pour la présentation&lt;/li&gt;
&lt;li&gt;on génère un template de slide&lt;/li&gt;
&lt;li&gt;on édite le slide, on ajoute des entrées, on configure un peu...&lt;/li&gt;
&lt;li&gt;on affiche le slide&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mais avant tout, vous devez modifier un fichier qui va permettre à Vim de
lire une configuration spécifique qui sera créée par Vroom dans votre
répertoire de slide. Ouvrez le fichier &amp;quot;~/.vimrc&amp;quot; et ajoutez quelque part (à la
fin du fichier par exemple):&lt;/p&gt;
&lt;pre&gt;
&amp;quot; for vroom
set exrc
&lt;/pre&gt;
&lt;p&gt;Voilà, maintenant on y va... On commence par créer un template:&lt;/p&gt;
&lt;pre&gt;
mkdir ~/slidetuto/
cd ~/slidetuto/
vroom -new
&lt;/pre&gt;
&lt;p&gt;Un fichier est alors créé: &amp;quot;slides.vroom&amp;quot;. C'est le fichier qui va avoir
tout le contenu. Il y a pas mal de commentaires dans ce template. Pour le
moment, on ne va pas le modifier et simplement lancer le slide:&lt;/p&gt;
&lt;pre&gt;
vroom -vroom slides.vroom
&lt;/pre&gt;
&lt;p&gt;Vim se lance, et le premier slide apparait. Pressez la touche Espace et vous
passez au second slide, pressez une nouvelle fois Espace et vous voyez des
lignes apparaitre au fur et à mesure. Arrivé au slide 5 vous allez voir un bout
de code Perl. Pressez alors la séquence &amp;quot;RR&amp;quot; (Shift R R) et voilà le code
exécuté.&lt;/p&gt;
&lt;p&gt;Vous pouvez revenir en arrière avec la touche Backspace (la touche
d'effacement).&lt;/p&gt;
&lt;p&gt;Bref, arrivé à la fin du slide, vous pouvez quitter en pressant QQ (encore
une fois, avec la touche Maj enfoncée).&lt;/p&gt;
&lt;p&gt;Si vous regardez dans le répertoire, vous voyez une série de fichiers qui a
été générée. En fait, Vroom fait simplement une ouverture dans l'ordre de
fichier, et passe de buffer en buffer via un map de commande (Espace mappé en
&amp;quot;:n&amp;quot; pour passer au buffer suivant). C'est bête comme choux, mais ça
marche.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.fedora-fr.org/public/metal3d/2012-08-02-114750_1364x727_scrot.png&quot; title=&quot;Vroom&quot;&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.2012-08-02-114750_1364x727_scrot_m.jpg&quot; alt=&quot;Vroom&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;Vroom, août 2012&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Regardons le fichier slides.vrooms.&lt;/p&gt;
&lt;p&gt;En haut, une partie sert à la configuration du slide. Vous pouvez ici
surcharger un comportement de vim (par exemple, pour ma part, je dois forcer
&amp;quot;set nonumber&amp;quot; pour ne pas avoir de numéro de ligne) ou encore forcer les
dimensions de slide. Une option intéressante est justement de permettre le
calcul automatique de la taille en fonction du terminal. Il suffit de
décommenter &amp;quot;auto_size: 1&amp;quot; et le tour est joué.&lt;/p&gt;
&lt;p&gt;Du coup, vous pouvez changer la taille de police de votre terminal pour la
rendre plus lisible sur un rétroprojecteur, et tout va se caller
correctement.&lt;/p&gt;
&lt;p&gt;Ensuite, chaque slide est séparé par 4 tirets sur une ligne &amp;quot;&amp;quot;. Cette ligne
peut aussi permettre de spécialiser un slide, par exemple vous voyez dans le
template de base qu'un slide est utilisé pour lancer du Perl (et avoir la
coloration syntaxique). Les slides de code permettent d'utiliser Perl, PHP,
Python, Sh, Haskell, et quelques autres...&lt;/p&gt;
&lt;p&gt;Un double égal (==) permet de définir le titre (qui sera centré). Et si une
ligne commence par &amp;quot;+&amp;quot; alors elle n'apparaitra qu'après avoir pressé
Espace.&lt;/p&gt;
&lt;p&gt;C'est simple... et ça fonctionne.&lt;/p&gt;
&lt;p&gt;Pour ceux qui comme moi avez déjà un .vimrc fourni, et qui vous demande
d'avoir une configuration forcée, voici comment faire.&lt;/p&gt;
&lt;p&gt;Dans la partie de configuration, en haut, ajoutez simplement:&lt;/p&gt;
&lt;pre&gt;
vimrc: |
    set nonumber

&lt;/pre&gt;
&lt;p&gt;Ou tout autres options dont vous avez besoin.&lt;/p&gt;
&lt;p&gt;Il est possible d'exporter votre slide en HTML, en texte brut, et il existe
même un bindings pour envoyer vos slides sur github.&lt;/p&gt;
&lt;p&gt;Le seul défaut que j'ai trouvé est que si vous vous trompez dans la
configuration de votre slide, la commande &amp;quot;vroom -vroom slides.vroom&amp;quot; ne vous
donne aucune information... mais je pense que cela va évoluer.&lt;/p&gt;
&lt;p&gt;Voilà, j'ai tout simplement trouvé ce système intéressant, je m'en sers de
plus en plus pour faire des vidéos didacticiels, et je pense que vous pouvez
avoir un intérêt à l'utiliser.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Un OSD de capture clavier en bash</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Un-OSD-de-capture-clavier-en-bash</link>
    <guid isPermaLink="false">urn:md5:58847dab449da9f68a3752251790af55</guid>
    <pubDate>Sun, 29 Jul 2012 18:40:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>bash</category><category>osd</category><category>script</category><category>tool</category><category>xorg</category>    
    <description>&lt;p&gt;Impossible de trouver un outil OSD de capture clavier qui puisse fonctionner
convenablement avec un tilling desktop... car évidemment tous les outils que
j'ai trouvé me place la capture dans la mosaïque... Comme je suis en vacance,
je me suis pris 25 minutes à coder un truc qui marche en bash, et qui fasse du
&lt;strong&gt;vrai&lt;/strong&gt; OSD (On Screen Display), c'est à dire &amp;quot;sans fenêtre&amp;quot;. Et
comme je suis gentil, je vous montre &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;    &lt;p&gt;Je cherchais sur le net un outil qui afficherait ce que je tape au clavier
sur l'écran. Histoire de faire des captures pour des didacticiels vidéo. J'ai
cherché un peu partout, rien ne me plaisait vraiment... je me suis alors penché
sur une solution à coder. Deux outils sont utilisés: xosd et xinput. OSD
voulant dire: On Screen Display, c'est à dire &amp;quot;Affichage sur l'écran&amp;quot;&lt;/p&gt;
&lt;p&gt;Je suis d'abord parti en Python... puis en quelques minutes je me suis dit
que &amp;quot;finalement, en bash, ce sera tout aussi simple à gérer&amp;quot;... vous me pensez
fou, c'est pas faux...&lt;/p&gt;
&lt;p&gt;Pourquoi utiliser un &lt;strong&gt;vrai&lt;/strong&gt; OSD ? tout simplement parce
que ça m'énervait d'avoir une fenêtre qui affiche les contrôles... je bosse sur
Xmonad, et par conséquent le mode &amp;quot;tilling&amp;quot; en fait baver les outils que j'ai
trouvé...&lt;/p&gt;
&lt;p&gt;Avant de pouvoir utiliser mon script il vous faudra installer 3 paquets (je
ne sais pas lesquels sont là par défaut):&lt;/p&gt;
&lt;pre&gt;
yum install util-linux xosd xorg-x11-apps
&lt;/pre&gt;
&lt;p&gt;Cela vous donne quelques commandes que mon script utilise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;xinput qui va capter ce que vous tapez&lt;/li&gt;
&lt;li&gt;osd_cat qui affiche des choses sur l'écran&lt;/li&gt;
&lt;li&gt;script qui va capturer une sortie terminal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le script que vous allez voir par la suite fait quelques manipulations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;trouve le clavier par défaut: je cherche un clavier qui a &amp;quot;AT&amp;quot; dans &amp;quot;xinput
--list&amp;quot;&lt;/li&gt;
&lt;li&gt;lance la capture des touches via &amp;quot;xinput test ID&amp;quot; où ID est l'identifiant
du clavier trouvé ci-dessus&lt;/li&gt;
&lt;li&gt;faire tourner ça dans &amp;quot;script&amp;quot; qui écrit le typescript dans /dev/null, mais
dont la sortie sera captée dans un FIFO&lt;/li&gt;
&lt;li&gt;cherche la correspondance de clef clavier dans &amp;quot;xmodmap -pke&amp;quot; et écrit ça
dans un autre FIFO&lt;/li&gt;
&lt;li&gt;et enfin, en boucle, on lit le FIFO de sortie clavier qu'on inject dans
&amp;quot;osd_cat&amp;quot; avec des options de couleur, de placement, de fontes...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je me suis amusé à savoir si on pressait une touche de modification (Maj,
Ctrl, Super...) pour concaténer les chaines.&lt;/p&gt;
&lt;p&gt;Le script est &lt;strong&gt;loin&lt;/strong&gt; d'être parfait, il affiche mal la touche
&amp;quot;AltGr&amp;quot; et vous ne pouvez pas non plus faire des maintiens de touches trop
complexe en séquence. Par exemple il est impossible de presser:&lt;/p&gt;
&lt;p&gt;Ctrl+shift+a puis relacher shift et a en gardant Ctrl pessé et frapper une
autre touche sans relacher Ctrl&lt;/p&gt;
&lt;p&gt;Bref, le but était de faire un truc fonctionnel, rapidement, et qui me
permette de faire à peu près ce que je veux... Je ferai évoluer le script et je
le mettrai à jour ici.&lt;/p&gt;
&lt;p&gt;Attention les yeux, voici le script:&lt;/p&gt;
&lt;pre class=&quot;bash bash&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#author Patrice Ferlet&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#Licence BSD&lt;/span&gt;
 
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#some conf vars&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;COLOR&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Purple&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;FONT&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;'-*-terminus-*-*-*-*-32-*-*-*-*-*-*-*'&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;DELAY&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;5&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;XPOS&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;center&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;YPOS&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;bottom&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;OFFSET&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;15&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;INDENT&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;80&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;MAXLINE&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#FIFOS&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;_tmp_opt&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-d&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;dev&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;shm &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#some unix can use shared memory instead of /tmp&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;_tmp_opt&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot; --tmpdir=/dev/shm&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;fi&lt;/span&gt;
 
&lt;span style=&quot;color: #007800;&quot;&gt;OSDPID&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;TMP&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mktemp&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-u&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$_tmp_opt&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;OSD&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mktemp&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-u&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$_tmp_opt&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mkfifo&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$TMP&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mkfifo&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OSD&lt;/span&gt;
 
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#when script is closed, remove fifos&lt;/span&gt;
onexit&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;close...&amp;quot;&lt;/span&gt;
    &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;kill&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OSDPID&lt;/span&gt;
    &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$TMP&lt;/span&gt;
    &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OSD&lt;/span&gt;
    &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;exit&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;}&lt;/span&gt;
&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;trap&lt;/span&gt; onexit INT TERM
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#get valid keyboard input&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;kb&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;xinput &lt;span style=&quot;color: #660033;&quot;&gt;--list&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;keyboard&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AT&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-Po&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;id=\d+&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;cut&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-d&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;=&amp;quot;&lt;/span&gt; -f2&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#launch &amp;quot;script&amp;quot; to capture xinput, this is a trick !&lt;/span&gt;
script &lt;span style=&quot;color: #660033;&quot;&gt;-c&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;xinput test &lt;span style=&quot;color: #007800;&quot;&gt;$kb&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;dev&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;null &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$TMP&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#lauch osd command that read OSD fifo&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;tail&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OSD&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; osd_cat &lt;span style=&quot;color: #660033;&quot;&gt;-a&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-d&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$DELAY&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-l&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$MAXLINE&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$FONT&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-A&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$XPOS&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-o&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OFFSET&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-i&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$INDENT&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-p&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$YPOS&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-c&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$COLOR&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;OSDPID&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$!&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#be sure everything is launched&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sleep&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;0.2&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#now, read lines from xinput output to do the job&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;MOD&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;read&lt;/span&gt; line; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#reading code, state (press, release) and get keyboard value&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#from xmodmap&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;code&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$line&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;awk&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'{print $3}'&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;state&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$line&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;awk&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'{print $2}'&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;key&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;xmodmap&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-pke&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;awk&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/keycode\s*&lt;span style=&quot;color: #007800;&quot;&gt;$code&lt;/span&gt;\s+/ {print &lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\$&lt;/span&gt;4}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; $&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$key&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-Pi&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Control|Shift|Alt|Super&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;
        &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#this case should not be displayed, we only record mod key&lt;/span&gt;
        &lt;span style=&quot;color: #007800;&quot;&gt;MOD&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$MOD&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$key&lt;/span&gt; + &amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$state&lt;/span&gt;&amp;quot;&lt;/span&gt; == &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;release&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;
            &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#mod released, remove mod&lt;/span&gt;
            &lt;span style=&quot;color: #007800;&quot;&gt;MOD&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;fi&lt;/span&gt;
    &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;elif&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$state&lt;/span&gt; == &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;press&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;
        &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; $&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$MOD&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Shift&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;
            &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#shift pressed, we should read 5th column&lt;/span&gt;
            &lt;span style=&quot;color: #007800;&quot;&gt;key&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;xmodmap&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-pke&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;awk&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/keycode\s*&lt;span style=&quot;color: #007800;&quot;&gt;$code&lt;/span&gt;\s+/ {print &lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\$&lt;/span&gt;5}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;fi&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$MOD&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$key&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$OSD&lt;/span&gt;
    &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;fi&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;done&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$TMP&lt;/span&gt;
&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;exit&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous lancez ce script dans un terminal, puis n'importe où vous pressez des
touches... Cela les affiches en OSD. Voilà, c'est ce que je voulais... rien de
plus.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.2012-07-29-185116_877x247_scrot_m.jpg&quot; alt=&quot;OSD keys Bash&quot; title=&quot;OSD keys Bash, juil. 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Pour arrêter le script, retournez sur le terminal et pessez &lt;em&gt;CTRL+c&lt;/em&gt;,
cela coupe le script, en supprimant les FIFO en passant.&lt;/p&gt;
&lt;p&gt;Voilà, si vous avez des questions, des remarques... je suis
preneur !&lt;/p&gt;
&lt;p&gt;UPDATE: et oui, il manque un truc... je coupe pas osd_cat à la fermeture, je
corrige le script de suite... désolé UPDATE: Voilà, corrigé&lt;/p&gt;</description>
    
          <enclosure url="http://blog.fedora-fr.org/public/metal3d/osdkeys.sh"
      length="1873" type="text/plain" />
    
    
      </item>
    
  <item>
    <title>Correction orthographique et grammaticale avec Vim</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Correction-orthographique-et-grammaticale-avec-Vim</link>
    <guid isPermaLink="false">urn:md5:e4a75ec79c52d5d54f9f7725e54db64e</guid>
    <pubDate>Sun, 03 Jun 2012 21:28:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>plugin</category><category>terminal</category><category>vim</category>    
    <description>&lt;p&gt;J'en avais assez de voir que je tapais faute sur faute en préparant mes
billets sous Vim... je suis mauvais en orthographe, et pire en grammaire. J'ai
honte souvent de cette tare, alors j'ai décidé de fouiller pour trouver une
méthode propre pour supprimer un bon paquets de fautes en utilisant mon éditeur
favori. Voici ce que j'ai à vous proposer.&lt;/p&gt;    &lt;p&gt;Vous êtes comme moi un mordu de Vim, vous tapez vos documents en RST, en
Latex, ou je ne sais quel format brut. Vous avez un manque, celui d'avoir
l'auto-correction orthographique et grammaticale. Je viens de me configurer mon
éditeur favori pour avoir la correction des deux aspects.&lt;/p&gt;
&lt;p&gt;Nous allons devoir installer quelques fichiers. En premier lieu, il faut
récupérer les dictionnaires français de vim. La manière la plus simple est de
faire:&lt;/p&gt;
&lt;pre&gt;
mkdir -p ~/.vim/spell
cd ~/.vim/spell
wget http://ftp.vim.org/vim/runtime/spell/fr.latin1.spl
wget http://ftp.vim.org/vim/runtime/spell/fr.latin1.sug
wget http://ftp.vim.org/vim/runtime/spell/fr.utf-8.spl
wget http://ftp.vim.org/vim/runtime/spell/fr.utf-8.sug
&lt;/pre&gt;
&lt;p&gt;Fermez vim si vous en avez déjà ouvert un. Cela permettra de s'assurer que
tout soit pris en compte au démarrage.&lt;/p&gt;
&lt;p&gt;Pour tester l'option spell, ouvrons un éditeur vim et rédigeons quelques
phrases. Faites en sorte de faire des fautes, puis pressez: Echap, :set
spelllang=fr spell&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.vim-corr-1_m.jpg&quot; alt=&quot;vim correction activé&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;vim correction activé, juin 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Cela permet d'activer la langue française, puis de mettre en surbrillance
les mots erronés. Toujours en mode commande (donc en ayant pressé sur Echap),
allez au début du document en pressant &amp;quot;gg&amp;quot;, puis &amp;quot;]s&amp;quot;. Le curseur se déplace
au premier mot mal orthographié. Vous avez alors plusieurs options :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pressez &amp;quot;z=&amp;quot; et vous entrez dans le mode &amp;quot;choix de mot&amp;quot; - taper Enter ou le
numéro du mot que vous voulez utiliser.&lt;/li&gt;
&lt;li&gt;presser &amp;quot;zg&amp;quot; pour ajouter le mot dans le dictionnaire local&lt;/li&gt;
&lt;li&gt;presser &amp;quot;zG&amp;quot; pour l'ajouter au dictionnaire global&lt;/li&gt;
&lt;li&gt;presser &amp;quot;]s&amp;quot; pour aller au prochain mot&lt;/li&gt;
&lt;li&gt;presser &amp;quot;[s&amp;quot; pour aller au prochain mot&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.vim-corr-2_m.jpg&quot; alt=&quot;vim liste de suggestions&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;vim liste de suggestions, juin 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Ce procédé est sympa pour une phase finale, après avoir rédigé. Mais si vous
voulez avoir une mode de correction en cours de frappe, il existe une autre
commande. Vim permet de compléter un mot lorsque l'on s'en sert d'éditeur de
code. On utilise alors CTRL+X puis une lettre correspondant à un mode de
complétion.&lt;/p&gt;
&lt;p&gt;Le mode utilisé pour &amp;quot;spell&amp;quot; est &amp;quot;s&amp;quot;. Donc, après avoir tapé un mot de la
mauvaise manière, il suffit, sans quitter le mode &amp;quot;insert&amp;quot;, de presser CTRL+X
puis &amp;quot;s&amp;quot;. Une liste de propositions de mots s'affiche. Sélectionnez celui qui
vous plait, puis pressez &amp;quot;espace&amp;quot; ou tout autre caractère pour continuer la
rédaction. &lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.vim-corr-3_m.jpg&quot; alt=&quot;vim completion orthographique&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;vim completion orthographique, juin 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Reste maintenant à avoir une correction grammaticale. Pour cela, nous allons
utiliser un outil en Java servi dans les options d'OpenOffice, et un plugin Vim
fortement bien pensé.&lt;/p&gt;
&lt;p&gt;Commençons par l'outil Java en question. Il se nomme LanguageTool et se
trouve à l'adresse: http://www.languagetool.org/&lt;/p&gt;
&lt;p&gt;Il suffit de décompresser le fichier zip dans un répertoire de votre choix,
cela va vous proposer deux fichiers, un &amp;quot;.jar&amp;quot; et un &amp;quot;.oxt&amp;quot; qui vont vous
permettre la correction grammaticale. L'intégration à vim se fait avec le
plugin: http://www.vim.org/scripts/script.php?script_id=3223&lt;/p&gt;
&lt;p&gt;Suivons le procédé recommandé, on télécharge la dernière version, puis:&lt;/p&gt;
&lt;pre&gt;
cd ~/.vim
unzip /chemin/vers/LanguageTool.zip
&lt;/pre&gt;
&lt;p&gt;On finit par configurer l'outil en ouvrant le fichier ~/.vimrc, et en
plaçant quelque part cette ligne:&lt;/p&gt;
&lt;pre&gt;
:set spelllang=fr
let g:languagetool_jar='/chemin/vers/LanguageTool.jar'
&lt;/pre&gt;
&lt;p&gt;En remplaçant évidemment le chemin par la bon. Je vous conseille d'utiliser
un répertoire simple à retrouver, genre /usr/local/LanguageTool ou comme moi
dans un répertoire utilisé pour compiler vous même l'outil. J'utilise pour ma
part la version SVN que je mets à jour souvent et que je compile simplement
avec &amp;quot;ant&amp;quot;. Si vous éditez votre vimrc avec vim, n'oubliez pas le racourcis (en
mode insert) &amp;quot;CTRL+X f&amp;quot; qui complète le chemin.&lt;/p&gt;
&lt;p&gt;Voilà, on rouvre notre texte, et on va s'amuser. Activez si vous le
souhaitez le mode &amp;quot;spell&amp;quot; en tapant: &amp;quot;Echap, :set spell&amp;quot;&lt;/p&gt;
&lt;p&gt;Tapez avec des fautes, faites vraiment des erreurs (accords, temps, double
virgule...), puis pressez: Echap, &amp;quot;:LanguageToolCheck&amp;quot; (la touche tabulation
complète les commandes je vous rappelle).&lt;/p&gt;
&lt;p&gt;Après quelques secondes, un mini buffer apparaît et vous donne une liste
complète des fautes possibles que vous auriez faites, avec si possible des
proposition de correction. Allez dans ce minibuffer en pressant CTRL+W w et
faites défiler la liste. En pressant sur la touche Entrée votre curseur ira à
la faute, ou parfois (je ne sais pas pourquoi) au début de la phrase erronée.
Il suffit de les corriger au fur et à mesure. Pour nettoyer le texte des
surlignages, vous pouvez simplement taper: Echap puis &amp;quot;:LanguageToolClean&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.vim-corr-4_m.jpg&quot; alt=&quot;vim et LanguageTool&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;vim et LanguageTool, juin 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Et pour supprimer le surlignage du mode spell, Echap, &amp;quot;:set nospell&amp;quot;&lt;/p&gt;
&lt;p&gt;Bref, voilà de quoi vous amuser à corriger la plupart de vos erreurs dans un
éditeur tel que Vim. Vous prendrez vite cette habitude de lancer la commande,
et de mettre le mode &amp;quot;spell&amp;quot; en marche.&lt;/p&gt;
&lt;p&gt;Certes, il restera des erreurs parfois, à vous de relire et de ne pas vous
lasser de vérifier mot à mot les coquilles possibles. Mais ces outils vont au
moins permettre d'éliminer un bon paquet d'erreurs. Alors ne vous en privez
pas. Personnellement j'en avais tellement assez de vous poster des billets
bourrés de fautes que je suis passé à ces outils... Ne m'en voulez pas s'il en
reste encore... je vous promet de faire des efforts.&lt;/p&gt;
&lt;p&gt;Notez que LanguageTool - l'outil java - permet aussi de prendre en argument
le fichier à corriger. Donc, vous pourrez vous en servir en dehors de vim ou en
l'intégrant dans Emacs, Gedit, ou quelques autres éditeurs acceptant les
greffons (plugins)&lt;/p&gt;
&lt;p&gt;En espérant vous avoir fait découvrir un outil sympathique &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Ha oui un dernier truc, comme je suis dans un terminal, et que je veux
copier mon billet depuis vim vers mon navigateur, je sauve mon fichier et je
fais simplement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Echap&lt;/li&gt;
&lt;li&gt;:!xclip %&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le fichier est alors copié dans le presse-papier, reste plus qu'à le coller
dans l'éditeur (bouton central de la souris, ou Maj+Insert). On gagne du
temps...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Go, routines et canaux - introduction au langage</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Go-et-les-goroutines-introduction-au-langage</link>
    <guid isPermaLink="false">urn:md5:1223692e5e62bac32a394234f35815ba</guid>
    <pubDate>Mon, 28 May 2012 13:03:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>développement</category><category>go</category><category>golang</category><category>google</category><category>performance</category>    
    <description>&lt;p&gt;Il y tellement de nouveaux langages, quand un de ceux là sort du lot c'est
en général parce qu'il offre des concepts particuliers. Go est un de ceux là,
et les concepts de routines, de canaux et de fonctions différées ne sont qu'une
infime partie des possibilités que vous pouvez découvrir dans ce langage.
Testons un peu ce langage.&lt;/p&gt;    &lt;p&gt;J’ai la chance d’aimer mon métier, et dans ce métier on apprend souvent de
nouvelles choses, des concepts, des langages... Dans le panel de langages
informatique que j’ai put entrevoir, certains m’ont vraiment surpris dans leur
concept. Le premier dont j’ai eut beaucoup de mal à m’approcher est le Haskell,
et depuis peu je me penche sur Go. Je m’empresse donc de vous montrer un peu
l’intérêt que je vois dans ce langage.&lt;/p&gt;
&lt;p&gt;C’est Nicolas Engel, avec qui j’ai travaillé sur un projet, qui m’en a
reparlé et l’envie de me repencher sur Go s’est vite manifesté.&lt;/p&gt;
&lt;p&gt;Alors Go c’est quoi ?&lt;/p&gt;
&lt;p&gt;Ce langage a été créé par une équipe de Google depuis 2010 et a pour
vocation de réduire des problématiques que beaucoup de développeurs doivent
supporter dans d’autres langages. Vous pouvez utiliser le compilateur Go à
télécharger ici: http://golang.org/ ou utiliser gcc-go (package Fedora
disponible dans les dépots officiels)&lt;/p&gt;
&lt;p&gt;C’est un langage compilé, performant et sous licence BSD... La seule
complication, et vous allez voir qu’elle est dominante au début, c’est que le
concept est vraiment différent de pas mal de langages. Amis développeurs
Python, Java, PHP et même C/C++... vous allez être un peu surpris.&lt;/p&gt;
&lt;p&gt;La raison principale de la création de ce langage a été motivée par la
réduction de problématiques telles que les threads, les sémaphores, les
transferts interprocessus, les fractures mémoire, et l’impérativité des
langages communs. Vous allez voir que des concepts ont été ajoutés à Go pour
rendre tout cela vraiment très simple... si si, c’est finalement très
simple.&lt;/p&gt;
&lt;p&gt;Tout d’abord, c’est un langage fortement typé, les habitués de langages
typés dynamiquement vont devoir se faire une raison: il va falloir déclarer vos
variables. Ensuite, Go n’est pas un langage purement objet mais vous allez
facilement pouvoir déclarer des struct avec des méthodes attachées. J’entends
d’ici pas mal d’entre vous rire doucement sur un fond de “huhu aujourd’hui
faire un langage non objet... c’est juste revenir dans le passé, autant faire
du C”. Je tiens à donner mon avis là dessus, les langages orientés objet ont
leurs avantages certains, mais Go est surtout fait pour être performant dans un
premier lieu, et le C n’a rien de vieillot car même votre Linux, votre Mac ou
votre Windows est un système d’exploitation quasiment entièrement écrit en
C.&lt;/p&gt;
&lt;p&gt;Enfin, pour ma part, je n’ai aucun mal à imaginer développer une grosse
infrastructure logiciel avec un langage structuré non objet. Et surtout si
c’est en Go. Dans tous les cas, Go est adressé aux développeurs désirant un
langage proche du processeur, un peu comme C/C++ tout en gardant des
simplification en terme de threads, sémaphores et gestion mémoire. Bien que Go
permette de créer aussi des application web, et se retrouve même dans Google
AppEngine. Voyez le guide de démarrage: &lt;a href=&quot;https://developers.google.com/appengine/docs/go/gettingstarted/?hl=fr&quot;&gt;go
appengine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bref, passons la polémique trollesque et passons au langage lui même.&lt;/p&gt;
&lt;p&gt;On commence par installer le compilateur. Soit vous utilisez gcc-go (dans
les dépots) soit vous utilisez le compilateur de google à cette adresse:
&lt;a href=&quot;http://golang.org&quot;&gt;Golang&lt;/a&gt;. Je vous conseille, pour commencer,
d'utiliser celui de google et de suivre la manière dont on utilise le runtime.
En général, cela revient à faire la commande&lt;/p&gt;
&lt;pre&gt;
go run monfichier.go
&lt;/pre&gt;
&lt;p&gt;Pour le compiler réellement:&lt;/p&gt;
&lt;pre&gt;
go build monfichier.go
&lt;/pre&gt;
&lt;p&gt;Je ne vais pas vous détailler les bases du langage, mais un exemple rapide
pour vous donner la syntaxe de base:&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;package&lt;/span&gt; &lt;span style=&quot;color: #006699;&quot;&gt;main&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//fmt est le package de formatage de chaine&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;import&lt;/span&gt; “fmt”
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on retrouve une fonction main&lt;/span&gt;
func main &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
     fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;“Hello le mondo &lt;span style=&quot;color: #339933;&quot;&gt;!&lt;/span&gt;”&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Bon rien de bien compliqué, un hello world bateau. Vous remarquez donc qu’on
a une notion de package, et donc qu’on pourra séparer des fonctions et
structures dans différent package (ce qui est un plus quand on se réfère au C).
Cela ressemble fortement aux espace de nom (namespace) mais l’idée est plus
claire selon moi.&lt;/p&gt;
&lt;p&gt;Petite parenthèse, vous allez rapidement vous rendre compte au fur et à
mesure que la plupart des concepts en Go se retrouve d’une manière ou d’une
autre dans C.&lt;/p&gt;
&lt;p&gt;Alors y’a quoi de nouveau ?&lt;/p&gt;
&lt;p&gt;D’abord, comment on déclare une variable ? et bien de deux façons:&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;// i variable de type int&lt;/span&gt;
var i &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;
i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;4&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//ou bien&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//i est une entier valant 4, le typage est déduit par inférence&lt;/span&gt;
i&lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;4&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour faire simple, utiliser &amp;quot;:=&amp;quot; (oubliez pas les deux points) pour déclarer
en assignant, sinon l'assignation se fait avec un simple &amp;quot;=&amp;quot;&lt;/p&gt;
&lt;p&gt;Voilà, pas plus pas moins... on va pas parler de pointeur et de structure de
suite, mais vous n’aurez pas de mal à comprendre en lisant la documentation ou
en faisant le gotour (voir les liens en fin de billtet)&lt;/p&gt;
&lt;p&gt;Je vais vous lister 3 concepts qui m’ont plut dans ce langage. Le premier
est le concept de “goroutine” qui est foncièrement parlant une méthode pour
créer des threads sans se prendre la tignasse et se taper le front sur le
clavier. Le second concept est le principe de canal (channel) qui permet
tellement de choses qu’on s’attriste de ne pas les avoir dans les autres
langages (du moins pas sous cette forme). Un canal permet de faire transiter
des valeurs d’un processus à l’autre, de bloquer un processus tant qu’un autre
n’est pas terminé et en plus de bufferiser tout ça. C’est le concept de
sémaphore (mutex) amélioré dans sa conception. Le troisième concept est la
possibilité de différer un appel dans le temps (defer). Cela rend le code
lisible à souhait.&lt;/p&gt;
&lt;p&gt;Un autre concept, que l’on retrouve un peu en python, est le fait de pouvoir
retourner plusieurs valeurs de plusieurs types depuis une fonction. Ceux qui
n’ont pas compris l’intérêt devrait penser simplement à cela: imaginez une
fonction qui retourne un résultat et un code d’erreur. Plutôt que de devoir
retourner une structure, ou un objet pour les langages qui le permettent, on
retourne une liste simple de variables.&lt;/p&gt;
&lt;p&gt;Bref, passons aux goroutines de suite.&lt;/p&gt;
&lt;p&gt;L’appel à une routine se fait simplement via le mot clef “go”. La fonction
sera appelée dans un thread (mais dans le même processus, on ne parle pas d’un
fork ici, mais bien d’un thread) et rien d’autre n’est à faire !&lt;/p&gt;
&lt;p&gt;Je ne vous ai pas encore parlé des canaux, donc cet exemple ne va pas
fonctionner exactement comme on le veut, mais le concept est là. Ne cherchez
pas si ça fonctionne mal chez vous.&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;package&lt;/span&gt; &lt;span style=&quot;color: #006699;&quot;&gt;main&lt;/span&gt;
 
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
 
func hello&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;you string&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;for&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;++&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
        fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;hello you:&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; you&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
func main &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    go hello&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;Pierre&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    hello &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;Paul&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ce qui va vous donner (selon la manière dont les threads sont créé sur votre
OS):&lt;/p&gt;
&lt;pre&gt;
hello you:Paul
hello you:Pierre
hello you:Paul
hello you:Pierre
hello you:Paul
hello you:Pierre
hello you:Pierre
hello you:Pierre
hello you:Paul
hello you:Paul
&lt;/pre&gt;
&lt;p&gt;Vous l’avez remarqué, j’ai parfois 3 fois “Pierre” qui apparait, parfois 2
fois “Paul”. Cela est le fait que la routine est géré selon les disponibilités
du CPU.&lt;/p&gt;
&lt;p&gt;Bon, on passe aux canaux. Là vous risquez de perdre un peu le fil, mais je
vous assure que la capacité de ce concept est tout bonnement génial.&lt;/p&gt;
&lt;p&gt;Un canal est un type dont le principe est d’empiler des valeurs et de
bloquer le processus si on cherche à lire dedans, et que celui-ci si il est
vide. C’est le principe du FIFO. L’intérêt est sa syntaxe aisée et lisible.&lt;/p&gt;
&lt;p&gt;Il faut utiliser la fonction “make” (genre de malloc, mais orienté fabrique
ou factory) pour créer un “chan”.&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//canal prenant des entiers&lt;/span&gt;
c &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; make &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Un canal peut prendre n'importe quel type, entier, flottants, chaines... et
même des structures.&lt;/p&gt;
&lt;p&gt;Ensuite c’est plutôt simple... On utilise “&amp;lt;-” pour placer des valeurs
dans le flux.&lt;/p&gt;
&lt;p&gt;Donc:&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//empile un entier (1) dans le canal&lt;/span&gt;
c &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et pour lire le canal&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//bloque tant que rien n’est empilé dans c&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on peut récupérer la valeur empilée&lt;/span&gt;
&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; val &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;c2
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//ou simplement attendre une écriture dans la canal&lt;/span&gt;
&lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;c2
&lt;/pre&gt;
&lt;p&gt;Faisons simple, on va juste comprendre le principe du canal:&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;package&lt;/span&gt; &lt;span style=&quot;color: #006699;&quot;&gt;main&lt;/span&gt;
 
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
 
func routine&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;a, b chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
     i &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;a
     fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Printf&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je viens de lire dans le canal: %d&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, i&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
 
     &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//'main' attend toujours, je vais écrire dans le canal b&lt;/span&gt;
     &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//pour le débloquer&lt;/span&gt;
     b &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
func main&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    a,b &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; make&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;, make&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on écrit dans a&lt;/span&gt;
    a &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;2&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on lance une fonction en parallèle&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//qui reçoit les deux canaux en paramètres&lt;/span&gt;
    go routine1&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;a,b&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on va attendre la fin de la routine&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//la routine doit écrire dans le canal b &lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//pour que cette instruction se débloque&lt;/span&gt;
    &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; b
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;voilà, j'ai fini, b a été lut&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour le moment on s'amuse à débloquer des canaux en écrivant dedans. Sachez
que vous pouvez fermer un canal avec la fonction &amp;quot;close&amp;quot; mais si vous en avez
besoin, c'est que vous être dans un cas particulier. Car en fait, Go n'aime pas
que des canaux restent ouverts avec une valeur bloquée et non lut... pensez à
traiter correctement les canaux, sinon forcez la fermeture avec &amp;quot;close&amp;quot;&lt;/p&gt;
&lt;p&gt;Voyons un autre exemple de code qui va fonctionner avec un canal d’entier.
Un peu plus salé par contre...&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;package&lt;/span&gt; &lt;span style=&quot;color: #006699;&quot;&gt;main&lt;/span&gt;
 
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;
 
 
func thread1 &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt; sem, done chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 1, je commence à bosser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//grosse fonction qui prend du temps&lt;/span&gt;
    time.&lt;span style=&quot;color: #006633;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;*&lt;/span&gt; 1e9&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on débloque le sémaphore&lt;/span&gt;
    sem&lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;0&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on travaille encore un peu&lt;/span&gt;
    time.&lt;span style=&quot;color: #006633;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;*&lt;/span&gt; 1e9&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 1, je préviens main que je termine&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//je préviens que la routine est finie&lt;/span&gt;
    done&lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;1&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//voir plus bas (dans thread2), &lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//cette méthode va permettre&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//une exécution différée&lt;/span&gt;
func send&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;c chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;, num &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    c &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; num
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
func thread2 &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;sem, done chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//autre manière de s'assurer qu'on écrit bien à la&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//fin de la fonction :&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//defer permet de différer l'appel à &amp;quot;send&amp;quot; &lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//à la fin de ma fonction&lt;/span&gt;
    defer send&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;done, &lt;span style=&quot;color: #cc66cc;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; 
 
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 2, je commence à bosser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on attend la fin de thread 1&lt;/span&gt;
    &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;sem
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 2, on m'a débloqué&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on bosse encore un peu&lt;/span&gt;
    time.&lt;span style=&quot;color: #006633;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;2&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;*&lt;/span&gt; 1e9&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//quant sleep a terminé, la fonction différée va&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//être exécutée&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
func main&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//sem va me permettre de gérer les bloquage et débloquage&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//des goroutines&lt;/span&gt;
    sem &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; make &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//ce canal sera emplilé par la seconde routine pour dire&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//à la fonction main qu'il a terminé&lt;/span&gt;
    done &lt;span style=&quot;color: #339933;&quot;&gt;:=&lt;/span&gt; make &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on lance les deux routine en parallèle, elle vont communiquer&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//au traver de sem&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on remplira &amp;quot;done&amp;quot; pour dire que le thread est terminé&lt;/span&gt;
    go thread1 &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;sem, done&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    go thread2 &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;sem, done&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis dans main, j'attend la fin en lisant le canal 'done'&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//les routines vont écrire dans &amp;quot;done&amp;quot;,&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//j'attend que ce soit le cas pour les deux threads&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//donc on attend 2 fois&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//la variable i récupérera la valeur envoyé dans le canal&lt;/span&gt;
    var i &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;
    i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;done
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Printf&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;routine %d vient d'écrire dans le canal 'done'&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, i&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
    i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;done
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Printf&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;routine %d vient d'écrire dans le canal 'done'&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, i&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis dans la fonction main, on m'a débloqué&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Voilà ce que donne mon programme:&lt;/p&gt;
&lt;pre&gt;
je suis dans main, j'attend la fin en lisant le canal 'done'
je suis le thread 1, je commence à bosser
je suis le thread 2, je commence à bosser
je suis le thread 2, on m'a débloqué
je suis le thread 1, je préviens main que je termine
routine 1 vient d'écrire dans le canal 'done'
routine 2 vient d'écrire dans le canal 'done'
je suis dans la fonction main, on m'a débloqué
&lt;/pre&gt;
&lt;p&gt;Ce qui est exactement ce que je voulais. La fonction main s’est mise en
attente, les deux threads on commencé à travailler en parralèle. La routine 1
déblique la routine 2, mais cette routine 1 fini certaines choses en même
temps. Enfin, la fonction “main” remprend la main (non c’est pas un jeu de
mot)...&lt;/p&gt;
&lt;p&gt;Plutôt que de créer une fonction &amp;quot;send&amp;quot; qui n'est utilisée que dans le
thread 2, on peut utiliser un système de closure. Car en effet, les fonctions
en Go sont des closures. Revoyons le code du thread 2:&lt;/p&gt;
&lt;pre class=&quot;java java&quot; style=&quot;font-family:inherit&quot;&gt;
func thread2 &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;sem, done chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//autre manière de s'assurer qu'on écrit bien à la&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//fin de la fonction :&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on crée une closure exécutée en fin de fonction&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//notez que c est local à la closure, la closure prend &amp;quot;done&amp;quot;&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//en argument, donc c correspondra à done&lt;/span&gt;
    defer func &lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;c chan &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
        c &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;2&lt;/span&gt; 
   &lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;done&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 2, je commence à bosser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on attend la fin de thread 1&lt;/span&gt;
    &lt;span style=&quot;color: #339933;&quot;&gt;&amp;lt;-&lt;/span&gt;sem
    fmt.&lt;span style=&quot;color: #006633;&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;je suis le thread 2, on m'a débloqué&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on bosse encore un peu&lt;/span&gt;
    time.&lt;span style=&quot;color: #006633;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;2&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;*&lt;/span&gt; 1e9&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//quant sleep a terminé, la fonction différée va&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//être exécutée&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous pouvez donc supprimer la fonction &amp;quot;send&amp;quot;. On retrouve ici un concept de
fonction &amp;quot;inline&amp;quot; interne à une fonction. En bref, la capacité qu'à Go à vous
simplifier la vie est vraiment intéressante.&lt;/p&gt;
&lt;p&gt;Bref, là je n’ai fait qu’une introduction à Go... je n’ai pas le recul ni
l’expérience nécessaire pour aller plus dans le détail (bien que je m’amuse
comme un fou avec des tests bourrins). Je vous conseille d’aller lire le
“gotour” ici : &lt;a href=&quot;http://tour.golang.org&quot;&gt;GoTour&lt;/a&gt;. Je vous
conseille de bien vous pencher sur les notions de &amp;quot;range&amp;quot;, de retour de
plusieurs variables depuis une fonction mais aussi sur les concepts de
structure et fonctions de structure. Ce billet ne visait qu'à vous éclairer sur
ce que peut vous apporter Go coté parallélisation.&lt;/p&gt;
&lt;p&gt;Go est désormais utilisable dans appengine, vous pouvez aussi créer votre
propre miniserveur HTTP très facilement avec le package (inclu) &amp;quot;net/http&amp;quot; et
que des portage de Gtk, WX etc... ont vu le jour et fonctionnenent.&lt;/p&gt;
&lt;p&gt;En ce qui concerne les deux compilateurs, le compilateur (et runtime) Go de
Google compile de manière statique mais donne de superbe résultats en terme de
performances. Vous pouvez utiliser gcc-go (dans les dépots Fedora du moins) qui
vous permettra de compiler dynamiquement vos programmes (le compilateur go
faisant de la compilation statique...)&lt;/p&gt;
&lt;p&gt;Un dernier point, Go vous permet aussi de récupérer très aisément des
librairies C et d’utiliser les fonctions impémentées dans ce langage.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Google App Engine et le souci os_compat</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Google-App-Engine-et-le-souci-os_compat</link>
    <guid isPermaLink="false">urn:md5:a97af1f0b3bef4299b835f60ed50a144</guid>
    <pubDate>Mon, 21 May 2012 18:46:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>appengine</category><category>google</category><category>python</category>    
    <description>&lt;p&gt;Google AppEngine propose est un service de développement web assez puissant
et très intéressant qui permet de faire une application &amp;quot;scalable&amp;quot; en Java,
Python et maintenant en Go. Le souci, si comme moi vous avez &amp;quot;MyPaint&amp;quot; et par
conséquent le paquet protobuf-python... vous allez vous taper une erreur
monstrueuse au démarrage de votre application... on va trouver une méthode
simple pour contourner ce souci&lt;/p&gt;    &lt;p&gt;Car effectivement, au premier lancement de votre application:&lt;/p&gt;
&lt;pre&gt;
 ./google_appengine/dev_appserver.py helloworld/
Traceback (most recent call last):
  File &amp;quot;./google_appengine/dev_appserver.py&amp;quot;, line 125, in &amp;lt;module&amp;gt;
    run_file(__file__, globals())
  File &amp;quot;./google_appengine/dev_appserver.py&amp;quot;, line 121, in run_file
    execfile(script_path, globals_)
  File &amp;quot;/home/patachou/Dev/google_appengine/google/appengine/tools/dev_appserver_main.py&amp;quot;, line 138, in &amp;lt;module&amp;gt;
    from google.appengine.tools import os_compat
ImportError: No module named appengine.tools
&lt;/pre&gt;
&lt;p&gt;Pourquoi ? tout simplement parce que le paquet protobuf contient un
module nommé... google ! du coup, python ne va pas voir ailleurs que dans
le site-package protobuf et plante misérablement, lachant son dernier souffle
en vous insultant... et vous, vous n'avez que pour seule solution de vous
rabattre tant bien que mal sur des discussions sur le net où tout le monde vous
demande de supprimer protobuf.&lt;/p&gt;
&lt;p&gt;Sauf que moi, j'utilise MyPaint et j'ai pas envie de me remettre le paquet à
chaque fois que je veux dessiner. Et puis de toutes manières j'aime pas les
méthodes où il faut supprimer un paquet tout simplement parce qu'une
implémentation sent la fosse septique...&lt;/p&gt;
&lt;p&gt;La solution ? oui oui deux secondes...&lt;/p&gt;
&lt;p&gt;Elle est simple ma solution... utiliser un environnement virtuel !
Attention, pas un LXC ou une VM qui va vous plomber tout votre espace disque...
non ! juste un outil python qui rend tellement service, et dont je me sers
tout le temps pour tester mes &amp;quot;setup.py&amp;quot; et autres joyeusetés qui peut
simplement foutre le boxon dans mes répertoires.&lt;/p&gt;
&lt;p&gt;Bref, on va faire ça propre !&lt;/p&gt;
&lt;p&gt;On crée un environnement virtuel&lt;/p&gt;
&lt;pre&gt;
mkdir -p ~/Dev/appengine
virtualenv ~/Dev/appengine
&lt;/pre&gt;
&lt;p&gt;Voilà, c'est fait... on copie maintenant le répertoire &amp;quot;google&amp;quot; fournis avec
le SDK Python de Google App Engine:&lt;/p&gt;
&lt;pre&gt;
cp -ra ~chemin/vers/google_appengine/google ~/Dev/appengine/lib/python2.7/site-packages/
&lt;/pre&gt;
&lt;p&gt;Et pour lancer l'engin google, on active l'environnement:&lt;/p&gt;
&lt;pre&gt;
source ~/Dev/appengine/bin/activate
&lt;/pre&gt;
&lt;p&gt;Du coup, on voit notre prompt terminal commencer par: (appengine), chez moi
ça donne:&lt;/p&gt;
&lt;pre&gt;
(appengine)[patachou@patrice-laptop ~]$
&lt;/pre&gt;
&lt;p&gt;Vous pouvez maintenant lancer votre programme (prenez le tutorial &lt;a href=&quot;https://developers.google.com/appengine/docs/python/python27/using27&quot;&gt;python
2.7&lt;/a&gt; de google) de cette manières:&lt;/p&gt;
&lt;pre&gt;
~chemin/vers/google_appengine/dev_appserver.py helloworld/
&lt;/pre&gt;
&lt;p&gt;Pour sortir de l'environnement virutel:&lt;/p&gt;
&lt;pre&gt;
deactivate
&lt;/pre&gt;
&lt;p&gt;Voilà, c'est simple, assez propre, et en plus ça marche...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Typescript to gif - convertir une capture terminal vers un gif animé</title>
    <link>http://blog.fedora-fr.org/metal3d/post/typescript-to-gif</link>
    <guid isPermaLink="false">urn:md5:afcc9864990b272fec7d17560d7ecac8</guid>
    <pubDate>Sun, 20 May 2012 16:01:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Multimedia</category>
        <category>bash</category><category>imagemagick</category><category>terminal</category>    
    <description>&lt;p&gt;Comment utiliser la commande &amp;quot;script&amp;quot; et un peu de bash + imagemagick pour
en faire une animation en GIF (ou pourquoi pas une vidéo par la suite)&lt;/p&gt;    &lt;p&gt;Cette semaine, un administrateur système m'a montré une commande que je ne
connaissais pas du tout... &amp;quot;script&amp;quot;. Ce petit utilitaire permet d'enregistrer
le flux terminal vers un fichier afin d'être relu. En grattant dans le &amp;quot;man&amp;quot;
j'ai découvert deux options intéressantes, l'une d'elle permet de garder les
&amp;quot;temps&amp;quot; de commande + le nombre de caractères à lire... On peut alors utiliser
&amp;quot;scriptreplay&amp;quot; pour relire la session ou bien, comme moi, jouer avec et créer
une animation&lt;/p&gt;
&lt;p&gt;Prenons le temps de comprendre. Si je tape la commande:&lt;/p&gt;
&lt;pre&gt;
script --timing=/tmp/timing /tmp/script
&lt;/pre&gt;
&lt;p&gt;alors commence une session enregistrée dans le fichier /tmp/script.&lt;/p&gt;
&lt;p&gt;Tapons alors des commandes, par exemple&lt;/p&gt;
&lt;pre&gt;
echo &amp;quot;hello world&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Puis pressez CTRL+D. La session &amp;quot;script&amp;quot; s'arrête. Vous pouvez rejouer la
session (qui ne va pas rejouer les commandes, mais les afficher avec les
résultats de l'époque...) en utilisant &amp;quot;cat&amp;quot;&lt;/p&gt;
&lt;pre&gt;
cat /tmp/script
&lt;/pre&gt;
&lt;p&gt;Or... on a besoin de voir &amp;quot;à la replay&amp;quot; la commande. Soit:&lt;/p&gt;
&lt;pre&gt;
scriptreplay -t /tmp/timing /tmp/script
&lt;/pre&gt;
&lt;p&gt;Et là, c'est déjà plus joli. Mais voilà, pour partager une capture de ce
genre en vidéo (ou en gif animé) ce format ne nous convient pas encore. On va
donc réfléchir recréer une belle vidéo de tout ce beau monde.&lt;/p&gt;
&lt;p&gt;Première option, on fait un screencast (avec ffmpeg) mais bon... la souris
peut apparaître... et puis pour en faire un gif c'est pas encore ça.&lt;/p&gt;
&lt;p&gt;Seconde option, celle qu'on va mettre en place, est de faire ceci: - relire
le fichier /tmp/timing - prendre séquence par séquence le texte depuis le
typescript (fichier généré par la commande script) - afficher ça dans le
terminal et faire une capture du terminal avec la commande &amp;quot;import&amp;quot; - relire
une fois de plus le timing et cette fois ci: lire les temps d'attente -
utiliser &amp;quot;convert&amp;quot; avec l'option -delay pour mettre frame à frame les images
dans le gif animé.&lt;/p&gt;
&lt;p&gt;Voilà... bon je vais pas passer par 4 chemins, le but n'est pas de vous
apprendre à faire du bash mais au moins vous parler des &amp;quot;soucis&amp;quot; que j'ai dut
régler: - lire un fichier d'un certain endroit à un autre: on utilise &amp;quot;dd&amp;quot; -
créer des images numérotées avec 5 chiffres pour être à l'aise: printf&lt;/p&gt;
&lt;p&gt;Le reste coule presque de source... Voilà le script:&lt;/p&gt;
&lt;pre class=&quot;bash bash&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style=&quot;color: #007800;&quot;&gt;TIMING&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$1&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;SCRIPT&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$2&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;W&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$WINDOWID&lt;/span&gt;
 
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-rf&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;script-replay-gifs&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mkdir&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;script-replay-gifs&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;
 
&lt;span style=&quot;color: #007800;&quot;&gt;t&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;mktemp&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;cp&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$SCRIPT&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$t&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#remove first line&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sed&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-i&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'1d'&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$t&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#clear screen&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;clear&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#read timing file one by one&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;curr&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;i&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;read&lt;/span&gt; line
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#capture time and chars to read&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;cols&lt;/span&gt;=&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$line&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;chars&lt;/span&gt;=&lt;span style=&quot;color: #800000;&quot;&gt;${cols[1]}&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#read from current char the number of chars to read&lt;/span&gt;
    &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;dd&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;if&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$t&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;bs&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;skip&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$curr&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;count&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$chars&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;/&lt;/span&gt;dev&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;null
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#convert to gif frame with a nice frame-number&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;n&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;printf&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;%010d&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$i&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    import &lt;span style=&quot;color: #660033;&quot;&gt;-window&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$WINDOWID&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;script-replay-gifs&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$n&lt;/span&gt;.gif
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#and move to next position&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;curr&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;curr+chars&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;i&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;i+&lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;done&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$TIMING&lt;/span&gt;
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$t&lt;/span&gt;
 
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#now, set gif with delay per frame&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;i&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;read&lt;/span&gt; line
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;cols&lt;/span&gt;=&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #007800;&quot;&gt;$line&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;timing&lt;/span&gt;=&lt;span style=&quot;color: #800000;&quot;&gt;${cols[0]}&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#get next image&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;file&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;ls&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-1&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;script-replay-gifs&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;head&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-n&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$i&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;tail&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-n&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;timing&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$timing&lt;/span&gt;*100&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;bc&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-l&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;awk&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'{print int($0)}'&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #007800;&quot;&gt;command&lt;/span&gt;=&lt;span style=&quot;color: #007800;&quot;&gt;$command&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot; -delay &lt;span style=&quot;color: #007800;&quot;&gt;$timing&lt;/span&gt; /tmp/script-replay-gifs/&lt;span style=&quot;color: #007800;&quot;&gt;$file&lt;/span&gt;&amp;quot;&lt;/span&gt;
 
    &lt;span style=&quot;color: #007800;&quot;&gt;i&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;i+&lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;done&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$TIMING&lt;/span&gt;
 
convert &lt;span style=&quot;color: #007800;&quot;&gt;$command&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;anim-notoptim.gif
convert &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;anim-notoptim.gif &lt;span style=&quot;color: #660033;&quot;&gt;-coalesce&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-layers&lt;/span&gt; Optimize &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;anim.gif
 
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;anim-notoptim.gif
&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-rf&lt;/span&gt;  &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;tmp&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;script-replay-gifs&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ce script est très très lent à cause de &amp;quot;import&amp;quot; qui prend près d'une
seconde par capture... de ce fait pour le moment c'est pas un modèle du
genre... et en plus, vous ne pouvez pas quitter le bureau dans lequel vous être
pour créer l'animation sous peine de messages d'erreur. Notez que ce n'est un
qu'un petit test&lt;/p&gt;
&lt;p&gt;Cela donne: &lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/anim2.gif&quot; alt=&quot;Animation terminal&quot; title=&quot;Animation terminal, mai 2012&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Pour le coup, j'ai quand même posé un petit coup de &amp;quot;gimp&amp;quot; pour optimiser le
gif animé. Je vous laisse maître de me faire des remarques et pourquoi pas (si
vous le demandez) je créerai un dépôt git quelque part pour qu'on le fasse
évoluer.&lt;/p&gt;
&lt;p&gt;Update: j'ai ajouté une opération d'optimisation de taille à la fin du
script&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Point de montage Google Drive</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Point-de-montage-Google-Drive</link>
    <guid isPermaLink="false">urn:md5:f3c2edfa9807a13ccb9b3c4ab2a5bb85</guid>
    <pubDate>Fri, 27 Apr 2012 18:21:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>google</category><category>python</category><category>terminal</category>    
    <description>    &lt;p&gt;Google vient de sortir Google Drive, comprenez un espace de stockage dans le
&amp;quot;cloud&amp;quot; (à distance, sur les serveur Google, avec mix des documents de
google-docs). L'application de disque dur distant est accessible de plusieurs
manières: Android, PC ou directement sur le net. Or sous Windows et Mac on a la
possibilité d'utiliser un programme qui monte un disque sur l'ordinateur. Qui
dit &amp;quot;monter&amp;quot; rappelle le point de montage Linux (unix...). Google a annoncé une
version de Google Drive Linux pour bientôt mais en attendant vous pouvez encore
utiliser le projet http://code.google.com/p/google-docs-fs/&lt;/p&gt;
&lt;p&gt;Ce projet était à la base un système de montage simple utilisant fuse pour
afficher les google-docs sur un disque monté localement. Mais comme Drive
utilise le même point d'accès, ce (vieux) projet fonctionne très bien. Sous
Fedora, il suffit de faire:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;update&lt;/strong&gt; merci à &amp;quot;hk&amp;quot;, j'avais oublié le paquet
python-gdata&lt;/p&gt;
&lt;pre&gt;

su -c &amp;quot;yum install fuse-python python-gdata -y&amp;quot;

cd /tmp
hg clone https://code.google.com/p/google-docs-fs/
cd google-docs-fs
su -c &amp;quot;python setup.py install&amp;quot;

&lt;/pre&gt;
&lt;p&gt;Reste alors à monter le dossier:&lt;/p&gt;
&lt;pre&gt;
mkdir ~/GoogleDrive
gmount ~/GoogleDrive votre_user@gmail.com
&lt;/pre&gt;
&lt;p&gt;On vous demande alors le mot de passe google, et hop le point de montage est
créé:&lt;/p&gt;
&lt;pre&gt;
mount
gmount.py on /home/patachou/GoogleDrive type fuse.gmount.py (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
&lt;/pre&gt;
&lt;p&gt;Vous pouvez dés lors visiter le dossier, créer des répertoires, copier des
données, ouvrir vos documents... et y accéder depuis votre mobile, le net...
Reste à voir ce que l'application Google offrira de mieux que ce petit projet
python, parce que pour le moment cela me convient tellement bien...&lt;/p&gt;
&lt;p&gt;PS: vous pouvez ajouter ce point de montage dans /etc/fstab pour l'avoir
actif tout le temps, mais comme je ne sais pas comment placer le mot de passe.
Je vous tiens au courant si je trouve &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Intégration continue - PHP, Selenium et Xvfb - Partie 1</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Int%C3%A9gration-continue-Partie-1</link>
    <guid isPermaLink="false">urn:md5:80b7a4bfac2c130b9e15ec58748bd107</guid>
    <pubDate>Sat, 31 Mar 2012 11:23:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>intégration continue</category><category>php</category><category>selenium</category>    
    <description>    &lt;p&gt;Depuis quelques mois je me suis penché sur les outils d'intégration continue
pour les projets PHP. Il en existe un bon paquet, mais celui qui pour le moment
répond le mieux à mes attentes reste phpUnderControl. L'installation reste tout
de même assez complexe et il me parait bon de vous montrer comment mettre en
oeuvre ce genre d'outil. Le but étant de vous aider pas à pas à installer les
outils qui permettront d'utiliser un service d'intégration continue. Nous
allons passer en revue les outils à installer depuis PEAR, puis Selenium et
enfin comment intégrer tout ça dans phpUnderControl.&lt;/p&gt;
&lt;p&gt;Certes, je ne vais pas vous donner &amp;quot;la solution dans les règles de l'art&amp;quot;
car chaque projet est différent, chaque attente est spécifique... Mais vous
pourrez adapter au besoin les explications.&lt;/p&gt;
&lt;p&gt;Nous allons donc procéder à ces opérations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;installer les outils pear: phpcs, phpmd, phpcpd, phpunit&lt;/li&gt;
&lt;li&gt;installer selenium IDE avec le plugin php (ces outils ne sont pas
obligatoires mais rendent la tâche tellement plus simple...)&lt;/li&gt;
&lt;li&gt;préparer un environnement X virtuel pour lancer les tests selenium&lt;/li&gt;
&lt;li&gt;installer phpundercontrol&lt;/li&gt;
&lt;li&gt;configurer la bête...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les deux derniers points seront dans la partie 2, pour le moment il faut
s'assurer d'avoir tous les composants nécessaires à la bonne conduite du
projet.&lt;/p&gt;
&lt;p&gt;En ce qui concerne Selenium et phpUnderControl, ce sont des outils
développés en Java. On nous recommande d'utiliser le jre de oracle (comme ce
n'est plus Sun...) mais pour ma part j'utilise openjdk sans aucun souci...
alors pourquoi passer au propriétaire quand le libre fonctionne très
bien ?&lt;/p&gt;
&lt;p&gt;Donc, sur votre Fedora ou Centos, préparons un environnement propre... Je
vous conseille d'utiliser un conteneur LXC pour bosser, mais si vous voulez
utiliser votre système hôte je ne vais pas vous en empêcher.&lt;/p&gt;
&lt;p&gt;On commence par installer les outils important:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;php-cli, php-pear&lt;/li&gt;
&lt;li&gt;openjdk&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;on ouvre un terminal, on se met en root et on installe tout ça&lt;/p&gt;
&lt;pre&gt;
su -
yum install php-cli php-pear java-1.7.0-openjdk
&lt;/pre&gt;
&lt;p&gt;Pour la suite, je sais que certains d'entres vous vont me taper sur les
doigts, clamant haut et fort que les dépots Fedora ont les paquets PEAR
demandés (ou pas...) mais je vais être très clair: les paquets sur les serveurs
PEAR sont à jour, et certaines dépendances risquent de ne pas marcher si vous
utiliser les RPM. C'est le cas aussi sur Debian (j'en ai fait les frais cette
semaine). Donc ayez confiance et faites ce que je dis &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;On commence par faire deux ou trois manipulations sur PEAR pour être à
l'aise (toujours en tant que root):&lt;/p&gt;
&lt;pre&gt;
pear set-config auto_discover 1
pear upgrade pear
pear install --alldeps pear.phpunit.de/PHPUnit
pear install --alldeps phpunit/PHPUnit_Selenium
pear install --alldeps pear.phpunit.de/phpcpd
pear install --alldeps phpmd/PHP_PMD
pear install --alldeps PHP_CodeSniffer
pear install --alldeps channel://pear.phpdoc.org/PhpDocumentor-2.0.0a1
&lt;/pre&gt;
&lt;p&gt;Si jamais il vous manque des paquets php, installez les, faites un &amp;quot;prear
uninstall&amp;quot; du paquet qui a donné une erreur, et relancez l'installation du
paquet.&lt;/p&gt;
&lt;p&gt;Vous avez donc à présent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;phpunit pour faire des tests unitaires de vos développement php&lt;/li&gt;
&lt;li&gt;phpunit-selenium qui est une classe permettant de piloter le serveur
selenium qui lancera un navigateur pour tester des aspect fonctionnels&lt;/li&gt;
&lt;li&gt;phpcpd (Copy Paste Detector) qui vérifie les &amp;quot;copier coller&amp;quot; de code&lt;/li&gt;
&lt;li&gt;phpmd (Mess Detector) qui va vérifier des aspects complexe de code
(variables non utilisé, code complexe, nom de variables ou fonctions...)&lt;/li&gt;
&lt;li&gt;phpcs qui va vérifier si votre code est bien formaté selon des standards
choisis&lt;/li&gt;
&lt;li&gt;phpdocumentor qui permet de créer la documentation de vos projets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cela étant fait, nous allons passer à la suite... Selenium !&lt;/p&gt;
&lt;p&gt;Selenium est un ensemble d'outils qui permettent de piloter un navigateur au
travers un serveur. Vous allez pouvoir vérifier si une page apparait
correctement, si les liens sont bien présents sur une certaine page, et bien
plus encore. Le principe est très simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on enregistre une séquence de manipulations et de tests&lt;/li&gt;
&lt;li&gt;on l'exporte pour phpunit&lt;/li&gt;
&lt;li&gt;on lance le test&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mais pour que cela fonctionne, il faut jouer un peu dans le terminal... rien
de bien méchant mais important.&lt;/p&gt;
&lt;p&gt;Dans votre terminal, en root, téléchargez le serveur:&lt;/p&gt;
&lt;pre&gt;
mkdir /opt/selenium
cd /opt/selenium
wget http://selenium.googlecode.com/files/selenium-server-standalone-2.20.0.jar
&lt;/pre&gt;
&lt;p&gt;Ce serveur, une fois lancé, pilotera un firefox tout seul. Sauf que voilà...
si vous travaillez sur une machine de bureau alors aucun souci ne se profile...
mais quand on travaille sur un serveur distant... sans écran... ça va aller
mal !&lt;/p&gt;
&lt;p&gt;La solution la plus simple, selon moi, est d'installer un firefox
&amp;quot;standalone&amp;quot; sur /opt/selenium et de lancer tout ça dans un Xvfb (X virtuel).
On va donc faire cela... toujours dans votre répertoire /opt/selenium:&lt;/p&gt;
&lt;pre&gt;
wget &amp;quot;http://download.mozilla.org/?product=firefox-11.0&amp;amp;os=linux&amp;amp;lang=fr&amp;quot;
tar jxf firefox*.bz2
&lt;/pre&gt;
&lt;p&gt;Si tout est ok, vous avez un répertoire &amp;quot;firefox&amp;quot; dans /opt/selenium&lt;/p&gt;
&lt;p&gt;On va tenter de lancer firefox dans un X virtuel pour être certain que tout
se passe bien:&lt;/p&gt;
&lt;pre&gt;
Xvfb :99 &amp;amp;
DISPLAY=:99 /opt/selenium/firefox/firefox &amp;amp;
DISPLAY=:99 import -window root /tmp/snapshot.png
&lt;/pre&gt;
&lt;p&gt;Maintenant, ouvrez /tmp/snapshot.png et vérifiez que vous voyez bel et bien
un firefox ouvert. Si oui: nickel ! si non... heu vérifiez si il ne manque
pas une librairie pour firefox (genre gdlib-dbus...)&lt;/p&gt;
&lt;p&gt;Bref, si Xvfb et firefox ont marché alors on coupe:&lt;/p&gt;
&lt;pre&gt;
killall Xvfb
&lt;/pre&gt;
&lt;p&gt;Notez qu'on aurait put utiliser &amp;quot;xvb-run /opt/selenium/firefox/firefox&amp;quot; et
utiliser le port retourné pour faire la capture, mais les lignes su-citées me
paraissent plus explicites pour comprendre comment ça fonctionne.&lt;/p&gt;
&lt;p&gt;Bref, utilisons maintenant le serveur selenium pour lancer un test.&lt;/p&gt;
&lt;pre&gt;
Xvfb :99 &amp;amp;
sleep 2
PATH=/opt/selenium/firefox:$PATH DISPLAY=:99 java -jar selenium-server-standalone-2.20.0.jar &amp;amp;
&lt;/pre&gt;
&lt;p&gt;Attendez un peu...il faut voir une ligne indiquant que le serveur tourne, ce
genre de ligne:&lt;/p&gt;
&lt;pre&gt;
INFO org.openqa.jetty.http.SocketListener - Started SocketListener on 0.0.0.0:4444
INFO org.openqa.jetty.util.Container - Started org.openqa.jetty.jetty.Server@1ff4689e
&lt;/pre&gt;
&lt;p&gt;Cela peut prendre entre 5 et 30 secondes, soyez patient... A partir de là,
le serveur écoute le port 4444, on va donc jouer un peu !&lt;/p&gt;
&lt;p&gt;Créer un fichier test.php:&lt;/p&gt;
&lt;pre class=&quot;php php&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;class&lt;/span&gt; Example &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;extends&lt;/span&gt; PHPUnit_Extensions_SeleniumTestCase
&lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
  &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;protected&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;function&lt;/span&gt; setUp&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;setBrowser&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;*chrome&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;setBrowserUrl&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;http://www.google.fr/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
  &lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
 
  &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;function&lt;/span&gt; testMyTestCase&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;
  &lt;span style=&quot;color: #009900;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;waitForPageToLoad&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;30000&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//on vérifie que &amp;quot;Google&amp;quot; est sur la page...&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;verifyTextPresent&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;Google&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
 
    &lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//ce teste doit donner une erreur&lt;/span&gt;
    &lt;span style=&quot;color: #000088;&quot;&gt;$this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #004000;&quot;&gt;verifyTextPresent&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&amp;quot;foo bar baz&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
 
  &lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ce teste ne fait rien de compliqué... il ouvre Google et vérifie si le texte
&amp;quot;Google&amp;quot; est sur la page...&lt;/p&gt;
&lt;p&gt;Vous pouvez lancer le test:&lt;/p&gt;
&lt;pre&gt;
phpunit test.php
&lt;/pre&gt;
&lt;p&gt;Le résultat doit être:&lt;/p&gt;
&lt;pre&gt;
PHPUnit 3.6.10 by Sebastian Bergmann.

F

Time: 5 seconds, Memory: 5.75Mb

There was 1 failure:

1) Example::testMyTestCase
foo bar baz
Failed asserting that false is true.


FAILURES!
Tests: 1, Assertions: 2, Failures: 1.
&lt;/pre&gt;
&lt;p&gt;Cela indique donc que le serveur selenium a bien lancé firefox, la page
google et vérifier qu'un texte &amp;quot;Google&amp;quot; apparait. En ce qui concerne &amp;quot;foo bar
baz&amp;quot; cela donne une erreur. Donc:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 test&lt;/li&gt;
&lt;li&gt;2 assertions : texte &amp;quot;Google&amp;quot; et texte &amp;quot;foo bar baz&amp;quot;&lt;/li&gt;
&lt;li&gt;1 erreur, et une seule erreur !!! si vous en avez 2 alors c'est que cela
n'a pas marché !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà, on peut couper selenium et Xvfb:&lt;/p&gt;
&lt;pre&gt;
killall Xvfb
kill $(ps ax | grep selenium | grep -v grep | awk '{print $1}')
&lt;/pre&gt;
&lt;p&gt;Maintenant, on se crée un service pour lancer Xvfb et Selenium.&lt;/p&gt;
&lt;p&gt;Avant tout, pour des raison pratiques, je vous conseille de ne *plus du
tout* lancer Xvfb et Selenium en root, mais avec un utilisateur précis. Comme
nous allons utiliser phpUnderControl qui est un plugin de cruisecontrol, et que
ce dernier lancera son service avec un utilisateur recommandé, nous allons le
créer de suite et l'utiliser pour lancer Xvfb et Selenium.&lt;/p&gt;
&lt;pre&gt;
useradd -m -s /bin/bash cruisecontrol
&lt;/pre&gt;
&lt;p&gt;Notez ici que je demande la création du répertoire personnel (via l'option
-m) car firefox aura besoin de créer un répertoire de profil, de ce fait,
/home/cruisecontrol va être créé.&lt;/p&gt;
&lt;p&gt;Voilà, maintenant créons le service qui lance Xvfb et Selenium via cet
utilisateur. Créer le fichier /etc/init.d/xselenium et déposez ce code:&lt;/p&gt;
&lt;pre class=&quot;bash bash&quot; style=&quot;font-family:inherit&quot;&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style=&quot;color: #007800;&quot;&gt;XLOCK&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/var/lock/Xvfb.pid&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #007800;&quot;&gt;SLOCK&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/var/lock/selenium.pid&amp;quot;&lt;/span&gt;
 
 
startXVFB&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;{&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$XLOCK&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Already Running&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;local&lt;/span&gt; PID
        &lt;span style=&quot;color: #007800;&quot;&gt;PID&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;su&lt;/span&gt; cruisecontrol &lt;span style=&quot;color: #660033;&quot;&gt;-c&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'Xvfb :15 &amp;gt;/dev/null  2&amp;gt;&amp;amp;1 &amp;amp; echo $!'&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Xvfb pid &lt;span style=&quot;color: #007800;&quot;&gt;$PID&lt;/span&gt;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$PID&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$XLOCK&lt;/span&gt;
 
&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;}&lt;/span&gt;
 
startSelenium&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;{&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$SLOCK&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;]&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Selenium Already Running&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;
 
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;local&lt;/span&gt; PID
        &lt;span style=&quot;color: #007800;&quot;&gt;PID&lt;/span&gt;=$&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;su&lt;/span&gt; cruisecontrol &lt;span style=&quot;color: #660033;&quot;&gt;-c&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;'PATH=/opt/selenium/firefox:$PATH DISPLAY=:15 java -jar /opt/selenium/selenium-server-standalone-2.20.0.jar &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp; echo $!'&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Selenium pid &lt;span style=&quot;color: #007800;&quot;&gt;$PID&lt;/span&gt;&amp;quot;&lt;/span&gt;
        &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$PID&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$SLOCK&lt;/span&gt;
&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;}&lt;/span&gt;
 
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$1&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;in&lt;/span&gt;
        start&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Starting XVFB&amp;quot;&lt;/span&gt;
                startXVFB
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sleep&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;
                &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Starting Selenium server&amp;quot;&lt;/span&gt;
                startSelenium
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sleep&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;
                &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;;;&lt;/span&gt;
 
        stop&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;kill&lt;/span&gt; $&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;cat&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$SLOCK&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sleep&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;kill&lt;/span&gt; $&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;cat&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$XLOCK&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sleep&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;
                &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$SLOCK&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;$XLOCK&lt;/span&gt;
                &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;;;&lt;/span&gt;
       &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;)&lt;/span&gt;
               &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;echo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;$0 start|stop&amp;quot;&lt;/span&gt;
               &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;;;&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;esac&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Rendez le executable:&lt;/p&gt;
&lt;pre&gt;
chmod +x /etc/init.d/xselenium
&lt;/pre&gt;
&lt;p&gt;Et lancez le service:&lt;/p&gt;
&lt;pre&gt;
/etc/init.d.xselenium start
&lt;/pre&gt;
&lt;p&gt;Vous devez donc avoir désormais un Xvfb et un selenium actif. Attendez un
peu que le port 4444 soit ouvert pour commencer à lancer les tests, pour
vérifier le port:&lt;/p&gt;
&lt;pre&gt;
netstat -taupen | grep 4444
&lt;/pre&gt;
&lt;p&gt;Si aucune ligne n'apparait, c'est que le service ne tourne pas.&lt;/p&gt;
&lt;p&gt;Voilà pour la partie pear, selenium-server et Xvfb. Dans la partie 2 nous
utiliserons Selenium IDE pour créer des tests, mais surtout nous installerons
phpUnderControl afin de piloter notre intégration continue.&lt;/p&gt;
&lt;p&gt;En espérant avoir donner quelques clefs...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>lxc 0.7.5 recompilé</title>
    <link>http://blog.fedora-fr.org/metal3d/post/lxc-0.7.5-recompil%C3%A92</link>
    <guid isPermaLink="false">urn:md5:d20fabc9b248d7ab7dd65492f683eb61</guid>
    <pubDate>Sun, 04 Sep 2011 11:53:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Admin</category>
        <category>lxc</category><category>virtualisation</category>    
    <description>&lt;p&gt;J'ai eu du mal à faire fonctionner lxc sur ma fedora (pour une fois qu'un
truc marche mal, je me suis penché sur le cas). Avec l'aide de number80 (un des
habitués du canal #fedora-fr sur IRC freenode) j'ai pu patcher et recompiler
des rpm pour la version 0.7.5 de lxc.&lt;/p&gt;    &lt;p&gt;Le souci qui se posait, outre les désastreuses erreurs liées à cgroup, était
l'absence de templates. En fait, je ne sais pas pourquoi le mainteneur a
supprimé les templates d'installation (apparement ils ne devaient pas être bons
à l'époque). Toujous est-il que le template fedora fonctionne bien.&lt;/p&gt;
&lt;p&gt;J'ai patché le template &amp;quot;debian&amp;quot; qui demandait à utiliser &lt;em&gt;dpkg&lt;/em&gt; pour
avoir l'architechture procésseur de la machine. Pour remplacer cela, j'effectue
un test autre (via &lt;em&gt;uname -i&lt;/em&gt;) et je permet une option &lt;em&gt;-a&lt;/em&gt; ou
&lt;em&gt;--arch&lt;/em&gt; qui peut prendre en charge &lt;em&gt;amd64&lt;/em&gt; ou &lt;em&gt;i386&lt;/em&gt;.
L'architechture est par défaut celle de votre cpu.&lt;/p&gt;
&lt;p&gt;Autre partie que j'ai patchée, le template debian ne créait pas d'interface
réseau... chose réparée&lt;/p&gt;
&lt;p&gt;Bref, pour installer mes paquets, comme pour le moment je n'ai pas de dépot,
il vous suffit de prendre l'archive de 1.1Mo ici: &lt;a href=&quot;http://www.metal3d.org/rpms/lxc-0.7.5-rpm.tar.gz&quot; title=&quot;http://www.metal3d.org/rpms/lxc-0.7.5-rpm.tar.gz&quot;&gt;http://www.metal3d.org/rpms/lxc-0.7...&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pour installer tout ça:&lt;/p&gt;
&lt;pre&gt;
su 
tar zxvf lxc-0.7.5-rpm.tar.gz
#pour les 32bits:
yum install --nogpgcheck lxc/{lxc-0.7.5-1.fc15.i686.rpm,lxc-templates-0.7.5-1.fc15.i686.rpm,lxc-libs-0.7.5-1.fc15.i686.rpm}
#pour les 64bits:
yum install --nogpgcheck lxc/{lxc-0.7.5-1.fc15.x86_64.rpm,lxc-templates-0.7.5-1.fc15.x86_64.rpm,lxc-libs-0.7.5-1.fc15.x86_64.rpm}
&lt;/pre&gt;
&lt;p&gt;Je vous remercie d'avance si vous avez des retours particuliers, notez que
je n'ai testé que les templates fedora et debian pour le moment.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Configurer Mutt pour gmail</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Configurer-Mutt-pour-gmail</link>
    <guid isPermaLink="false">urn:md5:dd4c62f93d76a3f8cb64cb0918a653aa</guid>
    <pubDate>Fri, 26 Aug 2011 19:37:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>bash</category><category>bureautique</category><category>mail</category><category>python</category>    
    <description>&lt;p&gt;Il est évident que nous ne sommes pas tous accrocs aux outils en mode texte
(dans un terminal) mais personnellement j'y trouve mon compte: vitesse,
exécution claire, lisibilité... et modularité. Je suis un Google Fan (houuu je
vais m'en prendre plein la poire moi) et j'ai beaucoup de mes données sur
Google: mail, documents, agenda... Voici donc comment pouvoir envoyer des mails
et lire ces derniers convenablement avec Mutt, y compris l'autocompletion des
contacts Gmail&lt;/p&gt;    &lt;p&gt;La configuration ne sera pas compliqué. Il faudra juste se farcir 3 fichiers
de configurations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un pour mutt lui même, configuration du compte&lt;/li&gt;
&lt;li&gt;un pour permettre les macros de lecture de mail en HTML&lt;/li&gt;
&lt;li&gt;un fichier netrc pour permettre à goobook de fonctionner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref, passons en premier lieu à l'installation proprement dite des
logiciels:&lt;/p&gt;
&lt;pre&gt;
su -c &amp;quot;yum install mutt python-setuptools links&amp;quot;
su -c &amp;quot;easy_install goobook&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Le première commande installe mutt et les utilitaires pytyon pour installer
un paquet python, puis links, le lecteur html en console. L'autre installe
goobook, un outil qui permet de récupérer un carnet d'adresse google.&lt;/p&gt;
&lt;p&gt;Goobook est un outil python que j'ai testé après en avoir essayé plusieurs,
c'est de loin le plus pratique et le plus abouti que je connaisse. Vous pouvez
voir la page du projet ici: &lt;a href=&quot;http://pypi.python.org/pypi/goobook/&quot; title=&quot;http://pypi.python.org/pypi/goobook/&quot;&gt;http://pypi.python.org/pypi/goobook...&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Maintenant, passons à la configuration de Mutt&lt;/p&gt;
&lt;pre&gt;
#fichier ~/.muttrc

#enregistre les messages envoyés et brouillons dans Gmail
set record=&amp;quot;+[Gmail]/Messages envoyés&amp;quot;
set postponed=&amp;quot;+[Gmail]/Brouillons&amp;quot;

#configuration du serveur
set hostname=gmail.com
my_hdr From: PRENOM NOM &amp;lt;USER@gmail.com&amp;gt;
set use_envelope_from
set envelope_from_address=&amp;quot;USER@gmail.com&amp;quot;

unignore Date Message-ID In-Reply-To

set move=no
set spoolfile=imaps://imap.gmail.com:993/INBOX
set imap_user = &amp;quot;USER@gmail.com&amp;quot;
set imap_pass= &amp;quot;VOTRE MOT DE PASSE&amp;quot;
set imap_authenticators=&amp;quot;login&amp;quot;
set imap_passive=&amp;quot;no&amp;quot;
set folder=&amp;quot;imaps://imap.gmail.com:993&amp;quot;
set imap_check_subscribed=&amp;quot;yes&amp;quot;
set imap_list_subscribed=&amp;quot;yes&amp;quot;

set smtp_url=&amp;quot;smtps://USER:VOTRE MOT DE PASSE@smtp.gmail.com:465&amp;quot;
set ssl_starttls=&amp;quot;yes&amp;quot;

set locale=&amp;quot;fr_FR&amp;quot;
set date_format=&amp;quot;%A %d %b %Y à %H:%M:%S (%Z)&amp;quot;
set attribution=&amp;quot;Le %d, %n à écrit:&amp;quot;
set forward_format=&amp;quot;[Fwd: %s]&amp;quot;
set forward_quote

mailboxes !

set pager_index_lines=&amp;quot;7&amp;quot;
set pager_stop

#gérer un cache
set message_cachedir=&amp;quot;~/.mutt_msg_cache&amp;quot;
set header_cache=&amp;quot;~/.mutt_header_cache&amp;quot;

#force l'utilisation d'un programme exterieur pour les mails en HTML
auto_view text/html

#et ici la config pour les contacts
set query_command=&amp;quot;goobook query '%s'&amp;quot;
bind editor &amp;lt;Tab&amp;gt; complete-query
macro index,pager a &amp;quot;&amp;lt;pipe-message&amp;gt;goobook add&amp;lt;return&amp;gt;&amp;quot; &amp;quot;add the sender address to Google contacts&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Et enfin il faut configurer les commandes pour lire les mails HTML:&lt;/p&gt;
&lt;pre&gt;
#fichier ~/.mailcap
text/html;  links %s; nametemplate=%s.html
text/html;  links -dump %s; nametemplate=%s.html; copiousoutput
&lt;/pre&gt;
&lt;p&gt;Bien. Reste à gérer goobook, on commence par créer un fichier:&lt;/p&gt;
&lt;pre&gt;
#~/.netrc
machine google.com
    login USER@gmail.com
    password Votre Mot de passe
&lt;/pre&gt;
&lt;p&gt;Voilà, testez rapidement que ça passe en tapant:&lt;/p&gt;
&lt;pre&gt;
goobook reload
goobook query un_nom_au_choix
&lt;/pre&gt;
&lt;p&gt;Et bien voilà, lancez maintenant la commande &lt;em&gt;mutt&lt;/em&gt; et appréciez un
peu la lecture de mail dans un terminal.&lt;/p&gt;
&lt;p&gt;Souvenez vous de quelques racourcis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Maj+D pour supprimer un ensemble de mail correspondant à un motif que vous
tapez (par exemple si vous tapez microsoft, tout les mails correspondants
seront marqué comme &amp;quot;à supprimer&amp;quot;)&lt;/li&gt;
&lt;li&gt;d pour supprimer le message sélectionné&lt;/li&gt;
&lt;li&gt;m pour envoyer un message (les contacts sont auto complétés via la touche
tabulation)&lt;/li&gt;
&lt;li&gt;r pour répondre&lt;/li&gt;
&lt;li&gt;c por changer de dossier de mail&lt;/li&gt;
&lt;li&gt;/ pour chercher un mail, selon le nom, le sujet...&lt;/li&gt;
&lt;li&gt;$ pour valider les changements (suppressions)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà, personnellement j'ai adopté mutt et j'en suis très content. Je classe
et nettoie ma boite mail en 4 fois moins de temps qu'avant.&lt;/p&gt;
&lt;p&gt;Notez que nous pourrons ensuite utiliser mcabber pour tchater avec nos
contacts google &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt; on en reparlera&lt;/p&gt;
&lt;p&gt;EDIT: j'ai supprimé la phase de création de goobookrc qui est inutile en
fait...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Xmonad, le bureau productif orienté terminal</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Xmonad%2C-le-bureau-productif-orient%C3%A9-terminal</link>
    <guid isPermaLink="false">urn:md5:fec65bed86a8a4ded0ec4ec013e26547</guid>
    <pubDate>Sun, 21 Aug 2011 13:28:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>outils</category><category>terminal</category><category>X11</category>    
    <description>&lt;p&gt;Vous utilisez certainement Gnome, KDE, ou XFCE (entre autre) pour afficher
vos programmes. Le gestionnaire de fenêtre vous permet de déplacer le programme
sur votre écran via la souris, vous avez des menus, des racourcis qui vous
permettent de gérer tout ça. Je ne critique pas ce principe, il est pratique,
assez standard et bien adapté à la plupart des utilisateurs. Mais nous ne
sommes pas tous identiques. Certains, comme moi, utilisent surtout des
terminaux, et n'aiment pas devoir passer la main du clavier à la souris pour
gérer son espace de travail. Pire encore, nous n'avons en général pas besoin de
la barre de titre, et devoir placer les fenêtres sur le bureau est une chose
qui peut vraiment être un frein à la productivité.&lt;/p&gt;    &lt;p&gt;Outre le coté production, il y a l'ergonomie. L'ergnonomie ne signifie pas
forcément &amp;quot;pouvoir tout déplacer à la souris et avoir plein d'infos sur les
fenêtres&amp;quot;. En fait, tout est relatif. Si un bureau me propose de placer mes
fenêtres et que j'ai juste les informations nécessaires, je trouve cela
ergonomique. Car je n'ai finalement que ce dont j'ai besoin. Mais sans pour
autant me limiter, car dans tous les cas, je peux retrouver les informations
supplémentaires si je connais mon outil.&lt;/p&gt;
&lt;p&gt;Je trouve le terminal ergonomique. Ça peut vous étonner, mais la plupart des
utilisateurs du terminal qui ont passé un peu de temps à apprendre à s'en
servir vous le dira. Le terminal est finalement bien plus simple et plus adapté
à un travail quotidien. Je n'enlève pas l'utilisation du navigateur internet,
ni des outils de création (image, films, 3D, musique...) mais pour le reste,
tout est gérable via des lignes de commande. Je sais ce que vous vous dites...
&amp;quot;il est fou, tout faire en ligne de commande...&amp;quot;, mais pourtant si vous passiez
un peu de temps à apprendre le principe, vous vous rendrez compte de la
puissance et de la simplicité de son utilisation.&lt;/p&gt;
&lt;p&gt;Revenons au gestionnaire de fenêtre. J'ai toujours au moins 4 ou 5 terminaux
ouverts, et passer de l'un à l'autre n'est pas si ergonomique que cela sous
Gnome ou KDE pour ne citer qu'eux. ALT+TAB ou souris, dans tous les cas je ne
vois pas clairement quelle fenêtre je vais avoir tant qu'elle n'est pas
affiché. Le fait est que dans 80% des cas, les fenêtres se recouvrent les unes
sur les autres. Encore une fois, je concois que cela peut être utile et
agréable pour certain, mais pas pour moi.&lt;/p&gt;
&lt;p&gt;Et là, une fois de plus, avoir un système d'exploitation libre vous donne un
choix, adapté, et vraiment viable. Il existe une autre famille de gestionnaire
de fenêtre nommé &amp;quot;tiling desktop&amp;quot; ou &amp;quot;bureau en mosaïque&amp;quot;. Ce genre de
gestionnaire de fenêtre permet de placer les fenêtre selon des &amp;quot;layout&amp;quot; (mise
en page) automatisés et modifiables. Pour en citer quelques uns: awsome, wmii,
ion3, Xmonad...&lt;/p&gt;
&lt;p&gt;Alors pourquoi mon choix se porte sur XMonad ? Parce que ce dernier est
très poussé en terme de configuration et n'a pas de décoration de fenêtre.
C'est selon moi la meilleure gestion de bureau que je connaisse dans le domaine
des tiling desktop.&lt;/p&gt;
&lt;p&gt;Pour vous expliquer le fonctionnement, et surtout pour configurer votre
bureau, je vais vous donner quelques clefs.&lt;/p&gt;
&lt;p&gt;Tout d'abord, sous fedora, on va installer les outils nécessaires pour:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;utiliser xmonad&lt;/li&gt;
&lt;li&gt;avoir quelques outils pratiques&lt;/li&gt;
&lt;li&gt;avoir des terminaux bien plus sympas&lt;/li&gt;
&lt;li&gt;se passer de la plupart des outils &amp;quot;graphiques&amp;quot; forcés sous d'autres
gestionnaires (navigation de fichier par exemple)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On commence:&lt;/p&gt;
&lt;pre&gt;
su -c &amp;quot;yum install xmonad xmobar dmenu mc xscreensaver feh rxvt-unicode&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Bien, si vous quitter votre session, vous aurez donc le choix d'utiliser
xmonad dans le gdm ou kdm (la fenêtre de connexion). Si vous choisissez Xmonad
vous allez avoir un terminal qui va s'ouvrir avec le manuel de Xmonad... et
rien d'autre.&lt;/p&gt;
&lt;p&gt;C'est bien Xmonad... épuré au maximum. Vous avez compris... il va falloir
configurer un peu le bureau pour avoir un truc plus sympa. En premier lieu, ne
paniquez pas et pressez ALT+Shift+c pour fermet le manuel puis ouvrez un autre
terminal avec ALT+shift+Enter.&lt;/p&gt;
&lt;p&gt;Dans ce terminal, vous allez ouvrir avec vim le fichier
~/.xmonad/xmonad.hs&lt;/p&gt;
&lt;p&gt;Placez y ce contenu:&lt;/p&gt;
&lt;pre&gt;
import XMonad
import XMonad.Config.Azerty
import XMonad.Hooks.DynamicLog


-- The main function.
main = xmonad =&amp;lt;&amp;lt; statusBar myBar myPP toggleStrutsKey myConfig

-- Command to launch the bar.
myBar = &amp;quot;xmobar&amp;quot;

-- Custom PP, configure it as you like. It determines what's being written to the bar.
myPP = xmobarPP { ppCurrent = xmobarColor &amp;quot;#429942&amp;quot; &amp;quot;&amp;quot; . wrap &amp;quot;&amp;lt;&amp;quot; &amp;quot;&amp;gt;&amp;quot; }

-- Keybinding to toggle the gap for the bar.
toggleStrutsKey XConfig {XMonad.modMask = modMask} = (modMask, xK_b)

-- Main configuration, override the defaults to your liking.
myConfig = azertyConfig { 
    terminal           = &amp;quot;urxvt -depth 32 -tr -tint rgb:2222/2222/2222 +sb -fg white -bg rgba:0000/0000/0000/7777 -fade 15 -fadecolor black -pr black -pr2 white&amp;quot;
    , logHook = dynamicLog
 }
&lt;/pre&gt;
&lt;p&gt;Fermez, et tenter de compiler la configuration:&lt;/p&gt;
&lt;pre&gt;
xmonad --recompile
&lt;/pre&gt;
&lt;p&gt;Si une erreur apparait, vérifiez bien le contenu du fichier.&lt;/p&gt;
&lt;p&gt;Avant de relancer xmonad, on va aussi configurer xmobar... et ce dans le
fichier ~/.xmobarrc&lt;/p&gt;
&lt;pre&gt;
Config { font = &amp;quot;-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*&amp;quot;
       , bgColor = &amp;quot;black&amp;quot;
       , fgColor = &amp;quot;grey&amp;quot;
       , position = TopW L 100
       , commands = [ Run Weather &amp;quot;LFLY&amp;quot; [&amp;quot;-t&amp;quot;,&amp;quot; &amp;lt;tempC&amp;gt;°&amp;quot;,&amp;quot;-L&amp;quot;,&amp;quot;64&amp;quot;,&amp;quot;-H&amp;quot;,&amp;quot;77&amp;quot;,&amp;quot;--normal&amp;quot;,&amp;quot;green&amp;quot;,&amp;quot;--high&amp;quot;,&amp;quot;red&amp;quot;,&amp;quot;--low&amp;quot;,&amp;quot;lightblue&amp;quot;] 36000
                    , Run Cpu [&amp;quot;-L&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;-H&amp;quot;,&amp;quot;50&amp;quot;,&amp;quot;--normal&amp;quot;,&amp;quot;green&amp;quot;,&amp;quot;--high&amp;quot;,&amp;quot;red&amp;quot;] 10
                    , Run Memory [&amp;quot;-t&amp;quot;,&amp;quot;Mem: &amp;lt;usedratio&amp;gt;%&amp;quot;] 10
                    , Run Swap [] 10
                    , Run Date &amp;quot;%a %b %_d %H:%M&amp;quot; &amp;quot;date&amp;quot; 10
                    , Run StdinReader
                    ]
       , sepChar = &amp;quot;%&amp;quot;
       , alignSep = &amp;quot;}{&amp;quot;
       , template = &amp;quot;%StdinReader% }{ %cpu% | %memory% * %swap%    &amp;lt;fc=#ee9a00&amp;gt;%date%&amp;lt;/fc&amp;gt; | %LFLY%&amp;quot;
       }
&lt;/pre&gt;
&lt;p&gt;Dans ce fichier, remplacer le code &amp;quot;LFLY&amp;quot; par celui de votre ville (ici Lyon
Bron), dans le fichier il est à deux endroits, donc remplacez bien tout. Pour
trouvez votre code, allez à la page http://weather.noaa.gov et prenez le code
qui apparait dans l'url...&lt;/p&gt;
&lt;p&gt;Bon, cette fois ci, on peu relancer xmonad... Pressez ALT+q&lt;/p&gt;
&lt;p&gt;Hop, xmonad se recharge. Pressez ALT+1 ou 2, 3... changement de bureau. Le
clavier azerty est donc bien géré et vous avez théoriquement une barre en haut
qui indique quelques infos.&lt;/p&gt;
&lt;p&gt;Bon, fermez le terminal en cours ALT+shift+c et relancez en un:
ALT+shift+Enter... ha voulà urxvt en mode semi transparent &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt; ouvrez en un
autre, hop l'écran se coupe en deux&lt;/p&gt;
&lt;p&gt;Puis un autre... et un autre....&lt;/p&gt;
&lt;p&gt;Pour vous déplacer, utilisez la souri (haaan) ou simplement alt+k ou alt+j.
Et pour redimensionner les colonnes: alt+h ou alt+l&lt;/p&gt;
&lt;p&gt;Pour augmenter le nombre de fenêtre possible sur la colonne principale (à
gauche) alt+, et pour en retirer alt+.&lt;/p&gt;
&lt;p&gt;Bon assez jouer... on va maintenant faire en sorte de lancer pulseaudio,
xscreensaver et changer ce foutu fond d'écran.&lt;/p&gt;
&lt;p&gt;Créé un fichier, par exemple j'utilise ~/bin/xmonad-startup et posez ceci
dedans:&lt;/p&gt;
&lt;pre&gt;
#!/bin/bash

#prevent running commands on xmonad restart
#I choose xscreensaver because it is stopped at xmonad shutdown
[ &amp;quot;$(ps --noheader -C xscreensaver -o pid)&amp;quot; ] &amp;amp;&amp;amp; exit 0

#commands to lauch
xscreensaver &amp;amp;
feh --bg-fill ~/Images/backgrounds/OTHER-Tuxsta_1600x1200.png
synclient VertTwoFingerScroll=0 VertEdgeScroll=1
pulseaudio --start
&lt;/pre&gt;
&lt;p&gt;Reste à demander à xmonad de les lancer au chargement:&lt;/p&gt;
&lt;pre&gt;
import XMonad
import XMonad.Config.Azerty
import XMonad.Hooks.DynamicLog


-- The main function.
main = xmonad =&amp;lt;&amp;lt; statusBar myBar myPP toggleStrutsKey myConfig

-- Command to launch the bar.
myBar = &amp;quot;xmobar&amp;quot;

-- Custom PP, configure it as you like. It determines what's being written to the bar.
myPP = xmobarPP { ppCurrent = xmobarColor &amp;quot;#429942&amp;quot; &amp;quot;&amp;quot; . wrap &amp;quot;&amp;lt;&amp;quot; &amp;quot;&amp;gt;&amp;quot; }

-- Keybinding to toggle the gap for the bar.
toggleStrutsKey XConfig {XMonad.modMask = modMask} = (modMask, xK_b)


-- my startup
myStartup :: X ()
myStartup = do
    spawn &amp;quot;~/bin/xmonad-startup&amp;quot;

-- Main configuration, override the defaults to your liking.
myConfig = azertyConfig { 
    terminal           = &amp;quot;urxvt -depth 32 -tr -tint rgb:2222/2222/2222 +sb -fg white -bg rgba:0000/0000/0000/7777 -fade 15 -fadecolor black -pr black -pr2 white&amp;quot;
    , logHook = dynamicLog
    , startupHook = myStartup
 }

&lt;/pre&gt;
&lt;p&gt;On recompile: &lt;em&gt;xmonad --recompile&lt;/em&gt; et on relance ALT+q&lt;/p&gt;
&lt;p&gt;Bon, reste à connaitre quelques outils pour utiliser xmonad sans avoir
besoin d'utiliser trop d'outils graphique:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dans un terminal: alsamixer =&amp;gt; gestion du volume&lt;/li&gt;
&lt;li&gt;dans un terminal: mc =&amp;gt; gestionnaire de fichier&lt;/li&gt;
&lt;li&gt;pour lancer un programme sans passer par un terminal: ALT+p et commencez à
taper le nom du programme, l'auto completion est gérée&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous pourrez trovuer des fichier &amp;quot;ini&amp;quot; de &amp;quot;+mc&amp;quot; pour le rendre plus joli.
Utilisez aussi weechat pour aller sur IRC, vous allez voir que finalement c'est
plus clair et efficace.&lt;/p&gt;
&lt;p&gt;Un dernier racourcis ? ALT+Shift+Q et vous quittez Xmonad &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Bon, sinon, utilisez des petits scripts pratique pour votre utilisation, par
exemple j'ai un script &amp;quot;~/bin/dodo&amp;quot; qui met en veille &amp;quot;mémoire&amp;quot; mon pc:&lt;/p&gt;
&lt;pre&gt;
#!/bin/bash
su -c &amp;quot;echo -n mem &amp;gt; /sys/power/state&amp;quot;
&lt;/pre&gt;
&lt;p&gt;ou encore un script pour lancer weechat en me connectant avec mon login/pass
+ ouverture des canaux que j'aime bien:&lt;/p&gt;
&lt;pre&gt;
#!/bin/bash
weechat-curses irc://VOTREUSERICI:VOTREMOTDEPASSEICI@irc.freenode.net/#fedora-fr,#blender-fr,#node.js,#blendercoders,#xmonad
&lt;/pre&gt;
&lt;p&gt;VOTREUSER et VOTREMOTDEPASSE sont les user et mot de passe que vous utilisez
sur IRC...&lt;/p&gt;
&lt;p&gt;Bon voilà... à vous d'apprendre les trucs et astuces, vim ou emacs,
uzbl-brower au lieu de google-chrome (étonnant ce truc, merci WilQu) et j'en
passe... vous allez vous rendre compte aussi que &amp;quot;mc&amp;quot; permet de connecter un
serveru distant sur la vue de gauche (cherchez un peu dans les menu avec F10)
et permet même l'édition. Essayez aussi le racourcis CTRL+O dans mc... sympa
non ?&lt;/p&gt;
&lt;p&gt;Bon allez une capture, parce que vous êtes gentils (faites avec scrot):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.fedora-fr.org/public/metal3d/2011-08-21-132404_1365x767_scrot.png&quot; title=&quot;Xmonad&quot;&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.2011-08-21-132404_1365x767_scrot_s.jpg&quot; alt=&quot;Xmonad&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;Xmonad, août 2011&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.fedora-fr.org/public/metal3d/2011-09-04-123459_1366x768_scrot.png&quot; title=&quot;Xmonad - 2&quot;&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.2011-09-04-123459_1366x768_scrot_m.jpg&quot; alt=&quot;Xmonad - 2&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;Xmonad - 2, sept. 2011&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Voilà, bon ba à vous hein.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Point de montage d'archives</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Point-de-montage-d-archives</link>
    <guid isPermaLink="false">urn:md5:4a398942853bbe45b2ad2e859937bb38</guid>
    <pubDate>Fri, 19 Aug 2011 21:42:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Admin</category>
        <category>bash</category><category>outils</category>    
    <description>&lt;p&gt;Si comme moi vous avez besoin d'utiliser le contenu d'un tar.gz, d'un zip,
ou tout autre archive et que cela vous agace de devoir le décompacter pour le
modifier et le compresser par la suite pour le déplacer... ce billet va vous
intéresser. Nous allons parlons ici de &amp;quot;archivemount&amp;quot;, un outil sympa comme
tout, utilisant &amp;quot;fuse&amp;quot;, et qui va vous faire gagner un peu de temps.&lt;/p&gt;    &lt;p&gt;Il m'arrive souvent ce genre de chose. Devoir récupérer une archive tar.gz
ou tar.bz2, ou encore un zip, et devoir le décompresser pour l'utiliser avec
une application (par exemple un storage pour ezPublish que je déplace pour
bosser chez moi, ou la création d'une archive de release que je veux manipuler
et vérifier simplement). Le fait est que l'archive est parfois lourde, et
devoir ajouter des fichiers ou en supprimer, ou même en modifier est parfois un
peu... suante. Gnome, KDE, proposent bien un outil de montage dans le
navigateur de fichier, mais moi je suis sur Xmonad et j'aime le terminal. C'est
donc le moment de vous montrer l'outil qui rend bien service &amp;quot;archivemount&amp;quot;&lt;/p&gt;
&lt;p&gt;Sur Fedora il est dans les dépôts standard, donc un simple:&lt;/p&gt;
&lt;pre&gt;
su -c &amp;quot;yum install archivemount&amp;quot;
&lt;/pre&gt;
&lt;p&gt;et le tour est joué.&lt;/p&gt;
&lt;p&gt;Alors comment ça marche tout ça ?&lt;/p&gt;
&lt;p&gt;Imaginons une archive &lt;em&gt;monarchive.tar.gz&lt;/em&gt; que je veux utiliser comme
un répertoire. Encore une fois, les systèmes UNIX sont bien sympa en ce qui
concerne la gestion de point de montage. Fuse va être utilisé avec
archivemount. C'est simple comme tout:&lt;/p&gt;
&lt;pre&gt;
mkdir ~/monarchive
archivemount monarchive.tar.bz ~/monarchive
&lt;/pre&gt;
&lt;p&gt;Et voilà... c'est tout. dans le répertoire &lt;em&gt;~/monarchive&lt;/em&gt; se trouve
le contenu de l'archive. Toute modification dans ce répertoire se répercute (au
démontage) dans monarchive.tar.gz.&lt;/p&gt;
&lt;p&gt;C'est donc un point de montage, simple, clair et efficace. A peu près tout
fonctionne: tar (compressé ou non en gz, bz2...), xv, cdrom iso, zip... et les
options de &lt;em&gt;mount&lt;/em&gt; sont évidemment utilisables (ro, rw, nosuid...) comme
avec n'importe quel point de montage.&lt;/p&gt;
&lt;p&gt;Notez que le mode d'écriture asynchrone force donc la recompression au
démontage.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Configuration spécifique de iptables</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Configuration-sp%C3%A9cifique-de-iptables</link>
    <guid isPermaLink="false">urn:md5:c0f3e447448c924e5a086dddea46106d</guid>
    <pubDate>Wed, 10 Aug 2011 18:23:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Réseau</category>
        <category>administration</category><category>iptables</category>    
    <description>    &lt;p&gt;Fedora offre un outil de configuration rapide de par-feu iptables assez
simple, pratique dans la plupart des cas. Comme vous le savez certainement,
CentOS est proche de Fedora dans le sens où la base est quasiment identique, à
la différence des paquets et de l'aptitude de la distribution. CentOS est
orientée serveur. Bref, j'ai eu besoin de créer une machine virtuelle sur ma
Centos et de permettre une redirection de port sur la machine hôte pour me
connecter directement à cette dernière. Or, toucher à iptables ne sauve pas
votre configuration directement, et l'outil de gestion de base ne permet pas de
faire des ip-forward.&lt;/p&gt;
&lt;p&gt;Car en fait, créer une règle de port fowrading est plutôt rapide. Exemple,
ici ma VM a l'ip locale &amp;quot;192.168.122.18&amp;quot; et n'est vu que de ma CentOS hôte
(adresse public 1.2.3.4). Ajouter le port forward se fait de cette manière:&lt;/p&gt;
&lt;pre&gt;
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 10222 -j DNAT --to 192.168.122.18:22
iptables -A FORWARD -i eth0  -p tcp -d 192.168.122.18 --dport 22 -j ACCEPT
&lt;/pre&gt;
&lt;p&gt;Donc j'admet ici que si on se connecte au port 10222 de ma CentOS, je
redirige la connexion sur la machine 192.168.122.18 port 22 (ssh). Cela se fait
par la table PREROUTING qui va manipuler les paquets en changeant les données
ip source et port source, et la table FORWARD qui assigne la redirection. Bref,
sympa &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Mais voilà, si vous voulez redémarrer votre machine, vos deux commandes sont
oubliées car non inscrites dans la configuration de base du service iptables
installée sur votre machine. Donc la solution est simple.&lt;/p&gt;
&lt;p&gt;On va sauver notre ancienne configuration, sait-on jamais, et forcer la
nouvelle configuration depuis la commande iptables-save.&lt;/p&gt;
&lt;pre&gt;
cat /etc/sysconfig/iptables &amp;gt; /etc/sysconfig/iptables.save
iptables-save &amp;gt; /etc/sysconfig/iptables
&lt;/pre&gt;
&lt;p&gt;C'est simple non ? en fait, par bonheur, le service iptables utilise le
format standard de &amp;quot;iptables-save&amp;quot; et &amp;quot;iptables-restore&amp;quot; donc la manipuation
est aisée.&lt;/p&gt;
&lt;p&gt;Voilà, vous pouvez tester en relançant le service iptables, et ne plus avoir
peur de perdre votre forward si le serveur redémarre.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Un chroot si rapide à créer</title>
    <link>http://blog.fedora-fr.org/metal3d/post/un-chroot-si-rapide-%C3%A0-cr%C3%A9er</link>
    <guid isPermaLink="false">urn:md5:97bf8a81f07904cb804cf3523b161d83</guid>
    <pubDate>Wed, 03 Aug 2011 02:15:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>administration</category><category>bash</category><category>chroot</category><category>terminal</category>    
    <description>    &lt;p&gt;J'avais travaillé sur la documentation de chroot sur cette page: &lt;a href=&quot;http://doc.fedora-fr.org/wiki/Utilisation_de_chroot&quot; title=&quot;http://doc.fedora-fr.org/wiki/Utilisation_de_chroot&quot;&gt;http://doc.fedora-fr.org/wiki/Utili...&lt;/a&gt;
mais depuis, les choses ont changé. Febootstrap ne marche plus du tout comme
avant... et j'ai trouvé une manière encore plus simple de créer une base chroot
sans manipuler des fichiers de dépôts. Vous allez voir, c'est tellement simple
que ça en est presque indécent.&lt;/p&gt;
&lt;p&gt;Voilà la manière la plus facile que j'ai trouvé, par exemple pour encapluser
&amp;quot;php-cli&amp;quot; dans un chroot:&lt;/p&gt;
&lt;pre&gt;
cd ~
mkdir -p chroots/fedora-15-chroot
cd chroots
su -c 'yum --installroot=`pwd`/fedora-15-chroot --releasever=15 install php-cli -y'
&lt;/pre&gt;
&lt;p&gt;C'est simple comme choux en fait...&lt;/p&gt;
&lt;p&gt;Je crée un répertoire dans mon &amp;quot;home&amp;quot; (cd ~ et mkdir -p
chroots/fedora-15-chroot). Ensuite je demande à &lt;em&gt;yum&lt;/em&gt; d'installer
&lt;em&gt;php-cli&lt;/em&gt; dans le répertoire fedora-15-chroot. Comme je n'ai pas créé de
fichier de dépots Fedora dans le répertoire de chroot, je spécifie simplement
que je veux utiliser la version &amp;quot;15&amp;quot; de fedora. Notez que &amp;quot;releasever&amp;quot; est une
contraction de &amp;quot;release version&amp;quot;.&lt;/p&gt;
&lt;p&gt;Et comme par enchantement, j'ai un chroot fonctionnel !&lt;/p&gt;
&lt;p&gt;Là où c'est intéressant, c'est que je me passe de pas mal de configuration
un peu compliqué. Il est alors facile de changer de &lt;em&gt;--releasever&lt;/em&gt; en
&lt;em&gt;16&lt;/em&gt; pour tester la rawhide, ou une version inférieure...&lt;/p&gt;
&lt;p&gt;Me reste plus qu'à voir comment fonctionne lxc (et je n'ai pas la dernière
version de libvirt donc je n'ai pas encore l'accès facilité par virt-manager)
et je vais pouvoir tester pas mal de choses, comme faire marcher des bases en
jail, compiler des choses tordus ou voir comment péter un système sans avoir
peur &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Radeon et Blender font mauvais ménage</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Radeon-et-blender-font-mauvais-m%C3%A9nage</link>
    <guid isPermaLink="false">urn:md5:0e1c2cfb00d2f1590dca571475de43c0</guid>
    <pubDate>Sat, 30 Jul 2011 11:00:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Multimedia</category>
        <category>blender</category><category>radeon</category>    
    <description>    &lt;p&gt;En fait, ce n'est pas seulement pour Blender que je vais parler, mais
certaines applications 3D qui peuvent avoir tendance à planter misérablement en
utilisant une carte ATI (AMD) sur notre Fedora 15... Car voilà, depuis mon
passage à Fedora 15, tout se passe bien sauf un truc: travailler sous Blender.
J'ai tout tenté: passage à Xfce pour éviter Mutter, recompilation de Blender,
debugage, ... et rien n'y faisait. Après quelques minutes, un plantage et pas
moyen de trouver une solution. Sauf que j'ai trouvé un tour de passe-passe qui
permet, pour le moment, de palier le souci.&lt;/p&gt;
&lt;p&gt;Bon avant toutes chose, un petit tour vers le rapport de bug que j'ai
commenté: &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=714280&quot;&gt;libllvmcore-2.8.so.debug
has no usable debug info&lt;/a&gt; Ça donne pas envie hein... En fait pour faire
court, un souci bien dégoûtant apparaît avec le pilote radeon et en plus de
cela on a pas les infos de débogage pour notre problème. Raaa la rage
m'envahissait et comme je voulais finir un boulot sur Blender, me fallait vite
une solution.&lt;/p&gt;
&lt;p&gt;Et bien j'ai finis par y aller &amp;quot;bourrin&amp;quot;... en utilisant une compilation du
pilote &amp;quot;gallium&amp;quot;. C'est en fait une compilation &amp;quot;grotesque&amp;quot; qui va me permettre
d'utiliser une librairie openGL très épurée. Donc certes je vais perdre
l'antialiasing et certainement avoir une visu assez moche dans Blender, mais au
moins ça ne plantera pas. Et pour vous rassurer, seule la vue 3D est impactée,
le rendu et le traitement image/vidéo ne sont pas impactés.&lt;/p&gt;
&lt;p&gt;Bon et bien voici la méthode:&lt;/p&gt;
&lt;pre&gt;
#on va dans notre répertoire perso
cd ~
#on clone le dépot mesa
git clone git://anongit.freedesktop.org/git/mesa/mesa
cd mesa

#on compile le driver gallium, donc pas de DRI pour radeon et consorts
make  linux-x86-64 -j4
#make  linux-x86-32 -j4 pour les cpu 32 bits

#si vous avez un core i7, vous pouvez mettre -j8 au lieu de -j4
#on attend un peu la fin de la compilation puis
cd lib64 #ou cd lib si vous êtes sur un pc 32 bits

#à faire avant de lancer blender...
export LD_LIBRARY_PATH=~/mesa/lib64
#puis on lance blender
cd ~/blender-2.58
./blender -w
&lt;/pre&gt;
&lt;p&gt;Deux choses, d'une part évitez le mode plein écran, perso ça fait un truc
tout bizarre sur mon pc... et secondo, utilisez l'option &amp;quot;-w&amp;quot; comme spécifié,
ça évitera des ennuis de bordure que j'ai vu sur mon poste.&lt;/p&gt;
&lt;p&gt;Si vous avez des soucis, passez de Gnome à Xfce. Ca limitera les appels
OpenGL et les court-circuits d'affichage. Toujours est-il que ça marche, ça
marche même pas mal du tout... c'est moins beau, oui, mais ça marche.&lt;/p&gt;
&lt;p&gt;Aussi, pour couper l'herbe sous les pieds des trolls qui vont arriver en
commentaire: oui, ATI sur linux c'est pas bien, je sais, mais j'ai pas le choix
pour deux raisons: d'une j'ai un laptop (ordinateur portable) et le prix était
intéressant avec cette carte, et secondo j'utilise de temps en temps un kernel
RT qui ne marche pas avec les pilotes nvidia. Donc je sais, j'ai pas une bonne
config, mais je suis pas le seul. Et quand bien même, un matériel ne doit pas
engendrer un souci de ce genre alors qu'il est récent.&lt;/p&gt;
&lt;p&gt;Soit dit en passant, bien que le bug soit là, on apprécie tout de même
d'avoir utilisé des logiciels libres. Car si tout ce que j'utilise était
propritaire, je n'aurai pas de solution pour contourner le problème. Là, encore
une fois, en suivant quelques indications, on arrive à se dépêtrer d'un gros
problème parce que nous pouvons compiler et/ou modifier des sources.&lt;/p&gt;
&lt;p&gt;Alors dans notre malheur, vous et moi qui avons des soucis avec cette
radeon, réjouissons nous de pouvoir travailler en mode dégradé grâce à la
philosophie du logiciel libre, et de ne pas rester coincé !&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Tester des paquets sans tout casser</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Tester-des-paquets-sans-tout-casser</link>
    <guid isPermaLink="false">urn:md5:da5731d2bd5f344b2bf18c24798c1e90</guid>
    <pubDate>Sat, 30 Jul 2011 00:40:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Développement</category>
        <category>administration</category><category>rawhide</category><category>yum</category>    
    <description>    &lt;p&gt;Une des raisons pour laquelle j'utilise Fedora depuis des années c'est
l'aptitude (clin d'oeil de geek...) de yum à permettre des manipulations de
paquets assez rapide. J'avais justement besoin de tester llvm 2.9 qui est pour
le moment dans les dépôts &lt;em&gt;rawhide&lt;/em&gt; (c'est à dire dans les dépôts de
développement de la future version de fedora). Donc, me voilà avec un dilemme:
comment tester sans tout casser et sans me prendre la tête à installer une VM?
La réponse est dans &lt;em&gt;yum&lt;/em&gt; l'ami.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;yum&lt;/em&gt; a deux options (en fait une commande et une option) qui me
permettent de tester sans massacrer mon système: &lt;em&gt;distro-sync&lt;/em&gt; et
&lt;em&gt;--releasever&lt;/em&gt;. La première fait en sorte de synchroniser mes versions
de paquets à la version de fedora en cours, et l'autre me permet de spécifier
la version de fedora à utiliser.&lt;/p&gt;
&lt;p&gt;Et bien allons y gaiement:&lt;/p&gt;
&lt;pre&gt;
su -
yum clean all
yum --releasever=rawhide --nogpgcheck --disablerepos=rpmfusion\* update llvm
&lt;/pre&gt;
&lt;p&gt;Cela à pour effet de lancer une installation en spécifiant que je cherche
des paquets pour rawhide. L'installation terminée, j'ai bien un llvm 2.9 qui
est installé alors que sur Fedora 15 nous sommes en version 2.8.&lt;/p&gt;
&lt;p&gt;Mes tests terminés (et non concluant) j'ai eut envie de revenir à ma version
de base. Et bien c'est simple:&lt;/p&gt;
&lt;pre&gt;
yum clean all
yum distro-sync
&lt;/pre&gt;
&lt;p&gt;Et voilà, &lt;em&gt;yum&lt;/em&gt; trouve des paquets à &lt;em&gt;downgrader&lt;/em&gt; (réduire la
version) et me réinstalle tous les paquets estampillés pour la version fedora
supérieure à la version actuelle (ici fedora 15). Du coup j'ai resynchronisé ma
fedora. Attention tout de même à ne pas faire ça pour n'importe quoi...
n'oubliez pas que des fichier &lt;em&gt;.rpmnew&lt;/em&gt; peuvent apparaître ou encore
peuvent vraiment planter le système.&lt;/p&gt;
&lt;p&gt;Personnellement j'évite de faire ça pour tout, par exemple pour le moment
j'évite de jouer avec des version de gnome qui se trouve dans rawhide, mais
pour ce qui est de certaines librairies, compilateurs, ou encore apache, php...
j'aime bien tester de la sorte.&lt;/p&gt;
&lt;p&gt;Effectivement lxc ou carrément une machine virtuelle pourrait faire
l'affaire, mais c'est tellement sympa avec yum... non ?&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Faire parler son pc</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Faire-parler-son-pc</link>
    <guid isPermaLink="false">urn:md5:5d613b440fd6685e3bb62623bf9d3003</guid>
    <pubDate>Wed, 27 Jul 2011 14:53:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>bash</category><category>outils</category><category>synthèse vocale</category>    
    <description>    &lt;p&gt;Ça peut paraître gadget, mais on se rend compte assez vite que la synthèse
vocale sur un poste peut être intéressante dans pas mal de cas. Par exemple,
j'ai tendance à compiler des applications assez lourdes, et pour être prévenu,
j'aime avoir une voix qui me dit &amp;quot;la compilation de blender 2.58 pour cycles
est terminée sans erreur&amp;quot;... Ou encore, me prévenir vocalement que j'ai un
souci sur un serveur distant... Cela permet d'avoir une annonce clair et de ne
pas avoir constamment sous les yeux un panel de tests. En gros, c'est pratique,
gadget oui, mais pratique.&lt;/p&gt;
&lt;p&gt;Alors comment faire causer notre coucou. Il existe des méthodes libres et/ou
gratuites. Je vais vous montrer une procédure pas à pas qui va vous permettre
d'avoir une jolie voix sur le pc (si on est pas trop regardant) et comment
utiliser cela pour pas mal d'opérations. Le but est de faire simple, pratique
et utile.&lt;/p&gt;
&lt;h2&gt;Première approche, espeak seul.&lt;/h2&gt;
&lt;p&gt;Espeak est un projet libre, facilement installable sur votre Fedora puisque
dans les dépots officiels. Pour l'installer vous pouvez passer par l'outil
d'ajout de paquets ou via une console:&lt;/p&gt;
&lt;pre&gt;
su -c &amp;quot;yum install espeak -y&amp;quot;
&lt;/pre&gt;
&lt;p&gt;A partir de maintenant, vous avez la commande &lt;em&gt;espeak&lt;/em&gt; qui vous
permet de faire parler le pc. Avant de vous lancer en vous disant &amp;quot;ça y est
mais trop bien !!!&amp;quot; je tiens à vous prévenir: ça va pas être super beau. En
effet, la voix anglaise est à peu près écoutable, par contre en Français... mon
dieu. Je veux bien être indulgent, mais honnêtement là vous allez voir c'est
pas super joli.&lt;/p&gt;
&lt;p&gt;Exemple:&lt;/p&gt;
&lt;pre&gt;
espeak -vfr &amp;quot;bonjour à toi humble utilisateur de la console&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Ça pique un peu non ?&lt;/p&gt;
&lt;p&gt;En anglais c'est à peine mieux:&lt;/p&gt;
&lt;pre&gt;
espeak  &amp;quot;Hi dude, this is better, isn't it ?&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Bref, si cela vous plait vous pouvez utiliser epseak tel quel... mais
personnellement j'ai eut envie de trouver mieux. Et la solution a été &amp;quot;mbrola&amp;quot;.
Notre méthode va utiliser espeak et mbrola, le premier pour générer des
phonèmes et l'autre pour parler.&lt;/p&gt;
&lt;h2&gt;Deuxième approche: espeak + mbrola&lt;/h2&gt;
&lt;p&gt;mbrola est un projet gratuit mais non libre. Je suis pas fan de la politique
qu'ils utilisent, d'autant que le projet a l'air de sombrer doucement dans les
abîmes des ligiciels qui auraient put devenir des références pour des années...
Mais toujours est-il qu'à l'heure actuelle on peut encore s'en servir.&lt;/p&gt;
&lt;p&gt;Donc, on va préparer notre installation.&lt;/p&gt;
&lt;pre&gt;
su -
mkdir -p /opt/mbrola
cd /opt/mbrola
wget http://tcts.fpms.ac.be/synthesis/mbrola/bin/pclinux/mbr301h.zip
unzip mbr301h.zip
rm -f mbr301h.zip
&lt;/pre&gt;
&lt;p&gt;Oui, que vous soyez sous 64bits ou 32bits, on devra utiliser la version
32bits.&lt;/p&gt;
&lt;p&gt;mbrola a besoin de fichier de voix. On va récupéré l'une de celle qui va le
mieux pour notre test:&lt;/p&gt;
&lt;pre&gt;
mkdir fr4
cd fr4
wget http://tcts.fpms.ac.be/synthesis/mbrola/dba/fr4/fr4-990521.zip
unzip fr4-990521.zip
rm -f fr4-990521.zip
exit
&lt;/pre&gt;
&lt;p&gt;N'oubliez pas de bien taper &amp;quot;exit&amp;quot;, nous ne devons plus être &amp;quot;root&amp;quot; à partir
de maintenant.&lt;/p&gt;
&lt;p&gt;Bon, maitenant que le paquet est là... on passe au &amp;quot;pipe&amp;quot; qui permet de
faire parler mbrola. Il faut savoir que espeak embarque quelques &amp;quot;voix&amp;quot; de
mbrola par défaut. Donc nous allons utiliser cela pour faire causer
l'ordinateur.&lt;/p&gt;
&lt;p&gt;Bon je vous explique rapidement, on va pas trop détailler le principe&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;espeak -vmb/mb-fr2 &amp;quot;texte à donner&amp;quot; retourne une sortie qui correspond aux
phonèmes au format reconnu par mbrola&lt;/li&gt;
&lt;li&gt;mbrola fichier-de-voix phonèmes fichier.format: va lire l'entrèe de
phonèmes et sortir un fichier au format désiré &amp;quot;au, wave...&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Comme nous ne voulons pas créer des fichiers sur le disque, on peut &amp;quot;piper&amp;quot;
les sorties. De ce fait:&lt;/p&gt;
&lt;pre&gt;
mbrola fichier_de_voix - -.au | play - 2&amp;gt;/dev/null
&lt;/pre&gt;
&lt;p&gt;aura pour effet de récupérer les phonèmes depuis l'entrée standard et créera
un fichier &amp;quot;au&amp;quot; directement envoyé à la sortie standard. &amp;quot;play&amp;quot; va alors lire
cette sortie standard et nous redirigeons toutes les erreurs dans /dev/null
pour ne pas polluer notre console...&lt;/p&gt;
&lt;p&gt;Donc le pipe complet est:&lt;/p&gt;
&lt;pre&gt;
espeak -vmb/mb-fr4 &amp;quot;Bonjour à toi humble utlisateur de la console&amp;quot; | /opt/mbrola/mbrola-linux-i386 /opt/mbrola/fr4/fr4 - -.au | play - 2&amp;gt;/dev/null
&lt;/pre&gt;
&lt;p&gt;Ha oui, elle parle vite la nana hein &lt;img src=&quot;/themes/default/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Et bien nous allons palier la vitesse via les options de mbrola.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-t 1.2 par exemple va réduire la vitesse de parole d'un ration de 1.2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce qui nous donne:&lt;/p&gt;
&lt;pre&gt;
espeak -vmb/mb-fr4 &amp;quot;Bonjour à toi humble utlisateur de la console&amp;quot; | /opt/mbrola/mbrola-linux-i386 -t 1.2 /opt/mbrola/fr4/fr4 - -.au | play - 2&amp;gt;/dev/null
&lt;/pre&gt;
&lt;p&gt;Mieux n'est-ce pas ?... On peut encore jouer avec quelques options, comme le
&amp;quot;pitch&amp;quot; (hauteur de voix) et le volume:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-v 0.8 volume à 80%&lt;/li&gt;
&lt;li&gt;-f 1.1 monte le pitch de 10%&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
espeak -vmb/mb-fr4 &amp;quot;Bonjour à toi humble utlisateur de la console&amp;quot; | /opt/mbrola/mbrola-linux-i386 -f 1.1 -v 0.8 -t 1.2 /opt/mbrola/fr4/fr4 - -.au | play - 2&amp;gt;/dev/null
&lt;/pre&gt;
&lt;p&gt;Comme je vous le disai, c'est mieux que espeak mais on est encore loin de la
beauté extême. Le souci n'est pas mbrola, mais la création des phonèmes. Car
les exemples proposés par mbrola vous montre qu'on pourrait s'y tromper.&lt;/p&gt;
&lt;h2&gt;Automatisation&lt;/h2&gt;
&lt;p&gt;Bon il nous reste une chose à faire, rendre utilisable aisément cette
commande. Et bien faisons ça simple:&lt;/p&gt;
&lt;pre&gt;
su -
cat &amp;gt; /usr/local/bin/sayit&amp;lt;&amp;lt;EOF
espeak -vmb/mb-fr4 &amp;quot;\$@&amp;quot; | /opt/mbrola/mbrola-linux-i386 -f 1.1 -v 0.8 -t 1.2 /opt/mbrola/fr4/fr4 - -.au | play - 2&amp;gt;/dev/null
EOF
chmod +x /usr/local/bin/sayit
exit
&lt;/pre&gt;
&lt;p&gt;Voilà nous avons créé une commande &amp;quot;sayit&amp;quot; qui va nous permettre de faire
cela:&lt;/p&gt;
&lt;pre&gt;
sayit &amp;quot;Que c'est bien de travailler sous linux&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Reste alors à utiliser notre commande comme je vous le disais au début de
l'article. Par exemple, quand je compile un programme:&lt;/p&gt;
&lt;pre&gt;
make &amp;amp;&amp;amp; sayit &amp;quot;Compilation de Blender terminé avec succès&amp;quot; || sayit &amp;quot;Compilation de Blender avec erreurs&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Et j'en passe, vous pouvez faire un petit programme en bash qui lit des logs
et vous annonce une erreur, ou encore un module XChat qui vous préviens que
quelqu'un vient de vous parler.&lt;/p&gt;
&lt;p&gt;Ce gadget est intéressant quand on est comme moi à travailler sur plusieurs
machines en même temps, souvent en train de préparer du café, ou sur plusieurs
taches en même temps.&lt;/p&gt;
&lt;p&gt;Voilà, j'espère que vous avez apprécié mon explication et si vous avez des
idée d'utilisations ou script, faites passer !&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Evolution et le «marquer comme lut»</title>
    <link>http://blog.fedora-fr.org/metal3d/post/Evolution-et-le-marquer-comme-lut</link>
    <guid isPermaLink="false">urn:md5:4485661a24aa2ac720ff42dcbbefb3b0</guid>
    <pubDate>Sun, 24 Jul 2011 03:09:00 +0200</pubDate>
    <dc:creator>Metal3d</dc:creator>
        <category>Bureau</category>
        <category>evolution</category><category>gconf</category><category>gnome</category><category>mail</category>    
    <description>    &lt;p&gt;Depuis mon passage à Gnome 3 j'ai quelques mauvaises surprises dans quelques
applications... Rien de bien méchant, mais il arrive que certaines nouvelles
applications perdent des options que je trouvais agréables. C'est le cas pour
Evolution Mail 3, j'ai cherché un bon moment avant de me rendre compte que &amp;quot;non
je ne suis pas fou, l'option «marquer comme lut après X secondes»&amp;quot; a bel et
bien disparut... Mais n'ayant pas donné mon dernier mot, j'ai pensé que comme
beaucoup d'applications gnome, la configuration a dut passer dans &amp;quot;gconf&amp;quot;&lt;/p&gt;
&lt;p&gt;Et je n'ai pas eut tort... en fouillant un peu dans &amp;quot;gconf-editor&amp;quot; j'ai
trouvé ça:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.fedora-fr.org/public/metal3d/.Capture-Editeur_de_configuration_-_display_m.jpg&quot; alt=&quot;Gconf - Evolution - Mark as read&quot; style=&quot;display:block; margin:0 auto;&quot; title=&quot;Gconf - Evolution - Mark as read, juil. 2011&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Il a suffit de mettre cette valeur à 0 pour qu'enfin un mail soit marqué
comme lut immédiatement, et pas après 1.5 secondes.&lt;/p&gt;
&lt;p&gt;Autre méthode plus rapide, dans une console:&lt;/p&gt;
&lt;pre&gt;
gconftool-2 --set /apps/evolution/mail/display/mark_seen_timeout 0 --type int
&lt;/pre&gt;
&lt;p&gt;Cela revient au même...&lt;/p&gt;
&lt;p&gt;Alors pour ne pas m'arrêter à cette mésaventure, je tiens à donner un avis
sur la direction que prend Gnome dans certains cas qui me gêne. J'ai toujours
été un détracteur de la base de registre Windows, selon moi c'est un truc
imbuvable pour le commun des mortels et en plus de cela vous remarquez que ce
n'est pas franchement trivial.&lt;/p&gt;
&lt;p&gt;Alors qu'un fichier de configuration suffirait, et que des options aisées
sont plus adéquates, surtout sur un outil aussi basique que la lecture de
mails, on se retrouve à chercher un terme dans une liste énorme de valeur typée
et ce dans un système de configuration imbitable.&lt;/p&gt;
&lt;p&gt;Bien que l'interface Gnome 3 me plaise énormément, que je trouve que
l'avancée ergonomique que montre le développement de ce gestionnaire de bureau
est impressionnant, et que l'innovation de ce dernier m'a vraiment plut, j'ai
l'impression de régresser sur le sujet de la configuration.&lt;/p&gt;
&lt;p&gt;Oui, je conçois bien que gconf est un outil vraiment intéressant,
techniquement parlant, car cela permet une homogénéité des données pour la
configuration de l'environnement. Et d'autant plus que cela permet un échange
de configuration inter logiciel. Mais ce coté qui force l'utilisation d'un
outil de configuration pour changer des valeurs m'horripile fortement.&lt;/p&gt;
&lt;p&gt;Bon, cela étant dit, j'ai utilisé gconf que peu de fois pour modifier ce
genre de valeur... en général, les développeurs pensent bien à mettre une
option dans l'interface dédiée de configuration du programme... mais pour le
coup, là, Evolution porte son nom à l'envers, car on a régressé sur pas mal de
points.&lt;/p&gt;
&lt;p&gt;Seul plaisirs vraiment intéressant que je trouve à Evolution 3, outre le
fait qu'il puisse se connecter à Exchange, c'est qu'il est devenu bien plus
performant. Et l'interfaçage avec Google pour l'agenda et les contacts
synchronisés m'ont charmé (Thunderbird peut le faire, mais honnêtement je
trouve qu'Evolution le fait mieux)&lt;/p&gt;
&lt;p&gt;Voilà pour ma partie coup de gueule du dimanche à 3h du matin...&lt;/p&gt;</description>
    
    
    
      </item>
    
</channel>
</rss>