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

<channel>
	<title>Trux &#187; Informatique</title>
	<atom:link href="http://trux.info/category/informatique/feed/" rel="self" type="application/rss+xml" />
	<link>http://trux.info</link>
	<description>Partage de mes astuces et découvertes</description>
	<lastBuildDate>Tue, 09 Jun 2009 19:47:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Reverse SSH, ou comment se faufiler entre NAT et Firewall</title>
		<link>http://trux.info/2009/05/reverse-ssh-ou-comment-se-faufiler-entre-nat-et-firewall/</link>
		<comments>http://trux.info/2009/05/reverse-ssh-ou-comment-se-faufiler-entre-nat-et-firewall/#comments</comments>
		<pubDate>Fri, 15 May 2009 06:58:35 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://trux.info/?p=122</guid>
		<description><![CDATA[ssh est un outil merveilleux : il permet de se connecter à un hôte et exécuter des commandes à distances de manière sécurisée.
Il permet également de tunneler un port local vers un port distant d&#8217;une autre machine. Ainsi tout ce qui est envoyé sur le port local va être transmis au port distant via la [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.openssh.com/">ssh</a> est un <a href="http://doc.ubuntu-fr.org/ssh">outil merveilleux</a> : il permet de se connecter à un hôte et exécuter des commandes à distances de manière sécurisée.</p>
<p>Il permet également de tunneler un port local vers un port distant d&#8217;une autre machine. Ainsi tout ce qui est envoyé sur le port local va être transmis au port distant via la communication ssh sécurisée. Cette manipulation s&#8217;avère très pratique pour sortir d&#8217;un réseau dont seuls les ports 22 et 80 sont ouverts.</p>
<p>Je viens d&#8217;apprendre récemment comment faire l&#8217;inverse : tunneler un port d&#8217;une machine distante vers un port d&#8217;une machine locale. Ainsi tout ce qui est envoyé sur le port de la machine distante va être transmis au port de la machine locale. En résumé, si votre machine locale est sur un réseau protégé par un NAT et un firewall, çette manipulation met en place une backdoor vers le réseau protégé.<br />
<span id="more-122"></span><br />
Par exemple, vous avez une machine, nommée dest, qui est sur un réseau NATé protégé par un firewall. On ne peut pas s&#8217;y connecter en ssh par l&#8217;extérieur car le pare feu bloque ce port (ou bien il le redirige sur une autre machine qui ne vous intéresse pas). Prenons maintenant une autre machine, nommée middle, qui se trouve à l&#8217;extérieur du réseau protégé. Il suffit de créer un reverse tunnel pour exposer le port 22 de la machine dest sur un autre port de la machine middle. Cette commande est à exécuter au préalable sur dest :</p>
<pre>destuser@dest$ ssh -R 2200:localhost:22 middleuser@middle</pre>
<p>Tant que la connexion ssh est active, le port 2200 de middle est en écoute et transmet les paquets au port 22 de dest.Ensuite de l&#8217;extérieur, depuis chez vous sur votre machine home, il suffit de se connecter à middle de manière classique, puis de se connecter une nouvelle fois en utilisant le port exposé, 2200, pour se connecter à dest.</p>
<pre>user@home$ ssh middleuser@middle
middleuser@middle$ ssh destuser@localhost -p 2200
destuser@dest$</pre>
<p>Voilà, vous êtes connecté à dest.</p>
<p>Si vous pouvez sortir sur le port 2200 directement, vous n&#8217;êtes pas obligé de faire ce double saut. Vous pouvez vous connecter directement au port 2200 de la machine middle :</p>
<pre>user@home$ ssh destuser@middle -p 2200</pre>
<p>Si vous ne pouvez pas sortir sur un autre port que le prt 22 et que vous voulez vous connecter en une seule commande, on peut rajouter un petit tunnel supplémentaire entre le port 2200 de la machine home et le port 2200 de la machine middle :</p>
<pre>user@home$ ssh -L2200:localhost:2200 middleuser@middle</pre>
<p>et on se connecte alors ainsi :</p>
<pre>user@home$ ssh destuser@localhost -p 2200</pre>
<p>Dans cet exemple, j&#8217;ai présenté une connexion vers le port 22, pour ssh, mais le plus souvent, vous avez déjà établi un mécanisme permettant une connexion à votre réseau domestique. Dans ce cas cette astuce peut être pratique quand vous êtes à l&#8217;extérieur, pour exposer temporairement le port d&#8217;un service de votre réseau local à l&#8217;extérieur (au hasard, des ports POP et IMAP pour relever votre mail). Attention à bien protéger les accès dans ce cas.</p>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/05/reverse-ssh-ou-comment-se-faufiler-entre-nat-et-firewall/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>assertThat(JUnit4, canHave(betterSyntax));</title>
		<link>http://trux.info/2009/03/assertthatjunit4-canhavebettersyntax/</link>
		<comments>http://trux.info/2009/03/assertthatjunit4-canhavebettersyntax/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 20:50:54 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jmock]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://trux.info/?p=113</guid>
		<description><![CDATA[Lors de l&#8217;écriture de tests unitaires, on peut se retrouver à écrire ce genre de code :

assertEquals&#40;42, answer&#41;;
assertFalse&#40;answer == 34&#41;;
assertTrue&#40;info.matches&#40;&#34;color&#34;&#41; &#124;&#124; info.matches&#40;&#34;colour&#34;&#41;&#41;;
assertTrue&#40;colorsList.contains&#40;&#34;red&#34;&#41;&#41;;
assertTrue&#40;s instanceof MagicString&#41;;

Mais JUnit propose depuis la version 4.4 une nouvelle syntaxe à base de Matchers. En fait, cette syntaxe n&#8217;est pas totalement nouvelle : elle est empruntée à JMock qui possède déjà les [...]]]></description>
			<content:encoded><![CDATA[<p>Lors de l&#8217;écriture de tests unitaires, on peut se retrouver à écrire ce genre de code :</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;">assertEquals<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span>, answer<span style="color: #009900;">&#41;</span>;
assertFalse<span style="color: #009900;">&#40;</span>answer <span style="color: #339933;">==</span> <span style="color: #cc66cc;">34</span><span style="color: #009900;">&#41;</span>;
assertTrue<span style="color: #009900;">&#40;</span>info.<span style="color: #006633;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span> || info.<span style="color: #006633;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;colour&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertTrue<span style="color: #009900;">&#40;</span>colorsList.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;red&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertTrue<span style="color: #009900;">&#40;</span>s <span style="color: #000000; font-weight: bold;">instanceof</span> MagicString<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Mais JUnit propose depuis la version 4.4 une <a href="http://junit.sourceforge.net/doc/ReleaseNotes4.4.html">nouvelle syntaxe</a> à base de <a href="http://junit.org/apidocs/org/junit/matchers/JUnitMatchers.html">Matchers</a>. En fait, cette syntaxe n&#8217;est pas totalement nouvelle : elle est empruntée à <a href="http://www.jmock.org/">JMock</a> qui possède déjà les <a href="http://www.jmock.org/matchers.html">Matchers JMock</a> pour décrire les contraintes d&#8217;un mock. L&#8217;idée vient de <a href="http://joewalnes.com/">Joe Walnes</a> dans son article <a href="http://joe.truemesh.com/blog/000511.html">Flexible JUnit assertions with assertThat()</a>.</p>
<p>Les assertions précédentes peuvent alors s&#8217;écrire de la manière suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;">assertThat<span style="color: #009900;">&#40;</span>answer, is<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertThat<span style="color: #009900;">&#40;</span>answer, is<span style="color: #009900;">&#40;</span>not<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">34</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertThat<span style="color: #009900;">&#40;</span>info, either<span style="color: #009900;">&#40;</span>containsString<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">or</span><span style="color: #009900;">&#40;</span>containsString<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;colour&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertThat<span style="color: #009900;">&#40;</span>colorsList, hasItem<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;red&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
assertThat<span style="color: #009900;">&#40;</span>s, <span style="color: #000000; font-weight: bold;">instanceOf</span><span style="color: #009900;">&#40;</span>MagicString.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Les avantages sont multiples :</p>
<ul>
<li>Ça se lit mieux : le développeur communique donc mieux son intention aux autres développeurs, ce qui est essentiel !</li>
<li>Contrairement aux méthodes assertEquals et consorts, on ne risque pas de tromper dans l&#8217;ordre des arguments : la syntaxe d&#8217;assertEquals est <code>assertEquals([expected], [actual])</code> mais beaucoup de gens se trompent et écrivent <code>assertEquals(answer, 42)</code>. Avec assertThat, aucun risque.</li>
<li>Les matchers peuvent être modifiés: par exemple : <code>not(s)</code> pour inverser la condition, <code>either(s).or(t)</code> pour combiner des conditions, <code>each(s)</code> pour appliquer une condition sur chaque élément d&#8217;une collection, <code>afterFiveSeconds(s)</code> pour attendre 5 secondes avant de tester&#8230;</li>
<li>En cas d&#8217;échec de l&#8217;assertion, les messages sont beaucoup plus lisibles. Si on reprend l&#8217;exemple précédents, avec les assertXxx classiques, les messages ressembleraient à ça :
<pre>
assertEquals(42, answer);
 => expected:<42> but was:<36>
assertFalse(answer == 34);
 => junit.framework.AssertionFailedError:
assertTrue(info.matches("color") || info.matches("colour"));
 => junit.framework.AssertionFailedError:
assertTrue(colorsList.contains("red"));
 => junit.framework.AssertionFailedError:
assertTrue(s instanceof MagicString);
 => junit.framework.AssertionFailedError:
</pre>
<p>Avec assertThat, les message ressemblent plutôt à ça :
<pre>
assertThat(answer, is(42));
 => Expected: is <42>
         got: <36>
assertThat(answer, is(not(34)));
 => Expected: is not <34>
         got: <34>
assertThat(info, either(containsString("color")).or(containsString("colour")));
 => Expected: (a string containing "colour" or a string containing "color")
         got: "rainbow"
assertThat(colorsList, hasItem("red"));
 => Expected: a collection containing "hello"
         got: <[bonjour, ia orana]>
assertThat(s, instanceOf(MagicString.class));
 => Expected: an instance of sandbox.FooTest$MagicString
         got: "polop"
</pre>
<p>Inutile de dire qu&#8217;il est beaucoup plus facile de débugguer des tests écrits avec assertThat&#8230;</li>
<li>Il est plus facile d&#8217;écrire des Matcher maison plutôt que des méthodes assertXxxx maison. En plus ces Matchers pourront être réutilisés dans des tests JMock.</li>
<li>C&#8217;est sexy <img src='http://trux.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>Pour plus d&#8217;informations, je vous recommande la lecture de <a href="http://blog.xebia.fr/2008/04/02/simplifier-les-assertions-junit-et-ameliorer-vos-tests/">ce billet</a>. Il est en français, il est très détaillé et je suis tombé dessus en écrivant cet article.</p>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/03/assertthatjunit4-canhavebettersyntax/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Assurer la sérialisation d&#8217;un objet</title>
		<link>http://trux.info/2009/02/assurer-la-serialisation-dun-objet/</link>
		<comments>http://trux.info/2009/02/assurer-la-serialisation-dun-objet/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 14:09:39 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[sérialisation]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://trux.info/?p=84</guid>
		<description><![CDATA[En java, n&#8217;importe quel objet implémentant l&#8217;interface Serializable peut être converti facilement en une séquence d&#8217;octets. Cette même séquence peut ensuite être reconverti en l&#8217;objet original. Ce mécanisme est par exemple utilisé pour transmettre des objets par RMI.
Voici une petite méthode pour vérifier que votre classe est bien sérialisable

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import static [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://trux.info/wp-content/uploads/2009/02/conserve.jpg" alt="boîte de conserve" title="boîte de conserve" class="alignright size-full wp-image-83" />En java, n&#8217;importe quel objet implémentant l&#8217;interface <a href="http://java.sun.com/javase/6/docs/api/java/io/Serializable.html">Serializable</a> peut être converti facilement en une séquence d&#8217;octets. Cette même séquence peut ensuite être reconverti en l&#8217;objet original. Ce mécanisme est par exemple utilisé pour transmettre des objets par <a href="http://fr.wikipedia.org/wiki/Remote_method_invocation_(Java)">RMI</a>.</p>
<p>Voici une petite méthode pour vérifier que votre classe est bien sérialisable</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ByteArrayInputStream</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ByteArrayOutputStream</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ObjectInputStream</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ObjectOutputStream</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">junit</span>.<span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertEquals</span>;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">junit</span>.<span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">fail</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> <span style="color: #000000; font-weight: bold;">Assert</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Assert that an object is serializable by dumping it and then reading it
     * back and finally by checking the original object and the dumped and read
     * object are equals.
     *
     * &lt;p&gt;Obviously, the method &lt;code&gt;equals()&lt;/code&gt; has to be implemented
     * correctly for this method can work.
     * @param objOriginal the instance which will be checked against serialization;
     * must implement &lt;code&gt;equals()&lt;/code&gt; or it won't work
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> assertSerializable<span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> objOriginal<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">ByteArrayOutputStream</span> stream <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ByteArrayOutputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">ObjectOutputStream</span> out <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ObjectOutputStream</span><span style="color: #009900;">&#40;</span>stream<span style="color: #009900;">&#41;</span>;
            out.<span style="color: #006633;">writeObject</span><span style="color: #009900;">&#40;</span>objOriginal<span style="color: #009900;">&#41;</span>;
            out.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">ObjectInputStream</span> in <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ObjectInputStream</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ByteArrayInputStream</span><span style="color: #009900;">&#40;</span>stream.<span style="color: #006633;">toByteArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Object</span> objSerialized <span style="color: #339933;">=</span> in.<span style="color: #006633;">readObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
            assertEquals<span style="color: #009900;">&#40;</span>objOriginal, objSerialized<span style="color: #009900;">&#41;</span>;
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">IOException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unable to serialize or deserialize object &quot;</span> <span style="color: #339933;">+</span> objOriginal <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;: &quot;</span> <span style="color: #339933;">+</span> e.<span style="color: #006633;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">ClassNotFoundException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// unlikely to happen...</span>
            fail<span style="color: #009900;">&#40;</span>e.<span style="color: #006633;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><span id="more-84"></span>Cette méthode sérialise une classe dans un buffer, puis relit ce buffer et s&#8217;assure que l&#8217;objet lu est bien égal à l&#8217;objet sérialisé.</p>
<p>Si ce test échoue, alors c&#8217;est que certaines données membres de l&#8217;objet testé ne sont pas sérialisables. Par exemple, un <a href="http://www.slf4j.org/apidocs/org/slf4j/Logger.html">Logger</a> ou un <a href="http://java.sun.com/javase/6/docs/api/java/lang/Thread.html">Thread</a> ne peuvent pas être sérialisés. Des données membres de ce type doivent donc être déclarés <code>transient</code> de la manière suivante</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Foo <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">transient</span> <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Thread</span> thread;
    <span style="color: #000000; font-weight: bold;">transient</span> <span style="color: #000000; font-weight: bold;">private</span> Logger logger <span style="color: #339933;">=</span> LoggerFactory.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> name;
&nbsp;
    <span style="color: #666666; font-style: italic;">// etc...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Attention une fois l&#8217;objet sérialisé puis désérialisé, les membres transients sont perdus. C&#8217;est ainsi qu&#8217;on se retrouve avec un logger à <code>null</code> et un <code>NullPointerException</code> assez rapidement&#8230; Dans ce cas, on peut implémenter une méthode privée ayant la signature <code>readObject(ObjectInputStream)</code> pour y restaurer le logger. La méthode doit être privée pour éviter tout appel par une autre classe ou toute surcharge par une classe fille.</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;">    <span style="color: #666666; font-style: italic;">// code...</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> readObject<span style="color: #009900;">&#40;</span><span style="color: #003399;">ObjectInputStream</span> in<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">ClassNotFoundException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// default implementation</span>
        in.<span style="color: #006633;">defaultReadObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #666666; font-style: italic;">// restore our logger object</span>
        logger <span style="color: #339933;">=</span> LoggerFactory.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// code...</span></pre></div></div>

<p>Tout les détails de la sérialisation sont expliqués <a href="http://java.sun.com/developer/technicalArticles/Programming/serialization/">sur le site de Sun</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/02/assurer-la-serialisation-dun-objet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convertir un entier en binaire, the ruby way</title>
		<link>http://trux.info/2009/02/convertir-un-entier-en-binaire-the-ruby-way/</link>
		<comments>http://trux.info/2009/02/convertir-un-entier-en-binaire-the-ruby-way/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 20:59:20 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://trux.info/?p=76</guid>
		<description><![CDATA[Dans un article précédent, je donnais une méthode pour convertir rapidement un nombre en binaire et inversement quand on n&#8217;avait pas python 3. Ça m&#8217;est pratique quand j&#8217;ai besoin de faire une conversion rapide : un terminal, on lance python, on tape l&#8217;expression et on a le résultat. En regardant les nouveautés de ruby 1.8.7, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://trux.info/wp-content/uploads/2009/02/ruby-language.png" alt="ruby" title="ruby" width="89" height="101" class="alignleft size-full wp-image-77" /><a href="http://trux.info/2009/01/python-convertir-un-entier-en-binaire/">Dans un article précédent</a>, je donnais une méthode pour convertir rapidement un nombre en binaire et inversement quand on n&#8217;avait pas <a href="http://www.python.org/download/releases/3.0/">python 3</a>. Ça m&#8217;est pratique quand j&#8217;ai besoin de faire une conversion rapide : un terminal, on lance python, on tape l&#8217;expression et on a le résultat. En regardant <a href="http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS">les nouveautés de ruby 1.8.7</a>, j&#8217;ai découvert que c&#8217;était encore plus trivial.</p>
<pre>
% irb
irb(main):001:0> 42.to_s(2)
=> "101010"
irb(main):002:0> "%b" % 42
=> "101010"
irb(main):003:0> "1001".to_i(2)
=> 9
irb(main):004:0> 0b1001
=> 9
</pre>
<p>Enfantin non ?</p>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/02/convertir-un-entier-en-binaire-the-ruby-way/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Débuts avec zsh</title>
		<link>http://trux.info/2009/01/debuts-avec-zsh/</link>
		<comments>http://trux.info/2009/01/debuts-avec-zsh/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 19:56:09 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[zsh]]></category>

		<guid isPermaLink="false">http://trux.info/?p=62</guid>
		<description><![CDATA[zsh est un shell complet qui remplace avantageusement bash dont on entend beaucoup parler en bien. J&#8217;ai décidé de l&#8217;essayer récemment.
Sans chercher à exploiter toutes les fonctionnalités qu&#8217;il propose, certaines facilités me sont maintenant indispensables lorsque je passe à bash. Une seule en fait : le ** qui se substitue à n&#8217;importe quel dossier ou [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cooking2000.com/fr/dossier/coquille-saint-jacques.htm"><img alt="" src="http://www.cooking2000.com/image/dossier/divers/coquille-st-jacques.jpg" title="shell signifie aussi coquille, ici une St Jacques" class="alignright" width="200" height="257" /></a><code>zsh</code> est un <a href="http://fr.wikipedia.org/wiki/Shell_(informatique)">shell</a> complet qui remplace avantageusement <code>bash</code> dont on entend <a href="http://doc.ubuntu-fr.org/zsh">beaucoup parler</a> en bien. J&#8217;ai décidé de l&#8217;essayer récemment.</p>
<p>Sans chercher à exploiter toutes les fonctionnalités qu&#8217;il propose, certaines facilités me sont maintenant indispensables lorsque je passe à bash. Une seule en fait : le <code>**</code> qui se substitue à n&#8217;importe quel dossier ou sous-dossier. Un <a href="http://en.wikipedia.org/wiki/Glob_(programming)">globbing</a> puissant qui permet de s&#8217;affranchir de <a href="http://pwet.fr/man/linux/commandes/find">find</a>.</p>
<p><span id="more-62"></span></p>
<pre>
# liste tous les fichiers, equivalent de find .
ls **/*
# recherche la chaine 'foo' dans tous les fichiers java
grep foo **/*.java
# recherche la chaine 'bar' dans tous les fichiers java qui ont pour
# repertoire parent le dossier src
grep foo **/src/**/*.java
</pre>
<p>De plus, on peut ajouter des options de recherche</p>
<pre>
# tous les fichiers contenant le nom 'dupont' en Ignorant la casse
# correspond à dupond, DUPOND, Dupond, DuPOnD, mais pas Durand
ls (#i)dupont
# liste uniquement les fichiers
ls **/*(.)
# liste uniquement les dossiers
ls -d **/*(/)
# liste tous les dossiers pleins (Full)
ls -d **/*(F)
# liste tous les dossiers vides (not Full)
ls -d **/*(^F)
</pre>
<p>Il existe <a href="http://www.manpagez.com/man/1/zshexpn/">beaucoup d&#8217;autres possibilités</a>, mais juste ces quelques commandes m&#8217;ont permis de m&#8217;affranchir du sempiternel <code>find . -type f -iname "*dupont*" | xargs svn revert</code>.</p>
<p>L&#8217;autre truc bien de zsh, évidemment, c&#8217;est l&#8217;aide à la <a href="http://zsh.sourceforge.net/Guide/zshguide06.html">complétion de commande</a>. Il est remarquable dans bien des cas, notamment</p>
<ul>
<li>tâches ant : <code>$ ant &lt;TAB&gt;</code> => liste les tâches ant disponibles</li>
<li>arguments ant : <code>$ ant --n&lt;TAB&gt;</code> => liste les options de ant commençant par <i>&#8211;n</i></li>
<li>adresses svn : <code>$ svn checkout http://some.svn.server/svn/trunk/src/&lt;TAB&gt;</code> => liste les fichiers disponibles</li>
</ul>
<p>Bref ça vaut le coup d&#8217;essayer. Pour mettre un pied à l&#8217;étrier (et me servir d&#8217;aide mémoire), voici le <code>.zshrc</code> que j&#8217;utilise. Il n&#8217;a rien d&#8217;exceptionnel, même le prompt est des plus basiques.</p>
<pre>
# Lines configured by zsh-newuser-install
HISTFILE=~/.histfile
HISTSIZE=1000
SAVEHIST=1000
setopt appendhistory autocd extendedglob nomatch notify
unsetopt beep
bindkey -e
# End of lines configured by zsh-newuser-install
# The following lines were added by compinstall
zstyle :compinstall filename '/home/cbliard/.zshrc'

autoload -Uz compinit
compinit
# End of lines added by compinstall

# Add ~/bin directory to PATH if possible
[ -d $HOME/bin ] &#038;&#038; export PATH=$PATH:$HOME/bin

# colors
eval "`dircolors -b`"
alias ls='ls --color=auto'

function l() {
	clear; pwd; echo; ls -lh $*; echo
}

# Set up aliases
alias mv='nocorrect mv'       # no spelling correction on mv
alias cp='nocorrect cp'       # no spelling correction on cp
alias mkdir='nocorrect mkdir' # no spelling correction on mkdir
alias grep='egrep --exclude-dir=\.svn --color=auto'
alias ll='ls -l'
alias la='ls -a'
alias less='less -i'
alias diff='diff -u -x .svn'

# Less verbose ant
alias ant='ant -logger org.apache.tools.ant.NoBannerLogger'

# List only directories and symbolic
# links that point to directories
alias lsd='ls -ld *(-/DN)'

# List only file beginning with "."
alias lsa='ls -ld .*'

# Simple bold prompt
PROMPT="%{%B%}%n@%m:%~%{%b%}%# "

# select words as in bash (for Meta-backspace and Meta-d)
autoload -U select-word-style
select-word-style bash
</pre>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/01/debuts-avec-zsh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python : convertir un entier en binaire</title>
		<link>http://trux.info/2009/01/python-convertir-un-entier-en-binaire/</link>
		<comments>http://trux.info/2009/01/python-convertir-un-entier-en-binaire/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 20:50:36 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://trux.info/?p=53</guid>
		<description><![CDATA[Depuis python 2.6, le langage python peut gérer les nombres entier dans leur représentation binaire.

$ python2.6
>>> 0b101111
47
>>> int('1101', 2)
13
>>> int('0b1101', 2)
13
>>> bin(13)
'0b1101'

Cependant, avec les versions précédentes, seule la conversion de binaire vers décimal est possible facilement.

$ python2.5
>>> int('1101', 2)
13
>>> bin(13)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'bin' is not [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://docs.python.org/whatsnew/2.6.html#pep-3127-integer-literal-support-and-syntax">Depuis python 2.6</a>, le langage python peut gérer les nombres entier dans leur représentation binaire.</p>
<pre>
$ python2.6
>>> 0b101111
47
>>> int('1101', 2)
13
>>> int('0b1101', 2)
13
>>> bin(13)
'0b1101'
</pre>
<p>Cependant, avec les versions précédentes, seule la conversion de binaire vers décimal est possible facilement.</p>
<pre>
$ python2.5
>>> int('1101', 2)
13
>>> bin(13)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'bin' is not defined
</pre>
<p>Voici donc une petite fonction <code>bin</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> bin<span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Convert an integer to its binary string representation&quot;&quot;&quot;</span>
    res = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> n <span style="color: #66cc66;">&gt;</span> 0:
        res.<span style="color: black;">insert</span><span style="color: black;">&#40;</span>0, <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>n <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        n = n // <span style="color: #ff4500;">2</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span></pre></div></div>

<p>Et ainsi :</p>
<pre>
$ python2.5
>>> def bin(n):
...     """Convertit un nombre en binaire"""
...     res = []
...     while n > 0:
...         res.insert(0, str(int(n % 2)))
...         n = n // 2
...     return "".join(res)
...
>>> bin(13)
'1101'
>>> int(bin(13), 2)
13
</pre>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2009/01/python-convertir-un-entier-en-binaire/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Utiliser rubygems avec Netbeans sur Ubuntu grâce aux ACLs</title>
		<link>http://trux.info/2008/12/utiliser-rubygems-avec-netbeans-sur-ubuntu-grace-aux-acls/</link>
		<comments>http://trux.info/2008/12/utiliser-rubygems-avec-netbeans-sur-ubuntu-grace-aux-acls/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 08:00:06 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[acl]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://trux.info/?p=29</guid>
		<description><![CDATA[En installant rubygems et en l&#8217;utilisant avec Netbeans, on se rend vite compte que rubygems est configuré pour stocker ses gemmes dans /var/lib/gems et que Netbeans n&#8217;a pas les droits d&#8217;écriture à cet endroit. En effet, la manière traditionnelle d&#8217;installer gem implique d&#8217;utiliser sudo, en ligne de commande :
$ sudo gems install rails -y
Oui mais [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-32" title="netbeans_ruby_debian" src="http://trux.info/wp-content/uploads/2008/12/netbeans_ruby_debian.png" alt="" width="300" height="83" />En installant rubygems et en l&#8217;utilisant avec <a href="http://www.netbeans.org/">Netbeans</a>, on se rend vite compte que rubygems est configuré pour stocker ses gemmes dans <code>/var/lib/gems</code> et que Netbeans n&#8217;a pas les droits d&#8217;écriture à cet endroit. En effet, la manière traditionnelle d&#8217;installer gem implique d&#8217;utiliser sudo, en ligne de commande :</p>
<pre>$ sudo gems install rails -y</pre>
<p>Oui mais voilà, Netbeans n&#8217;utilise pas sudo. Pour que Netbeans puisse gérer les gemmes lui-même, il lui faut donc les droits d&#8217;écriture sur le dossier <code>/var/lib/gems</code> et ses sous-répertoires. Le plus naïf est de donner tous les droits en écriture, mais c&#8217;est mal ! Sinon, on peut aussi créer un groupe nommé <code>rubygems</code> et donner le droit d&#8217;écriture à ce groupe. Cette approche est meilleure mais un problème se pose lorsque l&#8217;utilisateur y crée un nouveau fichier ou dossier : non seulement celui-ci appartient à l&#8217;utilisateur et non pas à root, mais en plus le groupe n&#8217;a pas le droit d&#8217;écriture. C&#8217;est là qu&#8217;interviennent les ACLs&#8230;</p>
<p><span id="more-29"></span></p>
<h3>Démonstration avec l&#8217;utilisateur foo.</h3>
<p>On crée un groupe ruby gems et on s&#8217;y ajoute</p>
<pre>
$ sudo addgroup rubygems
$ sudo adduser foo rubygems
</pre>
<p>On se déconnecte puis reconnecte pour prendre en compte le nouveau groupe, puis on vérifie les permissions</p>
<pre>
$ sudo mkdir /test
$ sudo chgrp rubygems /test
$ sudo chmod g+w /test
$ ls -ld /test
drwxrwxr-x 2 root rubygems 4096 2008-12-03 22:16 /test
$ touch /test/bar
$ ls -l /test/bar
-rw-r--r-- 1 foo foo 0 2008-12-03 22:21 /test/bar
</pre>
<p>Ce n&#8217;est pas bon du tout. On préférerait avoir quelque chose comme <code>-rw-rw-r-- 1 foo rubygems</code> afin que les autres membres du groupe <code>rubygems</code> puissent eux aussi modifier ce fichier. De manière plus générale, on veut que :</p>
<ul>
<li>le groupe soit <code>rubygems</code> ;</li>
<li>les permissions du groupe soient rwx pour un dossier et rw- pour un fichier ;</li>
<li>et que les permissions des autres soient r-x pour un dossier et r&#8211; pour un fichier.</li>
</ul>
<p>La partie qui va suivre est issu des connaissances acquises grâce à l&#8217;article <a href="http://www.udel.edu/topics/os/unix/general/groupsharing.html">Group sharing a directory</a>.</p>
<h3>Attribuer le groupe automatiquement</h3>
<p>Il est simple d&#8217;affecter le groupe <code>rubygems</code> automatiquement à chaque nouveau dossier créé dès qu&#8217;on connait l&#8217;astuce : il suffit de lever le bit &#8217;set groupid&#8217; du groupe du dossier pour que tout nouveau fichier ou dossier créé appartienne au groupe du dossier parent plutôt qu&#8217;au groupe de l&#8217;utilisateur</p>
<pre>
$ sudo chmod g+s /test
$ ls -ld /test
drwxrwsr-x 2 root rubygems 4096 2008-12-05 07:54 /test
$ touch f
$ mkdir /test/d
$ ls -l /test
total 4
drwxr-sr-x 2 foo rubygems 4096 2008-12-05 07:59 d
-rw-r--r-- 1 foo rubygems    0 2008-12-05 07:59 f
$ cd /test/d
$ touch bar
$ ls -l
-rw-r--r-- 1 foo rubygems 0 2008-12-05 08:00 bar
</pre>
<h3>Permettre l&#8217;écriture au groupe automatiquement </h3>
<p>Cette solution fait usage des ACLs. La commande</p>
<pre>
$ sudo setfacl -m default:user::rwx,default:group::rwx,default:mask:rwx,default:other:r-x /test
</pre>
<p>permet de définir les permissions par défaut pour les futurs fichiers du dossier <code>/test</code>. La commande est longue et peut être abrégée en</p>
<pre>
$ sudo setfacl -m d:u::rwx,d:g::rwx,d:m:rwx,d:o:r-x /test
</pre>
<p>Si la commande <code>setfacl</code> ne fonctionne pas, c&#8217;est parce que l&#8217;option <code>acl</code> n&#8217;est pas active pour votre volume. Assurez-vous d&#8217;avoir une ligne qui ressemble contienne l&#8217;option <code>acl</code> dans votre <code>/etc/fstab</code> :</p>
<pre>
/dev/hda2 / ext3 defaults,acl 0 1
</pre>
<p>Ensuite remontez votre volume pour prendre en compte les modifications</p>
<pre>
sudo mount / -o remount
</pre>
<p>Observons maintenant d&#8217;un peu plus près la définition d&#8217;ACLs</p>
<pre>
$ sudo setfacl -m d:u::rwx,d:g::rwx,d:m:rwx,d:o:r-x /test
$ ls -ld /test
drwxrwsr-x+ 3 root rubygems 4096 2008-12-05 07:59 /test
$ getfacl /test
getfacl: Removing leading '/' from absolute path names
# file: test
# owner: root
# group: rubygems
user::rwx
group::rwx
other::r-x
default:user::rwx
default:group::rwx
default:mask::rwx
default:other::r-x
</pre>
<p>Le + à droite des permissions affichées par la commande <code>ls</code> indique qu&#8217;il y a des permissions supplémentaires visibles par <code>getfacl</code>. Ce dernier permet d&#8217;afficher les permissions définies avec <code>setfacl</code>. Essayons de créer des fichiers.</p>
<pre>
$ cd /test
$ touch polop.txt
$ mkdir hello
$ ls -l
total 16
drwxr-sr-x  2 foo rubygems 4096 2008-12-05 08:00 d
-rw-r--r--  1 foo rubygems    0 2008-12-05 07:59 f
drwxrwsr-x+ 2 foo rubygems 4096 2008-12-05 08:17 hello
-rw-rw-r--+ 1 foo rubygems    0 2008-12-05 08:17 polop.txt
$ getfacl hello
# file: hello
# owner: foo
# group: rubygems
user::rwx
group::rwx
mask::rwx
other::r-x
default:user::rwx
default:group::rwx
default:mask::rwx
default:other::r-x
</pre>
<p>Les ACLs ont bien rempli leur rôle : les nouveaux fichiers créés ont la permission d&#8217;écriture pour le groupe et ont aux aussi les ACLs définis (notez le +).</p>
<h3>Application au dossier de gemmes de ruby</h3>
<p>Il nous faut définir le groupe les permissions pour tout fichier ou dossier existant du dossier <code>/var/lib/gems</code> et les ACLs ainsi que le &#8217;set groupid&#8217; bit pour tout dossier, sans oublier de changer le groupe pour qu&#8217;il devienne <code>rubygems</code>.</p>
<pre>
$ sudo chgrp -R rubygems /var/lib/gems
$ sudo chmod -R -s,g=rwX,o=rX /var/lib/gems
$ for dir in $(find /var/lib/gems -type d) ; do
> sudo chmod g+s "$dir"
> sudo setfacl -m d:u::rwx,d:g::rwx,d:o:r--,d:m:rwx "$dir"
> done
</pre>
<p>notez que si vous étiez sous <a href="http://fr.wikipedia.org/wiki/Zsh">zsh</a>, vous auriez pu écrire</p>
<pre>
$ sudo chgrp rubygems /var/lib/gems/**/*
$ sudo chmod -s,g=rwX,o=rX /var/lib/gems/**/*
$ sudo chmod g+s /var/lib/gems/**/*(/)
$ sudo setfacl -m d:u::rwx,d:g::rwx,d:o:r--,d:m:rwx /var/lib/gems/**/*(/)
</pre>
<p>Voilà ! désomais vous pouvez taper</p>
<pre>
$ gems install rails -y
</pre>
<p>en simple utilisateur, ce qui signifie que d&#8217;autres programmes tiers comme NetBeans peuvent également installer des gemmes.</p>
<h3>Autres applications</h3>
<p>On peut trouver d&#8217;autres application très utiles au partage de dossier par ACL. Comme ça de tête :</p>
<ul>
<li>Quand votre serveur web est partagé entre plusieurs personnes, partager le dossier <code>/var/www</code> d&#8217;apache pour que l&#8217;utilisateur système <code>www-data</code> ait le droit d&#8217;écriture sur tous les fichiers sans donner ces droits à tout le monde ;</li>
<li>Partager des fichiers sur un disque dur externe pour que chacun puisse y gérer ses films et photos sans se retrouver bloqué quand on veut déplacer ou supprimer certains éléments créés par d&#8217;autres utilisateurs.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2008/12/utiliser-rubygems-avec-netbeans-sur-ubuntu-grace-aux-acls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accéder à tous vos dépôts debian malgré les proxy</title>
		<link>http://trux.info/2008/11/acceder-a-tous-vos-depots-debian-malgre-les-proxy/</link>
		<comments>http://trux.info/2008/11/acceder-a-tous-vos-depots-debian-malgre-les-proxy/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 07:20:53 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://trux.info/?p=3</guid>
		<description><![CDATA[S&#8217;il vous est déjà arrivé d&#8217;avoir à accéder à des dépôts debian placés derrière un proxy, vous pouvez utiliser un outil graphique comme Synaptics qui permet de configurer ça assez facilement. Si vous êtes pluto adepte de la ligne de commande, vous avez alors à modifier les fichiers de configuration d&#8217;apt.

sudo echo 'Acquire::http::Proxy "http://proxy.mynetwork.com:1234/";' &#62; [...]]]></description>
			<content:encoded><![CDATA[<p>S&#8217;il vous est déjà arrivé d&#8217;avoir à accéder à des dépôts debian placés derrière un proxy, vous pouvez utiliser un outil graphique comme <a href="http://www.nongnu.org/synaptic/">Synaptics</a> qui permet de configurer ça assez facilement. Si vous êtes pluto adepte de la ligne de commande, vous avez alors à modifier les fichiers de configuration d&#8217;apt.</p>
<pre>
sudo echo 'Acquire::http::Proxy "http://proxy.mynetwork.com:1234/";' &gt; /etc/apt/apt.conf.d/proxy
</pre>
<p>ou plus simplement en définissant les paramètres du proxy dans la variable d&#8217;environnement <code>http_proxy</code> (ou <code>ftp_proxy</code> dans le cas d&#8217;un miroir ftp).</p>
<pre>
export http_proxy='http://proxy.mynetwork.com:1234/'
</pre>
<p>Si le proxy est un proxy authentifiant, alors il faut également préciser le login et le mot de passe dans <code>http_proxy</code>.</p>
<pre>
export http_proxy='http://login:pwd@proxy.mynetwork.com:1234/'
</pre>
<p>Évidemment, si vous avez un dépôt debian miroir sur votre réseau interne, vous n&#8217;avez pas besoin de définir tout ça. Cependant, si vous voulez également accéder aux dépôts externes, c&#8217;est là que ça se complique : si vous définissez <code>http_proxy</code>, le dépôt interne devient inaccessible car apt tente de passer par le proxy, et si vous ne le définissez pas, les depôts externes sont inaccessibles car vous ne passez plus par le proxy. Il faut donc procéder autrement.</p>
<p><span id="more-3"></span><br />
Une solution est d&#8217;utiliser la variable <code>no_proxy</code>. Cette variable définit les hôtes qui ne nécessitent pas un accès via proxy.</p>
<p>Par exemple</p>
<pre>
export no_proxy='127.0.01,.mynetwork.com,192.168.78.100'
</pre>
<p>n&#8217;utilisera pas le proxy pour accéder à 127.0.0.1, à n&#8217;importe quel hôte du domaine mynetwork.com ou à 192.168.78.100. Attention, l&#8217;utilisation de wildcards dans <code>no_proxy</code> ne fonctionnera pas. Ainsi écrire ce qui suit n&#8217;empêchera pas d&#8217;essayer d&#8217;utiliser le proxy pour accéder à wiki.mynetwork.com.</p>
<pre>
# wildcards dont work
export no_proxy='127.0.01,*.mynetwork.com'
</pre>
<p>Définir <code>http_proxy</code> et <code>no_proxy</code> dans <code>$HOME/.bashrc</code> permettra donc d&#8217;accéder à n&#8217;importe quel dépôt, qu&#8217;il soit sur le réseau interne ou à l&#8217;extérieur. Prenons l&#8217;exemple de deux dépôts, l&#8217;un sur l&#8217;hôte deb.mynetwork.com, l&#8217;autre sur l&#8217;hôte fr.archive.ubuntu.com. Il faut définir</p>
<pre>
export http_proxy='http://login:pwd@proxy.mynetwork.com:1234/'
export no_proxy='127.0.01,deb.mynetwork.com'
</pre>
<p>Mais si vous utilisez <code>sudo apt-get</code> pour installer un paquet, ça ne fonctionne toujours pas. C&#8217;est parce que <a href="http://aplawrence.com/Basics/sudo.html">sudo filtre les variables d&#8217;environnement</a> pour des raisons de sécurité. Pour constater quelles variables sont filtrées et comment :</p>
<pre>
sudo sudo -V
</pre>
<p>On y voit que la variable <code>http_proxy</code> est préservée, mais pas <code>no_proxy</code>. Pour y remédier, il va falloir éditer le fichier <code>/etc/sudoers</code>.</p>
<pre>
sudo visudo
</pre>
<p>et rajouter la ligne suivante</p>
<pre>
Defaults        env_keep+="no_proxy"
</pre>
<p>Attention à bien mettre des double-quotes et non des simple-quotes.</p>
<p>Si vous êtes sous <a href="http://www.ubuntu-fr.org/">Ubuntu</a>, le fichier devrait ressembler à ça</p>
<pre>
# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
# Host alias specification

# User alias specification

# Cmnd alias specification

# Defaults

Defaults        env_keep+='no_proxy'
Defaults        !lecture,tty_tickets,!fqdn

# User privilege specification
root    ALL=(ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
</pre>
<p>Ainsi, vous pouvez installer des paquets provenant de votre réseau local ou de l&#8217;extérieur.</p>
<p>L&#8217;avantage de cette solution, c&#8217;est qu&#8217;elle est valable pour tous les programmes : par exemple l&#8217;installation du paquet msttcorefonts va télécharger les polices true type microsoft sur le net en utilisant <code>wget</code>. Si vous êtes derrière un proxy et qu&#8217;aucun proxy n&#8217;est défini dans le fichier $HOME/.wgetrc, le fichier /etc/wgetrc ou dans la variable d&#8217;environnement http_proxy, le téléchargement échouera. En définissant la variable d&#8217;environnement <code>http_proxy</code> ça fonctionne comme un charme.</p>
<p>Petite astuce supplémentaire, si votre proxy requiert une authentification, vous n&#8217;avez pas envie que tout le monde connaisse votre mot de passe en regardant votre <code>.bashrc</code>.</p>
<p>Une solution est de mettre la définition dans un fichier <code>$HOME/.proxy</code> puis de l&#8217;appeler depuis le bashrc.</p>
<p>fichier <code>$HOME/.proxy</code></p>
<pre>
#!/bin/bash
# proxy settings
export http_proxy='http://login:pwd@proxy.mynetwork.com:1234/'
export no_proxy='127.0.01,deb.mynetwork.com'
</pre>
<p>changer les droits d&#8217;accès et modifier son bashrc</p>
<pre>
chmod go-rw $HOME/.proxy
echo 'source $HOME/.proxy' &gt; $HOME/.bashrc
</pre>
]]></content:encoded>
			<wfw:commentRss>http://trux.info/2008/11/acceder-a-tous-vos-depots-debian-malgre-les-proxy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
