<?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>TuXxX Blog</title>
	<atom:link href="http://blog.pepita.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://blog.pepita.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 02 Aug 2010 15:38:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Les Conteneurs Linux</title>
		<link>http://blog.pepita.org/?p=260</link>
		<comments>http://blog.pepita.org/?p=260#comments</comments>
		<pubDate>Mon, 02 Aug 2010 15:31:26 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Virtualisation]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=260</guid>
		<description><![CDATA[Petite révolution dans la demeure, je vais encore chambouler notre architecture domestique. En effet, puisqu&#8217;aujourd&#8217;hui je travaille exclusivement dans mon garage (le vieux rêve que voilà -;), je n&#8217;ai plus le courage d&#8217;éteindre la bête de course qui me sert de poste de travail. Du coup, le petit serveur miniITX a perdu sa raison d&#8217;être [...]]]></description>
			<content:encoded><![CDATA[<p>Petite révolution dans la demeure, je vais <em>encore</em> chambouler <a href="http://artisan.karma-lab.net/node/1310" target="_blank">notre architecture domestique</a>. En effet, puisqu&#8217;aujourd&#8217;hui je travaille exclusivement dans mon garage (le vieux rêve que voilà -;), je n&#8217;ai plus le courage d&#8217;éteindre la bête de course qui me sert de poste de travail. Du coup, le <a href="http://artisan.karma-lab.net/node/1327" target="_blank">petit serveur miniITX</a> a perdu sa raison d&#8217;être et l&#8217;envie m&#8217;a pris de la virtualiser sur la grosse bête. Quoi de plus logique au fond, tant qu&#8217;à consommer des watts, autant que cela soit le plus rentable possible.<span id="more-260"></span></p>
<p>Malgré tout, virtualiser &#8220;à la KVM, XEN ou VirtualBox&#8221; ne me plaisait pas des masses. Trop lourd pour le besoin. Quant à chrooter tout cela, pas assez fiable. C&#8217;est alors qu&#8217;un ami (coucou Daniel) m&#8217;a suggéré la solution OpenVZ. Ce n&#8217;est finalement pas elle que je vais mettre ici en oeuvre mais c&#8217;est ainsi que j&#8217;ai mis le doigt sur un concept de super-chroot alliant isolation et performance.</p>
<p><a name="chapter_1"></a></p>
<h2>Hôte, conteneur, isolation et performances</h2>
<p><a rel="lightbox" href="http://artisan.karma-lab.net/files/artisan1749/vps.jpg"></a></p>
<div><a rel="lightbox" href="http://artisan.karma-lab.net/files/artisan1749/vps.jpg"><img src="http://artisan.karma-lab.net/files/artisan/imagecache/illustration/1749/vps.jpg" alt="" width="200" height="129" /></a></div>
<p>La virtualisation est un vaste et complexe sujet (que je ne maîtrise pas !). Mais au fond, cela revient à une chose simple permettre de faire fonctionner un (ou plusieurs) système d&#8217;exploitation (et/ou des applications) comme s&#8217;il était sur sa propre machine, alors qu&#8217;en réalité il tourneau sein d&#8217;un système d&#8217;exploitation hôte. Et pour arriver à ce résultat, il y a en gros trois approches :</p>
<p><br class="spacer_" /></p>
<ul>
<li><strong>La virtualisation par isolation -</strong> cela consiste à mettre en place des contextes permettant de redéfinir ce que voit le conteneur. C&#8217;est typiquement ce que fait chroot qui cache la racine réelle du serveur pur ne montrer aux processus enfant qu&#8217;une partie de l&#8217;arborescence. C&#8217;est aussi ce que font de manière beaucoup plus complète OpenVZ, VServer ou encore les zones d&#8217;OpenSolaris.</li>
<li><strong>La machine virtuelle -</strong> le principe est d&#8217;émuler un ensemble de matériel (carte réseau, carte écran, disque dur, etc) pour faire croire à l&#8217;OS du conteneur qu&#8217;il évolue sur une véritable machine. Si celui-ci est compilé pour le même processeur que la machine physique, il est possible de faire l&#8217;économie de l&#8217;émulation du processeur, ce qui apporte un énorme gain de temps. C&#8217;est ce que permettent KVM, le couple Qemu/Kquemu ou encore VirtualBox. Si l&#8217;OS est prévu pour un autre processeur, alors il faut aussi l&#8217;émuler comme le permet Qemu-ARM, Bochs, les émulateurs de console, etc.</li>
<li><strong>La paravirtualisation -</strong> (ou hyperviseur) qui tente de ménager la chèvre et le choux en modifiant utilisant des OS conteneur qui ont &#8220;conscience&#8221; d&#8217;être hébergé chez un hôte, ce qui permet de jouer tantôt de l&#8217;isolation, tantôt de la virtualisation. C&#8217;est typiquement ce que permet XEN (et UML il me semble).</li>
</ul>
<p>Finalement, ce que l&#8217;on peut en déduire à notre niveau, c&#8217;est que plus l&#8217;isolation entre le conteneur et l&#8217;hôte est forte, plus la partie logicielle qui va gérer le conteneur est complexe, et de manière incidente, plus les performances au sein du conteneur s&#8217;éloignent d&#8217;un système natif. Chroot étant d&#8217;un côté du spectre avec une très faible isolation mais des performances natives, à qemu-arm, totalement isolé mais avec de bien moindre performances.</p>
<p><a name="chapter_2"></a></p>
<h2>Un Chroot totalement isolé</h2>
<p>Pour commencer, un point très important à noter, les considérations de sécurité <strong>ne sont pas le sujet de ce papier</strong>. Et cela tombe bien car un chroot est tout sauf sécurisé. Cela passe très bien pour l&#8217;enfermement d&#8217;une poignée de services, mais cela deviendrait critique pour le chrootage d&#8217;un OS complet. En effet, le conteneur chrooté partage son <kbd>/proc</kbd> et son <kbd>/dev</kbd> avec l&#8217;hôte, et il a donc tout liberté pour s&#8217;introduire dans le système. Libertés que nous allons grandement restreindre mais je ne donne aucune garanti sur la résistance à l&#8217;intrusion.</p>
<p>Mais au delà des considérations de sécurité, un conteneur chroot, de par sa faible isolation, n&#8217;est pas pratique du tout dés qu&#8217;il s&#8217;agit de faire tourner plein de services dedans. En effet, si le système de fichier du conteneur est correctement isolé, il n&#8217;en est pas de même pour les processus (le conteneur &#8220;voit&#8221; ceux de l&#8217;hôte). Enfin concernant les interfaces réseau, il est bien évidement possible de créer un bridge ou un alias utilisé par l&#8217;environnement chrooté mais nombre de services deviennent de véritables empoisonneurs dés qu&#8217;il s&#8217;agit de les obliger à écouter une seule interface (ex. typiquement les RPC comme NFS ou YP). L&#8217;idéal serait donc de pouvoir disposer d&#8217;un chroot à géométrie variable, capable de disposer, au minimum, de son propre contexte processus et réseau.</p>
<p>Ce type de chroot est l&#8217;équivalent des zones de <a href="http://en.wikipedia.org/wiki/Solaris_Containers" target="_blank">Solaris</a> ou les <a href="http://fr.wikipedia.org/wiki/BSD_Jail" target="_blank">Jails de BSD</a>. Dans l&#8217;univers Linux il existe plusieurs possibilités allant dans ce sens avec des outils comme <a href="http://wiki.openvz.org/Main_Page" target="_blank">OpenVZ</a> ou Linux <a href="http://linux-vserver.org/Welcome_to_Linux-VServer.org" target="_blank">VServer</a>. Mais ces solutions ont un inconvénient de taille, ils ne fonctionnent qu&#8217;avec un patch du kernel et ont toujours un bon nombre de versions de retard. Ce ne serait pas un problème si de nos jours, certains outils aussi idiots qu&#8217;indispensables (udev pour ne pas le nommer) n&#8217;avaient pas le mauvais goût de fonctionner en user-land (où il n&#8217;a rien à foutre à mon sens) et donc imposer des versions récentes de kernel (c&#8217;est encore le cas récemment avec la dernière version d&#8217;udev qui impose un kernel 2.6.26, ou plus, à cause d&#8217;un appel à sa nouvelle fonction <kbd>signalfs</kbd>).</p>
<p><a name="chapter_3"></a></p>
<h2>Linux Containers</h2>
<p>Fort heureusement, une nouvelle solution commence à pointer le bout de son nez sous le nom de Linux Containers (ou LXC). Il s&#8217;agit là d&#8217;un jeu de nouvelles options dans le kernel qui ont la particularité d&#8217;être intégré en mainstream. Cela comprend un ensemble d&#8217;isolateurs (ou namespace) et cgroup (pour <a href="http://libcg.sourceforge.net/" target="_blank">control group file system</a>) permettant de contrôler de manière unifiée un jeu de processus et leurs enfants. Les isolateurs ajoutés sont nombreux et fonctionnent comme chroot pour la racine :</p>
<ul>
<li><a href="http://lwn.net/Articles/179345/" target="_blank">UTS namespace</a> qui permet d&#8217;avoir pour chaque conteneur son propre <kbd>hostname</kbd>/<kbd>domainame</kbd> distinct de celui de l&#8217;hôte.</li>
<li><a href="http://lkml.org/lkml/2006/6/9/121" target="_blank">IPC Namespace </a> qui permet d&#8217;avoir pour chaque conteneur son jeu privé de fonctions <kbd>sem</kbd>, <kbd>shm</kbd>, <kbd>msg</kbd>, etc.</li>
<li><a href="http://lwn.net/Articles/237662/" target="_blank">User Namespace</a> qui permet d&#8217;avoir par conteneur des utilisateurs de l&#8217;hôte distinct (y compris root !!), même s&#8217;ils partagent le même UID/GID. </li>
<li><a href="http://lwn.net/Articles/259217/" target="_blank">PID Namespace</a> &#8211; un apport énorme sur chroot, permettant au conteneur de disposer de sa propre liste de processus. Les processus host ne sont donc plus visible du conteneur.</li>
<li><a href="http://lxc.sourceforge.net/network.php" target="_blank">Network namespace</a> &#8211; la aussi une avancée très importante permettant au conteneur de disposer de ses propres interfaces réseaux (y compris localhost!). </li>
</ul>
<p>L&#8217;ensemble de ces fonctionnalités (namespaces et cgroup) permet de créer relativement facilement un super-chroot beaucoup plus isolant que la version d&#8217;origine. C&#8217;est ce que cherche à obtenir le projet <a href="http://lxc.sourceforge.net/" target="_blank">Linux Containers</a>. Ce dernier fournit une batterie de nouvelles commandes qui à partir d&#8217;une simple racine (identique à celle utilisée pour un chroot), permettent de créer, démarrer, arrêter ou encore monitorer un conteneur.</p>
<p>Maintenant que nous avons la théorie en tête passons à la pratique.</p>
<p><a name="chapter_4"></a></p>
<h2>Préparation de la machine hôte</h2>
<h3>Le kernel</h3>
<p>L&#8217;utilisation du nouveau système de serveurs virtuels privés implique l&#8217;activation d&#8217;un certains nombre d&#8217;options dans le noyau. S&#8217;agissant de la distribution Mandriva, les paquets appelés <kbd>kernel-server</kbd> ont déjà ces options d&#8217;activées, il n&#8217;y a donc aucun noyau à recompiler si vous les utilisez. Pour les autres, vous devez tout d&#8217;abord ajouter le contrôle par groupe.</p>
<blockquote>
<div>General setup &#8212;<span>&gt;</span><br />
 <span>[</span><span>*</span><span>]</span> Group CPU scheduler<br />
 <span>[</span><span>*</span><span>]</span> Group scheduling <span>for</span> SCHED_OTHER<br />
 <span>[</span>_<span>]</span> Group scheduling <span>for</span> SCHED_RR<span>/</span>FIFO<br />
 Basis <span>for</span> grouping tasks <span>(</span>Control <span>groups</span><span>)</span><br />
 <span>(</span>X<span>)</span> Control <span>groups</span></p>
<p><br class="spacer_" /></p>
<p><span>[</span><span>*</span><span>]</span> Control Group support  &#8212;<span>&gt;</span> <br />
 <span>[</span> <span>]</span> Example debug cgroup subsystem<br />
 <span>[</span><span>*</span><span>]</span> Namespace cgroup subsystem<br />
 <span>[</span><span>*</span><span>]</span> Freezer cgroup subsystem<br />
 <span>[</span><span>*</span><span>]</span> Device controller <span>for</span> cgroups<br />
 <span>[</span><span>*</span><span>]</span> Cpuset support<br />
 <span>[</span><span>*</span><span>]</span> Include legacy <span>/</span>proc<span>/</span> <span>/</span>cpuset <span>file</span><br />
 <span>[</span><span>*</span><span>]</span> Simple CPU accounting cgroup subsystem<br />
 <span>[</span><span>*</span><span>]</span> Resource counters<br />
 <span>[</span><span>*</span><span>]</span> Memory Resource Controller <span>for</span> Control Groups<br />
 <span>[</span><span>*</span><span>]</span> Memory Resource Controller Swap Extension<span>(</span>EXPERIMENTAL<span>)</span></p>
</div>
<div>Activation du contrôle par groupe dans le kernel</div>
</blockquote>
<p>Ensuite vous devez activer la prise en charge des espaces de nom :</p>
<blockquote>
<div>General setup &#8212;<span>&gt;</span> <br />
 <span>[</span><span>*</span><span>]</span> Namespaces support   <br />
 <span>[</span><span>*</span><span>]</span> UTS namespace  <br />
 <span>[</span><span>*</span><span>]</span> IPC namespace  <br />
 <span>[</span><span>*</span><span>]</span> User namespace <span>(</span>EXPERIMENTAL<span>)</span> <br />
 <span>[</span><span>*</span><span>]</span> PID Namespaces <span>(</span>EXPERIMENTAL<span>)</span> <br />
 <span>[</span><span>*</span><span>]</span> Network namespace</div>
<div>Activation des namespaces dans le kernel</div>
</blockquote>
<p>Vous n&#8217;avez plus qu&#8217;à recompiler le noyau et à démarrer dessus.</p>
<h3>Montage de cgroup</h3>
<p><kbd>cgroup</kbd> est un psoeudo système de fichier, comme <kbd>proc</kbd> ou feu <kbd>udevfs</kbd>. Pour l&#8217;utiliser, vous devez donc créer un dossier sur lequel ce système sera monté. Pour automatiser cela, nous allons ajouter ce montage à <kbd>fstab</kbd>.</p>
<blockquote>
<div>
<div><span>root#</span>mkdir /cgroup</div>
<div><span>root#</span>echo &#8220;none    /cgroup cgroup rw 0 0&#8243; &gt;&gt; /etc/fstab</div>
<div><span>root#</span>mount /cgroup</div>
</div>
<div>montage du psoeudo filesystem cgroup</div>
</blockquote>
<h3>Mise en place du réseau</h3>
<p>Là c&#8217;est la partie un peu &#8220;touchy&#8221; de l&#8217;histoire. En effet, chacun de nos conteneurs va à terme disposer de sa propre adresse IP. Il va donc nous falloir créer autant d&#8217;interface ethernet virtuels (veth) que de conteneur. Ensuite nous allons relier ces interfaces à un bridge. Le rôle du bridge va être de faire circuler l&#8217;information et peut être vu comme une sorte de switch.</p>
<p>Enfin, lorsque nous avons nos interfaces virtuelles connectés au bridge, il faudra encore y connecter l&#8217;interface physique de l&#8217;hôte (eth0) et assigner l&#8217;ancienne adresse IP ce cet interface au bridge lui-même. A partir de là notre switch virtuel est fonctionnel.</p>
<p>Ça c&#8217;est la théorie, et pour une fois la pratique est un peu plus simple. La seule chose que nous allons devoir faire est de créer le bridge et d&#8217;y associer l&#8217;interface physique. Les interfaces virtuels seront créés, connectés et paramétrés automatiquement lors du démarrage du conteneur correspondant.</p>
<p>Pour mettre en place le bridge, vous devez installer le paquet <kbd>bridge-tools</kbd> qui nous fournit, entre autre, la commande <kbd>brctl</kbd>. La création manuelle se passerait comme ceci :</p>
<blockquote>
<div>
<div># Création du bridge nommé br0</div>
<div><span>root#</span>brctl addbr br0</div>
<div># Paramétrage du bridge, ici nous réglons à 0 le délai de transfert (Forward Delay)</div>
<div><span>root#</span>brctl setfd br0 0</div>
<div># Ajout de l&#8217;interface physique au bridge</div>
<div><span>root#</span>brctl addif br0 eth0</div>
<div># On vide l&#8217;adresse IP de l&#8217;interface physique (remplacez eth0 par votre propre interface) &#8230;</div>
<div><span>root#</span>ifconfig eth0 0.0.0.0</div>
<div># &#8230; pour l&#8217;assigner au bridge (changer l&#8217;IP pour l&#8217;IP de votre host)</div>
<div><span>root#</span>ifconfig br0 10.0.0.1</div>
<div># Ajout d&#8217;une route pour que le bridge communique avec votre routeur (adresse à change pour vos besoins)</div>
<div><span>root#</span>route add -net default gw 10.0.0.100 br0</div>
</div>
<div>Création manuelle d&#8217;un bridge</div>
</blockquote>
<p>Voilà, c&#8217;est tout. Normalement, vous devez pouvoir pinger le monde extérieur et de l&#8217;extérieur pouvoir pinger votre host. Ceci étant dit, ça va être vite galère de faire cela à chaque fois. Chaque distribution permet d&#8217;automatiser ce genre de montage et sous Mandriva cela se fait simplement en commençant par arrêter le réseau (<kbd>service network stop</kbd>) puis en recopiant <kbd>/etc/sysconfig/network-scripts/ifcfg-eth0</kbd> vers /etc/<kbd>sysconfig/network-scripts/ifcfg-zbr0</kbd>. Notez le &#8220;z&#8221; devant le &#8220;br0&#8243; qui est une astuce stupide pour que cet interface se monte après <kbd>eth0</kbd>. Ceci fait, modifiez <kbd>ifcfg-eth0</kbd> pour qu&#8217;il commence comme ceci :</p>
<blockquote>
<div><span>DEVICE=</span>eth0<br />
 <span>BRIDGE=</span>br0<br />
 <span>BOOTPROTO=</span>static<br />
 <span>IPADDR=</span><span>0.0</span><span>.0</span><span>.0</span><br />
 <span>NETMASK=</span><span>255.255</span><span>.255</span><span>.0</span><br />
 <span>GATEWAY=</span><span>0.0</span><span>.0</span><span>.0</span><br />
 <span>ONBOOT=</span>yes</div>
<div>Script de paramétrage de l&#8217;interface réseau physique</div>
</blockquote>
<p>Puis modifier <kbd>ifcfg-zbr0</kbd> pour qu&#8217;il commence comme cela :</p>
<blockquote>
<div><span>DEVICE=</span>br0<br />
 <span>TYPE=</span>bridge<br />
 <span>DELAY=</span><span>0</span><br />
 <span>STP=</span>off<br />
 <span>BOOTPROTO=</span>static<br />
 <span>IPADDR=</span><span>10.0</span><span>.0</span><span>.1</span><br />
 <span>NETMASK=</span><span>255.255</span><span>.255</span><span>.0</span><br />
 <span>GATEWAY=</span><span>10.0</span><span>.0</span><span>.100</span><br />
 <span>DNS1=</span><span>212.27</span><span>.40</span><span>.240</span><br />
 <span>ONBOOT=</span>yes</div>
<div>Script de paramétrage du bridge</div>
</blockquote>
<p>Pour que cela fonctionne chez vous, vous devez bien évidement changer l&#8217;adresse de la passerelle (<kbd>GATEWAY</kbd>) et du serveur de nom (<kbd>DNS1</kbd>). Vous n&#8217;avez maintenant plus qu&#8217;à redémarrer le réseau (<kbd>service network restart</kbd>) et à tester comme précédemment pour voir si tout répond correctement. Le mieux est même de redémarrer la machine pour être certain que le montage est reproductible. Vous devriez ainsi obtenir les traces suivantes :</p>
<blockquote>
<div>
<div><span>root#</span>ifconfig</div>
<div>br0       Link encap:Ethernet  HWaddr 00:1A:4D:5C:9A:04</div>
<div>inet adr:10.0.0.1  Bcast:10.0.0.255  Masque:255.255.255.0</div>
<div>UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1</div>
<div>RX packets:11105 errors:0 dropped:0 overruns:0 frame:0</div>
<div>TX packets:11398 errors:0 dropped:0 overruns:0 carrier:0</div>
<div>collisions:0 lg file transmission:0</div>
<div>RX bytes:6019978 (5.7 MiB)  TX bytes:1566064 (1.4 MiB)</div>
<div>eth0      Link encap:Ethernet  HWaddr 00:1A:4D:5C:9A:04</div>
<div>UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1</div>
<div>RX packets:2683832 errors:0 dropped:0 overruns:0 frame:0</div>
<div>TX packets:2128799 errors:0 dropped:0 overruns:0 carrier:0</div>
<div>collisions:0 lg file transmission:1000</div>
<div>RX bytes:3418220009 (3.1 GiB)  TX bytes:1255231891 (1.1 GiB)</div>
<div>Interruption:28 Adresse de base:0&#215;6000</div>
<div><span>root#</span>route</div>
<div>Table de routage IP du noyau</div>
<div>Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface</div>
<div>10.0.0.0        *               255.255.255.0   U     0      0        0 br0</div>
<div>link-local      *               255.255.0.0     U     1262   0        0 br0</div>
<div>default         10.0.0.100      0.0.0.0         UG    10     0        0 br0</div>
</div>
<div>Preuve de fonctionnement du bridge</div>
</blockquote>
<h3>Lutter contre uDev</h3>
<p>Dans la majorité des distributions &#8220;modernes&#8221;, <kbd>udev</kbd> prend en charge la détection des nouvelles interfaces réseau pour passer la main à un outil de paramétrage. Pour la Mandriva, cet outil va chercher à détecter la présence d&#8217;un script de configuration pour cette interface et le cas échéant en créer un. Ensuite il va donner la main à <kbd>ifplugd</kbd> pour que ce dernier monitore l&#8217;interface et le paramètre à l&#8217;aide du script lorsqu&#8217;il détectera son activité (link beat).</p>
<p>Ceci est très bien dans la majorité des cas mais bien ennuyeux concernant nos futures conteneurs. En effet, comme nous l&#8217;avons vu, LXC va créer automatiquement une interface ethernet virtuelle qu&#8217;il va rattacher au bridge. Comme pour l&#8217;interface physique, elle ne devra pas avoir d&#8217;adresse IP au niveau de l&#8217;hôte (elle en aura une au niveau du conteneur). Pour corser le tout, LXC nomme l&#8217;interface virtuelle <kbd>veth_XXXXX</kbd>, où <kbd>XXXX</kbd> est le pid du processus racine du conteneur. Du coup, udev va flanquer tout cela par terre et appelant la procédure de configuration automatique qui va créer un script pour chaque interface créée, c&#8217;est à dire à chaque redémarrage du conteneur (normal, le pid est à chaque fois différent). Et comme il n&#8217;a aucune information sur cette interface, la procédure va aller au plus simple en lui affectant une recherche d&#8217;IP via DHCP. Ifplug va récupérer cela et reconfigurer l&#8217;interface virtuelle avec l&#8217;IP que lui donnera un DHCP du réseau, ce qui va la déconnecter du bridge.</p>
<p>Pour régler ce problème, il faut paramétrer uDev pour ignorer les interfaces de type veth. Pour cela, il faut aller dans <kbd>/lib/udev/rules.d/76-net.rules</kbd> (cela peut varier d&#8217;une distro à l&#8217;autre) et ajouter la ligne sur veth suivante :</p>
<blockquote>
<div>SUBSYSTEM<span>!</span>=<span>&#8220;net&#8221;</span>, <span>GOTO=</span><span>&#8220;mdv_net_end&#8221;</span><br />
 ENV<span>{</span>INTERFACE<span>}</span>==<span>&#8220;&#8221;</span>, <span>GOTO=</span><span>&#8220;mdv_net_end&#8221;</span><br />
 <span>KERNEL=</span>=<span>&#8220;veth*&#8221;</span>, <span>GOTO=</span><span>&#8220;mdv_net_end&#8221;</span></p>
<p><br class="spacer_" /></p>
<p><span>ACTION=</span>=<span>&#8220;add&#8221;</span>, RUN+=<span>&#8220;net_create_ifcfg&#8221;</span><br />
 <span>ACTION=</span>=<span>&#8220;add|remove&#8221;</span>, RUN+=<span>&#8220;net_action&#8221;</span></p>
<p><span>LABEL=</span><span>&#8220;mdv_net_end&#8221;</span></p>
</div>
<div>Paramétrage d&#8217;uDev</div>
</blockquote>
<p>Ceci fait, un petit coup de <kbd>pkill udevd</kbd>, <kbd>udevd -d</kbd> pour relancer, et le problème devra être réglé. Nous vérifierons cela un peu plus loin.</p>
<h3>Récupération des outils Linux Containers</h3>
<p>Comme dit plus haut, le nouveau système Linux Containers dispose d&#8217;une série d&#8217;outils user-land permettant de gérer les conteneurs. Si vous avez déjà cela en paquet dans votre distribution, installez-le, sinon, il suffit d&#8217;aller les chercher et les compiler :</p>
<blockquote>
<div>
<div>#git clone git://lxc.git.sourceforge.net/gitroot/lxc/lxc</div>
<div>&#8230;</div>
<div>#cd lxc</div>
<div>#./autogen</div>
<div>&#8230;</div>
<div>#./configure &#8211;prefix=</div>
<div>&#8230;</div>
<div>#make</div>
<div>&#8230;</div>
<div>#make install</div>
<div>&#8230;</div>
<div>#ls /bin/lxc-*</div>
<div>/bin/lxc-cgroup* /bin/lxc-console* /bin/lxc-destroy* /bin/lxc-freeze* /bin/lxc-monitor* /bin/lxc-restart* /bin/lxc-start* /bin/lxc-unshare*</div>
<div>/bin/lxc-checkconfig* /bin/lxc-create* /bin/lxc-execute* /bin/lxc-info* /bin/lxc-netstat* /bin/lxc-setcap* /bin/lxc-stop* /bin/lxc-version*</div>
<div>/bin/lxc-checkpoint* /bin/lxc-debian* /bin/lxc-fedora* /bin/lxc-ls* /bin/lxc-ps* /bin/lxc-sshd* /bin/lxc-unfreeze* /bin/lxc-wait*</div>
</div>
<div>Compilation des outils LXC</div>
</blockquote>
<p>Tout est maintenant enfin prêt pour créer notre premier conteneur.</p>
<p><a name="chapter_5"></a></p>
<h2>Utilisation de Linux Container</h2>
<h3>Création d&#8217;un conteneur mandriva</h3>
<p>Les conteneurs LXC sont stockés dans le dossier <kbd>/var/lib/lxc</kbd> (personnellement j&#8217;ai fais un symlink vers un dossier plus adéquat). Chaque conteneur aura là dedans un dossier à son nom (ex. <kbd>/var/lib/lxc/mon_serveur</kbd> pour le conteneur <kbd>mon_serveur</kbd>). Dans chacun de ces dossiers se trouvera un sous-dossier <kbd>rootfs</kbd> qui correspond à la racine du système virtualisé (comme pour chroot). La première chose à faire est donc de créer la structure d&#8217;accueil. Pour cela nous allons commencer par créer un fichier de configuration pour la nouvelle machine, nommons le <kbd>mon_serveur.conf</kbd> à la racine du dossier home.</p>
<blockquote>
<div>lxc.utsname = mon_serveur<br />
 lxc.network.<span>type</span> = veth<br />
 lxc.network.flags = up<br />
 lxc.network.<span>link</span> = br0<br />
 lxc.network.ipv4 = <span>10.0</span><span>.0</span><span>.10</span><span>/</span><span>24</span><br />
 lxc.network.name = eth0</p>
<p><br class="spacer_" /></p>
<p>lxc.<span>pts=</span><span>1023</span><br />
 lxc.<span>tty=</span><span>12</span></p>
<p><span>//</span> Droits sur null et zero<br />
 lxc.cgroup.devices.allow = c <span>1</span>:<span>3</span> rwm<br />
 lxc.cgroup.devices.allow = c <span>1</span>:<span>5</span> rwm</p>
<p><span>//</span> Droits sur random et urandom<br />
 lxc.cgroup.devices.allow = c <span>1</span>:<span>9</span> rwm<br />
 lxc.cgroup.devices.allow = c <span>1</span>:<span>8</span> rwm<br />
 lxc.cgroup.devices.allow = c <span>136</span>:<span>*</span> rwm<br />
 lxc.cgroup.devices.allow = c <span>5</span>:<span>2</span> rwm</p>
<p><span>//</span> Droits sur l<span>&#8216;horloge<br />
 lxc.cgroup.devices.allow = c 254:0 rwm</span></p>
<p>// droits sur les consoles<br />
 lxc.cgroup.devices.allow = c 5:1 rwm<br />
 lxc.cgroup.devices.allow = c 5:0 rwm<br />
 lxc.cgroup.devices.allow = c 4:0 rwm<br />
 lxc.cgroup.devices.allow = c 4:1 rwm</p>
</div>
<div>~/mon_server.conf</div>
</blockquote>
<p>Ce fichier de configuration contient principalement le nom du serveur et le paramétrage réseau de celui-ci. Le gros bloc à la fin correspond aux droits du group de processus représenté par le conteneur. En effet, nous allons grâce à cgroup pouvoir paramétrer finement ce que le conteneur a le droit de faire. Il nous paramétrons cgroup pour autoriser l&#8217;accès aux devices important du sous-système (/dev/null, /dev/urandom, etc.).</p>
<p>Nous allons maintenant utiliser cette configuration pour créer le conteneur  :</p>
<blockquote>
<div>
<div><span>root#</span>lxc-create -n mon_serveur -f ~/mon_serveur.conf</div>
</div>
<div>Création du conteneur</div>
</blockquote>
<p>La structure est maintenant créée, ce que nous pouvons vérifier facilement :</p>
<blockquote>
<div>
<div># tree /var/lib/lxc/mon_serveur/</div>
<div>/var/lib/lxc/mon_serveur/</div>
<div>|&#8211; config</div>
<div>|&#8211; network</div>
<div>|   `&#8211; veth0</div>
<div>|       |&#8211; ipv4</div>
<div>|       |   `&#8211; addresses</div>
<div>|       |&#8211; link</div>
<div>|       |&#8211; name</div>
<div>|       `&#8211; up</div>
<div>|&#8211; pts</div>
<div>|&#8211; state</div>
<div>|&#8211; tty</div>
<div>`&#8211; utsname</div>
</div>
<div>Structure du conteneur</div>
</blockquote>
<p>Bien évidement il s&#8217;agit là que d&#8217;une configuration initiale qu&#8217;il est possible d&#8217;étendre par la suite. La configuration que se trouve la racine est un peu comme celle d&#8217;un kernel linux dans /boot. Elle est là à titre indicatif et je n&#8217;ai constaté aucun impact en la modifiant, sauf pour le paramétrage du cgroup. Pour le reste, si vous désirez changer la configuration, il faut toucher aux éléments suivants :</p>
<ul>
<li>network/vethX &#8211; pour les paramètres réseau</li>
<li>pts &#8211; pour le nombre de /dev/pts.</li>
<li>tty &#8211; pour le nombre de tty alloué.</li>
<li>utsname &#8211; pour le nom de la machine.</li>
</ul>
<h3>Création de la racine</h3>
<p>Comme vous l&#8217;avez déjà constaté, il manque pour l&#8217;instant le dossier <kbd>rootfs</kbd> qui va contenir la racine de notre système. Pour la créer nous allons utiliser la même technique que pour la création d&#8217;un GNU/Linux en <a href="http://artisan.karma-lab.net/node/1055" target="_blank">chroot</a> :</p>
<blockquote>
<div>
<div><span>root#</span>Création de la racine</div>
<div># mkdir /var/lib/lxc/mon_serveur/rootfs</div>
<div><span>root#</span>population d&#8217;une mandriva (utilisez basesystem-mini pour une version encore plus compact)</div>
<div># urpmi basesystem urpmi locales-fr drakxtools-curses &#8211;root /var/lib/lxc/mon_serveur/rootfs</div>
</div>
<div>Peuplement de la racine</div>
</blockquote>
<p>Notez que vous pouvez installer une version 32bits de GNU/Linux dans un conteneur pour un hôte 64bits sans aucun problème. Vous pouvez aussi installer n&#8217;importe quelle distribution linux pour peu qu&#8217;elle soit compatible avec le kernel hôte.</p>
<p>Notez enfin que vous pouvez ajouter d&#8217;autres paquets à l&#8217;installation en relançant la commande <kbd>urpmi ... --root ...</kbd>.</p>
<h3>Préparation de /dev</h3>
<p>Il s&#8217;agit là d&#8217;une étape optionnelle. En effet, <kbd>urpmi</kbd> nous a créé un dossier <kbd>/dev</kbd> correctement peuplé. Mais certains paranoïaques voudront limiter au maximum le nombre de devices disponibles dans ce dossier. La procédure qui suit permet de vider le dossier <kbd>/dev</kbd>, et d&#8217;y mettre le stricte nécessaire :</p>
<blockquote>
<div>
<div># chroot rootfs</div>
<div># cd /dev</div>
<div># rm -rf *</div>
<div># mkdir pts</div>
<div># mkdir shm</div>
<div># mknod -m 777 null c 1 3</div>
<div># mknod -m 777 zero c 1 5</div>
<div># mknod -m 644 random c 1 8</div>
<div># mknod -m 644 urandom c 1 9</div>
<div># chown root:root random urandom</div>
<div># exit</div>
</div>
<div>Le minimum dans le dossier /dev</div>
</blockquote>
<h3>Paramétrage du réseau et des services</h3>
<p>Pour que tout soit fonctionnel, il y a encore quelques paramétrages à faire. Pas la peine de lancer le conteneur pour cela, un <kbd>chroot rootfs</kbd> devrait suffire.</p>
<p>Tout d&#8217;abord nous allons installer les services nécessaires au conteneur (<kbd>openssh-server</kbd> est un minimum pour avoir une console, etc) en passant par <kbd>upmi</kbd>. Ensuite il suffira d&#8217;utiliser <kbd>chkconfig</kbd> ou <kbd>drakxservices</kbd> pour déterminer les services à lancer.</p>
<p>Nous allons ensuite vider <kbd>/etc/fstab</kbd> de son contenu pour éviter les montages intempestifs et y ajouter les montages importants. Au final, votre fichier /etc/fstab devra ressembler à ceci :</p>
<blockquote>
<div>/proc /proc proc defaults 0 0<br />
 tmpfs /dev/shm tmpfs defaults 0 0 <br />
 /sys /sys sysfs defaults 0 0</div>
<div>/etc/fstab du conteneur</div>
</blockquote>
<p>Après cela, il nous faut créer un fichier <kbd>/etc/sysconfig/network-scripts/ifcfg-eth0</kbd> qui contiendra quelque chose comme cela :</p>
<blockquote>
<div><span>DEVICE=</span>eth0<br />
 <span>ONBOOT=</span>yes<br />
 <span>IPADDR=</span><span>10.0</span><span>.0</span><span>.10</span><br />
 <span>NETMASK=</span><span>255.255</span><span>.255</span><span>.255</span><br />
 <span>GATEWAY=</span><span>10.0</span><span>.0</span><span>.100</span><br />
 <span>DNS1=</span><span>DNS1=</span><span>212.27</span><span>.40</span><span>.240</span></div>
</blockquote>
<h3>Gestion du démarrage/arrêt</h3>
<p># Création d&#8217;un faux &#8220;init&#8221; (à voir plus loin)   # mv /sbin/init /sbin/init.old   # echo &#8220;echo &#8216;Bienvenue sur le conteneur&#8217;&#8221; &gt; /sbin/init   # echo &#8220;/bin/sh&#8221; &gt;&gt; /sbin/init   # exit</p>
<p>Normalement il ne devrait rien y avoir de plus à faire. Malgré tout, nous allons avoir quelques problèmes avec <kbd>/sbin/init</kbd> :</p>
<ul>
<li>Comme nous avons installé dans rootfs une distribution tout ce qu&#8217;il y a de plus standard, le processus d&#8217;initialisation va tenter, via <kbd>rc.sysinit</kbd>, de monter des tas de choses inutiles voir nuisibles au conteneur (ex. udev). Ce serait facile à régler en vidant <kbd>rc.sysinit</kbd> de son contenu.</li>
<li>Je n&#8217;ai pas trouvé le moyen d&#8217;éteindre proprement les services lancés par un <kbd>halt</kbd>, <kbd>shutdown</kbd> ou encore <kbd>/etc/rc.d/rc.shutdown</kbd>.</li>
<li>Malgré tous mes efforts, je n&#8217;ai pas réussi à créer au sein du conteneur un seul <kbd>tty</kbd> valide. Ce qui dans le cadre d&#8217;un <kbd>init</kbd> standard pose problème car le lancement des consoles (<kbd>mgetty</kbd> ou <kbd>mingetty</kbd>) plante entraînant un plantage de l&#8217;init lui-même (<kbd>too many respawn</kbd>).</li>
</ul>
<p>Pour régler tout cela, ma solution (un peu pourrie j&#8217;en conviens) consiste à créer notre propre remplacement de <kbd>/sbin/init</kbd> qui ressemblera à cela :</p>
<blockquote>
<div><span>#!/bin/sh</span></p>
<p><br class="spacer_" /></p>
<p><span># Réseau</span><br />
 . <span>/</span>etc<span>/</span>sysconfig<span>/</span>network<br />
 . <span>/</span>etc<span>/</span>sysconfig<span>/</span>network-scripts<span>/</span>ifcfg-eth0<br />
 route add -net default gw <span>$GATEWAY</span> eth0<br />
 <span>hostname</span> <span>${HOSTNAME}</span></p>
<p><span># Set the NIS domain name</span><br />
 <span>if</span> <span>[</span> -n <span>"$NISDOMAIN"</span> <span>]</span>; <span>then</span><br />
 <span>nisdomainname</span> <span>$NISDOMAIN</span><br />
 <span>fi</span></p>
<p><span># arrêt/démarrage des services</span><br />
 <span>function</span> process<span>(</span><span>)</span> <span>{</span><br />
 <span>for</span> service <span>in</span> $<span>(</span><span>ls</span> <span>/</span>etc<span>/</span>rc.d<span>/</span>rc$<span>1</span>.d<span>/*</span> <span>|</span> <span>sort</span><span>)</span>; <span>do</span><br />
 <span>case</span> <span>$service</span> <span>in</span><br />
 <span>*</span>network<span>*</span> <span>|</span> <span>*</span>halt<span>*</span> <span>|</span> <span>*</span><span>kill</span><span>*</span><span>)</span> <span>;;</span><br />
 <span>*</span><span>)</span> <br />
 <span>$service</span> $<span>2</span><br />
 <span>;;</span><br />
 <span>esac</span><br />
 <span>done</span><br />
 <span>}</span></p>
<p><span># Montage des psoeudos systèmes de fichier</span><br />
 <span>mount</span> -t proc <span>/</span>proc <span>/</span>proc<br />
 <span>mount</span> -t sysfs <span>/</span>sys <span>/</span>sys<br />
 <span>mount</span> -t tmpfs  none <span>/</span>dev<span>/</span>shm<br />
 <span>mount</span> -a</p>
<p><span># Démarrage des services</span><br />
 process <span>5</span> start</p>
<p><span># Attente de la mise mort de la machine</span><br />
 <span>rm</span> -rf <span>/</span>.dead<br />
 <span>&gt;</span> <span>/</span>.running<br />
 <span>while</span> <span>[</span> -f <span>/</span>.running <span>]</span> ; <span>do</span><br />
 <span>sleep</span> <span>1</span><br />
 <span>done</span></p>
<p><span># Arrêt des services</span><br />
 process <span>0</span> stop</p>
<p><span># Démontage des systèmes de fichier</span><br />
 <span>umount</span> <span>/</span>proc<br />
 <span>umount</span> <span>/</span>sys<br />
 <span>umount</span> <span>/</span>dev<span>/</span>shm<br />
 <span>umount</span> -a</p>
</div>
<div>/sbin/init dans le conteneur</div>
</blockquote>
<p>Telle que cette initialisation est conçue, elle commence par monter les systèmes de fichiers utiles (sauf <kbd>/dev/pts</kbd> est pris en charge par lxc) et ensuite va démarrer les services actifs. La partie bien stupide qui suit permet de palier à l&#8217;absence de <kbd>tty</kbd>. Il s&#8217;agit d&#8217;une simple boucle d&#8217;attente sur la présence du fichier <kbd>/.running</kbd>. Ainsi pour arrêter le conteneur, il suffit de détruire ce fichier. Les services alors proprement sont déchargés et les systèmes de fichier démontés. Le conteneur s&#8217;arrêtera alors de lui-même.</p>
<h3>Lancement du conteneur</h3>
<p>Le conteneur est maintenant prêt à être lancé, cela se passe avec la commande <kbd>lxc-start</kbd> :</p>
<blockquote>
<div>
<div># lxc-start -n mon_serveur</div>
<div>Starting sshd                   [  OK  ]</div>
</div>
<div>Lancement du conteneur</div>
</blockquote>
<p>Et c&#8217;est tout, le conteneur est en route et dispose d&#8217;une logiquement adresse IP. Vous pouvez donc la &#8220;pinger&#8221; de l&#8217;extérieur pour vérifier. Vous constaterez au passage sur l&#8217;hôte l&#8217;apparition d&#8217;une interface <kbd>veth0</kbd> qui est l&#8217;équivalent d&#8217;eth0 pour le conteneur. Vous pouvez éteindre le conteneur en vous connectant en ssh dessus et en détruisant le fichier <kbd>/.running</kbd>.</p>
<blockquote>
<div>
<div><span>host</span>ssh mon_user@10.0.0.10</div>
<div>mon_user@10.0.0.10&#8217;s password:</div>
<div>mon_user@mon_serveur [~] $ su -</div>
<div>Password:</div>
<div><span>root@mon_serveur [~] </span>rm -rf /.running</div>
<div><span>root@mon_serveur [~] </span>Connection to 10.0.0.10 closed by remote host.</div>
<div>Connection to 192.168.154.103 closed.</div>
</div>
<div>Connexion au conteneur et extinction</div>
</blockquote>
<p><a name="chapter_6"></a></p>
<h2>Conclusion</h2>
<p>Il est possible de se rendre la vie plus agréable en ajoutant, comme pour OpenVZ, la possibilité que certains conteneurs se lancent au démarrage de l&#8217;hôte. C&#8217;est le rôle de <a href="http://arnumeral.fr/subversion/public/tools/services/lxc" target="_blank">ce script</a> qui est à placer en <kbd>/etc/init.d</kbd> et à activer avec <kbd>chkconfig</kbd> ou <kbd>drakxservices</kbd>. Pour l&#8217;utiliser il suffit de rajouter à la configuration du conteneur un paramètre <kbd>lxc.onboot=yes</kbd> qui impliquera son démarrage automatique.  Ce script exploite un autre script de mon cru, <a href="http://arnumeral.fr/subversion/public/tools/utilities/lxcctl" target="_blank">lxcctl</a> qui simplifie le lancement et l&#8217;extinction d&#8217;un conteneur. Il fournit ainsi les commandes <kbd>lxcctl start mon_conteneur</kbd>, <kbd>lxcctl stop mon_conteneur</kbd> et <kbd>lxcctl info mon_conteneur</kbd>. En espérant que ceci finisse par être intégré à LXC directement (sous réserve que les tty fonctionnent évidement).</p>
<p>Voilà, c&#8217;est la fin de ce &#8220;petit&#8221; papier sur ce projet très prometteur qu&#8217;est LXC. Personnellement j&#8217;ai un peu trouvé ce que je cherchais depuis très longtemps et que j&#8217;avais effleuré avec chroot. Grâce à LXC, je peux non seulement virtualiser le serveur domestique, mais aussi dupliquer à volonté des conteneurs pour mes projets (un conteneur &#8220;type&#8221; pour le développement WEB, un autre pour Android, etc.). Et tout cela sans souffrir de la moindre perte de performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=260</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>L&#8217;installation d&#8217;Hadopi sous Linux enfin possible !</title>
		<link>http://blog.pepita.org/?p=257</link>
		<comments>http://blog.pepita.org/?p=257#comments</comments>
		<pubDate>Mon, 28 Jun 2010 11:53:21 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Perso]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=257</guid>
		<description><![CDATA[Ça y est ! J&#8217;ai trouvé !
 Il est anéfé possible d&#8217;installer le logiciel d&#8217;Hadopi sous Linux. Voici  la procédure d&#8217;installation depuis un terminal ( [troll] Linux oblige  [/troll] ) qui vous  rafraîchira un peu les idées après l&#8217;ivresse des fêtes :
Code :
albanel@majors$ sudo apt-get install hadopi
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets supplémentaires suivants seront installés :
 lib-bypass-constitution-francaise lib-propagande
 lib-autorite-administrative-avec-tous-les-droits
E Les paquets suivants ont des dépendances non satisfaites : hadopi dépend de lo
bby-vivendi, mais lobby-vivendi est en conflit avec lib-information-impartiale.
Les actions suivantes permettront de résoudre ces dépendances :
 s-asseoir-sur-les-libertés-fondamentales
Accepter cette solution [O/n] ? O

Les paquets suivants seront enlevés :
 lib-presomption-d-innocence lib-droits-de-la-defense
 lib-separation-des-pouvoirs lib-information-impartiale
Les NOUVEAUX paquets suivants seront installés :
 hadopi lib-bypass-constitution-francaise lib-propagande
 lib-autorite-administrative-avec-tous-les-droits lobby-vivendi
0 mis à jour, 5 nouvellement installés, 4 à enlever et 0 non mis à jour.
Il est nécessaire de prendre 70 heures de débats à l'Assemblée Nationale et un n
ombre indéterminé d'heures de propagande dans les médias.
Après cette opération, 500000€ d'argent public supplémentaires seront utilisés.
Souhaitez-vous continuer [O/n] ? O

Suppression de lib-presomption-d-innocence...
Suppression de lib-droits-de-la-defense...
Suppression de lib-separation-des-pouvoirs...
Suppression de lib-information-impartiale...

Réception de : 1 http://www.vivendi.fr lobby/control lib-bypass-constitution-fra
ncaise réceptionnés en 1s
Réception de : 2 http://www.vivendi.fr lobby/control lobby-vivendi réceptionnés
en 1s
Réception de : 3 http://www.vivendi.fr lobby/control lib-propagande réceptionnés
 en 1s
Réception de : 4 http://www.sarkozy.fr util/rights lib-autorite-administrative-a
vec-tous-les-droits réceptionnés en 1s

Dépaquetage de lib-bypass-constitution-francaise...
Dépaquetage de lobby-vivendi...
I lobby-vivendi était déjà présent et très bien intégré au système.
Dépaquetage de lib-propagande...
Dépaquetage de lib-autorite-administrative-avec-tous-les-droits...

Génération de hadopi...
Refus de discussions...
Rejet des amendements proposés (utilisation du module anéfé-rejeté)...
Compilation de oofirewall...
Compilation de arguments-fallacieux...
 Compilation de les-accords-de-l-elysee...
 Compilation de les-ventes-de-cd-chutent-de-50%-et-celles-des-cassettes-audio-d
e-90%-c-est-inadmissible...
 Compilation de la-creation-est-en-train-de-mourir-a-cause-de-gens-qui-attaquen
t-les-bateaux...

W Le module 5-gus-dans-un-garage semble poser des problèmes de compilation de ar
guments-fallacieux.

E Problème lors de la génération de hadopi : des composants cachés derrière des
rideaux sont apparus de manière inattendue. Réessayer [O/n] ? O

Pour éviter que le problème ne se reproduise, il est nécessaire de mettre à jour
le module deputes-godillots. Souhaitez-vous mettre à jour [O/n] ? O

Compilation de cope-rabat-les-troupes...
Compilation de laver-l-affront...
Mise à jour de deputes-godillots...

W De nombreux paquets de type amendement ralentissent l'installation d'hadopi.

L'installation de hadopi semble avoir réussi.

Vérification de la compatibilité avec la constitution française...
E Le module lib-bypass-constitution-francaise a été détecté par le conseil const
itutionnel.
E Le module répression a dû être désactivé pour protéger la constitution.

Installation obligatoire de internet-liberte-fondamentale.
Réception de : 1 http://www.constitution.fr rights internet-liberte-fondamentale
 réceptionnés en 1s
Dépaquetage de internet-liberte-fondamentale...

albanel@majors$ for m in media; do echo 'Je prends acte de la décision du consei
l constitutionnel. 95% du texte a été validé.'; done

E lobby-vivendi panic détecté.
Prise en charge de l'erreur par sarkozy et lobby-vivendi.

exit

sarkozy@majors# deluser albanel
sarkozy@majors# ls gauche/corrompus/*
 Trop de résultats ont été trouvés : affichage des premiers résultats.
 jack_lang frederic_mitterrand
sarkozy@majors# adduser lang
 &#62; opération échouée
sarkozy@majors# adduser mitterrand
sarkozy@majors# su mitterrand

mitterrand@majors$ sudo /etc/init.d/pantind start
 * Starting PantinServer [ OK ]
mitterrand@majors$ pantin -verbose
Attente des ordres...
Exécution à distance de "apt-get install hadopi2"...
L'installation du paquet hadopi2 peut corriger le problème. Tenter [O/n] ? O
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets supplémentaires suivants seront installés :
 ordonnance-penale negligence-caracterisee
 on-vous-prend-vraiment-pour-des-cons
Les NOUVEAUX paquets suivants seront installés :
 hadopi2 ordonnance-penale negligence-caracterisee
 on-vous-prend-vraiment-pour-des-cons
Les paquets suivants seront mis à jour :
 lib-bypass-constitution-francaise
0 mis à jour, 4 nouvellement installés, 0 à enlever et 1 non mis à jour.
Il est nécessaire de prendre 40 heures de débats à l'Assemblée Nationale.
Après cette opération, 300000€ d'argent public supplémentaires seront utilisés.
Souhaitez-vous continuer [O/n] ? O

Réception de : 1 http://justice-expeditive.fr tools ordonnance-penale réceptionn
és en 1s
Réception de : 2 http://justice-expeditive.fr tools negligence-caracterisee réce
ptionnés en 1s
Réception de : 3 http://habitudes.gouv.fr kernel on-vous-prend-vraiment-pour-des
-cons réceptionnés en 1s
Réception de : 4 http://henrard.fr control lib-bypass-constitution-francaise réc
eptionnés en 5 minutes

Dépaquetage de ordonnance-penale...
Dépaquetage de negligence-caracterisee...
Dépaquetage de on-vous-prend-vraiment-pour-des-cons...
I En fait ce module était déjà présent sur le système depuis un moment.
Dépaquetage de lib-bypass-constitution-francaise...

Paramétrage de on-vous-prend-vraiment-pour-des-cons...
Paramétrage de lib-bypass-constitution-francaise...

Génération de hadopi2...
Refus de TOUTES discussions (ignorer-analyses-pertinentes activé)...
Rejet de TOUS les amendements proposés (utilisation du module anéfé-rejeté-en-ra
fale)...
Le paquet arguments-fallacieux existait déjà, mais il nécessite maintenant les d
épendances arguments-fallacieux-negligence-caracterisee et arguments-fallacieux-
ordonnance-pénale. Installer [O/n] ? O

Réception de : 1 http://henrard.fr control arguments-fallacieux-negligence-carac
terisee réceptionnés en 2 jours
Réception de : 2 http://henrard.fr control arguments-fallacieux-ordonnance-pénal
e réceptionnés en 1 jour

Dépaquetage de arguments-fallacieux-negligence-caracterisee...
Dépaquetage de arguments-fallacieux-ordonnance-pénale...

W hadopi2-senat-1 est moins performant que hadopi-senat-*.
I deputes-godillots utilisé pour compiler le module vote-solennel.
W Problème éventuel de sécurité. Des éléments de compilation de vote-solennel on
t peut-être été contrôlés à distance : des incohérences entre leurs données et l
eurs actions ont été détectées.
La compilation de vote-solennel a réussi.

W L'installation de hadopi2-senat-2 a fonctionné, mais il semble que 90% du code
source du paquet n'ait pas été utilisé.

Compilation de vote-solennel-2...
I deputes-godillots fonctionne à merveille.
La compilation de vote-solennel-2 a réussi.

Vérification de la compatibilité avec la constitution française...
E Le module on-vous-prend-vraiment-pour-des-cons a fortement déplu au conseil co
nstitutionnel.
E Le paquet hadopi2 a été tagué "censuré" par le conseil constitutionnel.

Attente des ordres...
Ordre reçu de lobby-vivendi : créer une taxe sur les fournisseurs d'accès sans c
ontrepartie.
Résolution du problème trouver-des-arguments-bidons-pour-faire-passer-ça-et-refu
ser-la-contribution-créative en cours...
Réception de : 1 http://www.majors.fr help toubon réceptionnés en 1s
Réception de : 2 http://www.majors.fr help zelnik réceptionnés en 1s

Attente des ordres...


 Quel suspense !
 Hormis l&#8217;objectif de divertissement proposé par [...]]]></description>
			<content:encoded><![CDATA[<p>Ça y est ! J&#8217;ai trouvé !<br />
 Il est anéfé possible d&#8217;installer le logiciel d&#8217;Hadopi sous Linux. Voici  la procédure d&#8217;installation depuis un terminal ( [troll] Linux oblige <img style="vertical-align: middle;" src="http://www.clubic.com/api/forum/img/smiley/sourire4.gif" border="0" alt="" /> [/troll] ) qui vous  rafraîchira un peu les idées après l&#8217;ivresse des fêtes :</p>
<div><strong>Code :</strong></p>
<pre>albanel@majors$ sudo apt-get install hadopi<span id="more-257"></span>
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets supplémentaires suivants seront installés :
 lib-bypass-constitution-francaise lib-propagande
 lib-autorite-administrative-avec-tous-les-droits
E Les paquets suivants ont des dépendances non satisfaites : hadopi dépend de lo
bby-vivendi, mais lobby-vivendi est en conflit avec lib-information-impartiale.
Les actions suivantes permettront de résoudre ces dépendances :
 s-asseoir-sur-les-libertés-fondamentales
Accepter cette solution [O/n] ? O

Les paquets suivants seront enlevés :
 lib-presomption-d-innocence lib-droits-de-la-defense
 lib-separation-des-pouvoirs lib-information-impartiale
Les NOUVEAUX paquets suivants seront installés :
 hadopi lib-bypass-constitution-francaise lib-propagande
 lib-autorite-administrative-avec-tous-les-droits lobby-vivendi
0 mis à jour, 5 nouvellement installés, 4 à enlever et 0 non mis à jour.
Il est nécessaire de prendre 70 heures de débats à l'Assemblée Nationale et un n
ombre indéterminé d'heures de propagande dans les médias.
Après cette opération, 500000€ d'argent public supplémentaires seront utilisés.
Souhaitez-vous continuer [O/n] ? O

Suppression de lib-presomption-d-innocence...
Suppression de lib-droits-de-la-defense...
Suppression de lib-separation-des-pouvoirs...
Suppression de lib-information-impartiale...

Réception de : 1 http://www.vivendi.fr lobby/control lib-bypass-constitution-fra
ncaise réceptionnés en 1s
Réception de : 2 http://www.vivendi.fr lobby/control lobby-vivendi réceptionnés
en 1s
Réception de : 3 http://www.vivendi.fr lobby/control lib-propagande réceptionnés
 en 1s
Réception de : 4 http://www.sarkozy.fr util/rights lib-autorite-administrative-a
vec-tous-les-droits réceptionnés en 1s

Dépaquetage de lib-bypass-constitution-francaise...
Dépaquetage de lobby-vivendi...
I lobby-vivendi était déjà présent et très bien intégré au système.
Dépaquetage de lib-propagande...
Dépaquetage de lib-autorite-administrative-avec-tous-les-droits...

Génération de hadopi...
Refus de discussions...
Rejet des amendements proposés (utilisation du module anéfé-rejeté)...
Compilation de oofirewall...
Compilation de arguments-fallacieux...
 Compilation de les-accords-de-l-elysee...
 Compilation de les-ventes-de-cd-chutent-de-50%-et-celles-des-cassettes-audio-d
e-90%-c-est-inadmissible...
 Compilation de la-creation-est-en-train-de-mourir-a-cause-de-gens-qui-attaquen
t-les-bateaux...

W Le module 5-gus-dans-un-garage semble poser des problèmes de compilation de ar
guments-fallacieux.

E Problème lors de la génération de hadopi : des composants cachés derrière des
rideaux sont apparus de manière inattendue. Réessayer [O/n] ? O

Pour éviter que le problème ne se reproduise, il est nécessaire de mettre à jour
le module deputes-godillots. Souhaitez-vous mettre à jour [O/n] ? O

Compilation de cope-rabat-les-troupes...
Compilation de laver-l-affront...
Mise à jour de deputes-godillots...

W De nombreux paquets de type amendement ralentissent l'installation d'hadopi.

L'installation de hadopi semble avoir réussi.

Vérification de la compatibilité avec la constitution française...
E Le module lib-bypass-constitution-francaise a été détecté par le conseil const
itutionnel.
E Le module répression a dû être désactivé pour protéger la constitution.

Installation obligatoire de internet-liberte-fondamentale.
Réception de : 1 http://www.constitution.fr rights internet-liberte-fondamentale
 réceptionnés en 1s
Dépaquetage de internet-liberte-fondamentale...

albanel@majors$ for m in media; do echo 'Je prends acte de la décision du consei
l constitutionnel. 95% du texte a été validé.'; done

E lobby-vivendi panic détecté.
Prise en charge de l'erreur par sarkozy et lobby-vivendi.

exit

sarkozy@majors# deluser albanel
sarkozy@majors# ls gauche/corrompus/*
 Trop de résultats ont été trouvés : affichage des premiers résultats.
 jack_lang frederic_mitterrand
sarkozy@majors# adduser lang
 &gt; opération échouée
sarkozy@majors# adduser mitterrand
sarkozy@majors# su mitterrand

mitterrand@majors$ sudo /etc/init.d/pantind start
 * Starting PantinServer [ OK ]
mitterrand@majors$ pantin -verbose
Attente des ordres...
Exécution à distance de "apt-get install hadopi2"...
L'installation du paquet hadopi2 peut corriger le problème. Tenter [O/n] ? O
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets supplémentaires suivants seront installés :
 ordonnance-penale negligence-caracterisee
 on-vous-prend-vraiment-pour-des-cons
Les NOUVEAUX paquets suivants seront installés :
 hadopi2 ordonnance-penale negligence-caracterisee
 on-vous-prend-vraiment-pour-des-cons
Les paquets suivants seront mis à jour :
 lib-bypass-constitution-francaise
0 mis à jour, 4 nouvellement installés, 0 à enlever et 1 non mis à jour.
Il est nécessaire de prendre 40 heures de débats à l'Assemblée Nationale.
Après cette opération, 300000€ d'argent public supplémentaires seront utilisés.
Souhaitez-vous continuer [O/n] ? O

Réception de : 1 http://justice-expeditive.fr tools ordonnance-penale réceptionn
és en 1s
Réception de : 2 http://justice-expeditive.fr tools negligence-caracterisee réce
ptionnés en 1s
Réception de : 3 http://habitudes.gouv.fr kernel on-vous-prend-vraiment-pour-des
-cons réceptionnés en 1s
Réception de : 4 http://henrard.fr control lib-bypass-constitution-francaise réc
eptionnés en 5 minutes

Dépaquetage de ordonnance-penale...
Dépaquetage de negligence-caracterisee...
Dépaquetage de on-vous-prend-vraiment-pour-des-cons...
I En fait ce module était déjà présent sur le système depuis un moment.
Dépaquetage de lib-bypass-constitution-francaise...

Paramétrage de on-vous-prend-vraiment-pour-des-cons...
Paramétrage de lib-bypass-constitution-francaise...

Génération de hadopi2...
Refus de TOUTES discussions (ignorer-analyses-pertinentes activé)...
Rejet de TOUS les amendements proposés (utilisation du module anéfé-rejeté-en-ra
fale)...
Le paquet arguments-fallacieux existait déjà, mais il nécessite maintenant les d
épendances arguments-fallacieux-negligence-caracterisee et arguments-fallacieux-
ordonnance-pénale. Installer [O/n] ? O

Réception de : 1 http://henrard.fr control arguments-fallacieux-negligence-carac
terisee réceptionnés en 2 jours
Réception de : 2 http://henrard.fr control arguments-fallacieux-ordonnance-pénal
e réceptionnés en 1 jour

Dépaquetage de arguments-fallacieux-negligence-caracterisee...
Dépaquetage de arguments-fallacieux-ordonnance-pénale...

W hadopi2-senat-1 est moins performant que hadopi-senat-*.
I deputes-godillots utilisé pour compiler le module vote-solennel.
W Problème éventuel de sécurité. Des éléments de compilation de vote-solennel on
t peut-être été contrôlés à distance : des incohérences entre leurs données et l
eurs actions ont été détectées.
La compilation de vote-solennel a réussi.

W L'installation de hadopi2-senat-2 a fonctionné, mais il semble que 90% du code
source du paquet n'ait pas été utilisé.

Compilation de vote-solennel-2...
I deputes-godillots fonctionne à merveille.
La compilation de vote-solennel-2 a réussi.

Vérification de la compatibilité avec la constitution française...
E Le module on-vous-prend-vraiment-pour-des-cons a fortement déplu au conseil co
nstitutionnel.
E Le paquet hadopi2 a été tagué "censuré" par le conseil constitutionnel.

Attente des ordres...
Ordre reçu de lobby-vivendi : créer une taxe sur les fournisseurs d'accès sans c
ontrepartie.
Résolution du problème trouver-des-arguments-bidons-pour-faire-passer-ça-et-refu
ser-la-contribution-créative en cours...
Réception de : 1 http://www.majors.fr help toubon réceptionnés en 1s
Réception de : 2 http://www.majors.fr help zelnik réceptionnés en 1s

Attente des ordres...
</pre>
</div>
<p> Quel suspense !</p>
<p> Hormis l&#8217;objectif de divertissement proposé par ce déroulement  d&#8217;installation quelque peu singulier et le parti pris flagrant dans ce  processus, il s&#8217;agit également d&#8217;une rétrospective détaillée du  processus de création et de (tentative) de mise en place d&#8217;Hadopi.</p>
<p> La suite au prochain épisode ?</p>
<p> ( source : <a rel="nofollow" href="http://blog.rom1v.com/2009/09/apt-get-install-hadopi/" target="_blank">http://blog.rom1v.com/2009/09/apt-get-install-hadopi/</a> )</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=257</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving Backuppc Data Dir</title>
		<link>http://blog.pepita.org/?p=249</link>
		<comments>http://blog.pepita.org/?p=249#comments</comments>
		<pubDate>Fri, 11 Jun 2010 01:51:11 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[backuppc]]></category>
		<category><![CDATA[reiserfs]]></category>
		<category><![CDATA[versionning]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=249</guid>
		<description><![CDATA[Tech Recipe for Backuppc

I will explain briefly how to move the Backuppc __TOP_DIR__ to another disk. The main reason of this long data processing is the performance improvement. I&#8217;ve tried several Filesystems and different under layer block device ( RAID5, RAID10) alwaysover LVM.
For the moment the best seems to be RAID10 with 32K chunksize and [...]]]></description>
			<content:encoded><![CDATA[<h2 style="text-align: center;">Tech Recipe for Backuppc</h2>
<p><br class="spacer_" /></p>
<p>I will explain briefly how to move the Backuppc __TOP_DIR__ to another disk. The main reason of this long data processing is the performance improvement. I&#8217;ve tried several Filesystems and different under layer block device ( RAID5, RAID10) alwaysover LVM.</p>
<p>For the moment the best seems to be RAID10 with 32K chunksize and a reiserfs filesystem mounted with (notail,noatime) options.</p>
<p>The backup speed is not that much faster than on ext3 filesystem, but the main advantage of Reiserfs is that compare to ext3 the disk usage is reduced from 34G in ext3 to 27G in Reiserfs.</p>
<p>The next step will be to test Btrfs performance but for that I first need to migrate from kernel 2.6.18 to 2.6.28 or higher <img src='http://blog.pepita.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>So let start the recipe<span id="more-249"></span></p>
<h4 style="padding-left: 30px;">Copy the real Files (the pool or cpool) to the new disk</h4>
<p>I do prefer rsync but other method are possible (simple cp, tar, &#8230;)</p>
<blockquote><p><code>cd /var/lib/backuppc rsync -aq --exclude=pc/ ./ /new_drive/new_backuppc/</code></p>
</blockquote>
<p>be patient this can be long&#8230; to see what&#8217;s going on replace -aq by -avP</p>
<h4 style="padding-left: 30px;">Use an Internal backuppc command (BackupPC_tarPCCopy) to copy each PC hardlinks structure</h4>
<p>this is also very long treatement. A huge amount of small hardlinks are read and relinked to the new destination</p>
<blockquote><p><code>su __BACKUPPCUSER__<br />
 cd NEW_TOPDIR<br />
 mkdir pc<br />
 cd pc<br />
 __INSTALLDIR__/bin/BackupPC_tarPCCopy __TOPDIR__/pc | tar xPf -<br />
</code></p>
</blockquote>
<p>too keep an eye on the progress I&#8217;ve found a small tool pretty handy to monitor piped data: &#8220;bar&#8221;</p>
<blockquote><p><code>/usr/share/backuppc/bin/BackupPC_tarPCCopy /var/lib/backuppc/pc | bar -dan -bs 4096 | tar xPf -</code></p>
</blockquote>
<p>Here you are for the moment</p>
<p>Glad to hear any comment from your backup experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=249</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vi VimDiff</title>
		<link>http://blog.pepita.org/?p=247</link>
		<comments>http://blog.pepita.org/?p=247#comments</comments>
		<pubDate>Fri, 04 Jun 2010 17:41:36 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[editeur]]></category>
		<category><![CDATA[versionning]]></category>
		<category><![CDATA[Vi]]></category>
		<category><![CDATA[Vim]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=247</guid>
		<description><![CDATA[Usefull vimdiff commands to view diff and merge
October 15, 2008 @ 8:20 am  			· Filed under Linux

Diffing the files and merging them is one of the very common task  we do everyday. Following are few very useful commands to view the diff  using vim and merge them using the vimdiff commands instead [...]]]></description>
			<content:encoded><![CDATA[<h2 id="post-48"><a title="Permanent link to Usefull vimdiff commands to view diff and  merge" rel="bookmark" href="http://puneetworld.com/archives/48">Usefull vimdiff commands to view diff and merge</a></h2>
<p>October 15, 2008 @ 8:20 am  			· Filed under <a title="View all  posts in Linux" rel="category tag" href="http://puneetworld.com/archives/category/linux">Linux</a></p>
<div>
<p>Diffing the files and merging them is one of the very common task  we do everyday. Following are few very useful commands to view the diff  using vim and merge them using the vimdiff commands instead of copying  and pasting from one file to another.</p>
<p><span id="more-247"></span></p>
<p>To diff two files using vim :</p>
<p>vimdiff  file1 file2<br />
or <br />
vim -d file1 file2</p>
<p>Ofcourse you can use gvim also but I don&#8217;t prefer using GVIM.</p>
<p>gvimdiff file1 file2</p>
<p>Commands :</p>
<p>[c : Jump to previous diff<br />
]c : Jump to the next diff</p>
<p>do or :diffget : Diff obtain (get the changes to the current  buffer/file from the other buffer)<br />
dp or :diffput : Diff Put (Put the  changes from the current buffer/file to the other buffer)</p>
<p>As this being one of very command task I do, I have mapped them to  single keys for the easy access.</p>
<p>nmap &lt;F7&gt; [czz <br />
nmap &lt;F8&gt; ]czz<br />
nmap &lt;F2&gt;  do<br />
nmap &lt;F3&gt; dp</p>
<p>The zz in the end of the command [c will center at the point of the  diff so that we can view the diff clearly.</p>
<p>~Enjoy Vim</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=247</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebDAV CGI</title>
		<link>http://blog.pepita.org/?p=241</link>
		<comments>http://blog.pepita.org/?p=241#comments</comments>
		<pubDate>Wed, 12 May 2010 10:14:06 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[WebDav]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=241</guid>
		<description><![CDATA[&#8230; is a Perl CGI script that enables the WebDAV protocol (class 1,2,3) for web server. If you need correct permissions for files and folders  you can install this WebDAV CGI script and a UID/GID wrapper.  The Apache module mod_dav does not support UID/GID wrapping,  so this implementation fills up this gap [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; is a Perl CGI script that enables the WebDAV protocol (class 1,2,3) for web server. If you need correct permissions for files and folders  you can install this WebDAV CGI script and a UID/GID wrapper.  The Apache module mod_dav does not support UID/GID wrapping,  so this implementation fills up this gap as a (most complete)  replacement.</p>
<p><span id="more-241"></span></p>
<p>Content of this topic:</p>
<ul>
<li><a href="#features">Features</a></li>
<li><a href="#download">Download</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#licensing">Licensing</a></li>
<li><a href="#links">Links</a></li>
</ul>
<p><a name="features"></a></p>
<h2>Features</h2>
<p>WebDAV CGI &#8230;</p>
<ul>
<li>supports WebDAV compliance classes 1, 2 and 3</li>
<li>implements CGI interface</li>
<li>offers a simple web interface for file/folder management</li>
<li>is wrappable to change UID/GID for file permissions other than web  server permissions</li>
</ul>
<p>My test environment:</p>
<ul>
<li> Ubuntu 8.04 LTS </li>
<li> Apache 2.2.x</li>
<li> Perl 5.8.8</li>
</ul>
<p>WebDAV CGI is tested with following WebDAV clients (licensing):</p>
<ul>
<li> Firefox web browser &#8211; for folder listing, POST uploads and download  tests (free)</li>
<li> M$ Internet Explorer 7 &#8211; for web interface tests (commercial)</li>
<li> cadaver &#8211; a Linux command line WebDAV client (free)</li>
<li> nautilus &#8211; the Gnome file manager (free)</li>
<li> konqueror &#8211; the KDE browser (free)</li>
<li> OpenOffice (free)</li>
<li> Web Folders &#8211; Windows XP &amp; Windows Vista (build-in)</li>
<li> Novell netdrive (commercial)</li>
<li> BitKinex WebDAV Client (free)</li>
</ul>
<p>Known Problems:</p>
<ul>
<li>Windows Web Folder tries to read folders without &#8216;/&#8217; at the end and  Apache responses with a redirect (Workaround: use Apache rewrite rule  instead of direct folder access)</li>
<li> Windows 7 does not support SSL with Web Folders (yet) and has some  trouble with HTTP Basic authentication (<code>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel</code> should be <code>2</code>(DWORD))</li>
<li>Amaya upload does not work yet</li>
<li>DAVExplorer has some trouble with XML parsing (PROPFIND) &#8230;  sometimes.</li>
<li>Adobe Dreamweaver has some trouble to read folders</li>
<li>nautilus cannot copy folders via clipboard</li>
</ul>
<p><a name="download"></a></p>
<h2>Download</h2>
<p>TuXxX Blog download : [filebase:file:file3]</p>
<p>Latest version: 0.3.3 (Changes: see <a href="http://amor.rz.hu-berlin.de/%7Erohdedan/webdav/dl.php?webdav.pl">webdav.pl</a>)</p>
<ul>
<li><a href="http://amor.rz.hu-berlin.de/%7Erohdedan/webdav/dl.php?webdav.pl">webdav.pl</a> &#8211; the WebDAV CGI  	<br />
 Downloads: 35</li>
<li><a href="http://amor.rz.hu-berlin.de/%7Erohdedan/webdav/dl.php?webdavwrapper.c">webdavwrapper.c</a> &#8211; a sample UID/GID wrapper: takes UID from the file/folder or if  file/folder does not exists takes the UID of the authenticated user  (REMOTE_USER)  	<br />
 Downloads: 18</li>
</ul>
<p>The latest BETA release is also available: <a href="http://amor.rz.hu-berlin.de/%7Erohdedan/webdav/dl.php?webdav-beta.pl">webdav-beta.pl</a> (Downloads: <img src='http://blog.pepita.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' />  <a name="installation"></a></p>
<h2>Installation</h2>
<ol>
<li>install required CPAN modules (Debian/Ubuntu package name):
<ul>
<li>CGI (libcgi-perl)</li>
<li>DBI (libdbi-perl) and a database driver, e.g. DBD::SQLite  (libdbd-sqlite3-perl)</li>
<li>Date::Parse (libtimedate-perl)</li>
<li>File::Copy::Recursive (libfile-copy-recursive-perl)</li>
<li>OSSP::uuid (libossp-uuid-perl)</li>
<li>XML::Simple (libxml-simple-perl)</li>
</ul>
<p>You can do that with &#8216;<code>perl -MCPAN -e "install  &lt;ModuleName&gt;"</code>&#8216; or with &#8216;<code>apt-get install  &lt;PackageName&gt;</code>&#8216;.</p>
</li>
<li>compile your wrapper, change the permissions and put it into  your cgi-bin, e.g:
<pre>gcc -o webdavwrapper webdavwrapper.c
strip webdavwrapper

chown root:root webdavwrapper
chmod ug+s webdavwrapper

cp -p webdavwrapper /srv/www/cgi-bin/
</pre>
</li>
<li>put the WebDAV CGI <code>webdav.pl</code> into your cgi-bin; edit  webdav.pl to setup and change permissions, e.g:
<pre>cp webdav.pl /srv/www/cgi-bin
vim webdav.pl
chmod a+rx webdav.pl
</pre>
</li>
<li>configure your web server:
<ul>
<li>you can do that with rewrite rules</li>
<li> or with a handler action</li>
</ul>
<p>Here is an example Apache 2.x configuration:</p>
<pre>Action webdav-cgi /cgi-bin/webdavwrapper
&lt;Location /mywebdavspace&gt;
	SetHandler webdav-cgi
	#necessary for PUT, MKCOL and LOCK:
	ErrorDocument  404  /cgi-bin/webdavwrapper
	#fix Windows requests to folders without slash (handle redirects):
	ErrorDocument  301  /cgi-bin/webdavwrapper
	AuthType Basic
	AuthName "WebDAV space"
	AuthUserFile /path-to-my-auth-file
	Require valid-user
&lt;/Location&gt;
# if you want to map this to a real path, do that:
# (end setup VIRTUAL_BASE)
RewriteRule  ^/mywebdavspace(.*) /cgi-bin/webdavwrapper \
	[L,E=PATH_TRANSLATED:/srv/www/htdocs$1]
    </pre>
</li>
</ol>
<p><a name="licensing"></a></p>
<h2>Licensing</h2>
<p><a href="http://www.gnu.org/licenses/gpl.txt">GPLv3</a> <a name="links"></a></p>
<h2>Links</h2>
<ul>
<li><a href="http://www.webdav.org/specs/rfc4918.html">RFC4918</a> &#8211;  WebDAV RFC</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=241</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Software Foundation réplique</title>
		<link>http://blog.pepita.org/?p=233</link>
		<comments>http://blog.pepita.org/?p=233#comments</comments>
		<pubDate>Tue, 04 May 2010 12:09:21 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Perso]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[GPL]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=233</guid>
		<description><![CDATA[Voici un nouveau rebondissement dans l&#8217;affaire qui oppose Adobe à Apple concernant la technologie Flash. Pour mémoire, leDG de la firme de Cupertino s&#8217;était exprimé  au travers d&#8217;un communiqué de presse afin de justifier l&#8217;absence de Flash sur l&#8217;iPhone, l&#8217;iPod Touch et l&#8217;iPad. Steve Jobs déclarait en effet que l&#8217;avenir des technologies mobiles devait [...]]]></description>
			<content:encoded><![CDATA[<p>Voici un nouveau rebondissement dans l&#8217;affaire qui oppose Adobe à Apple concernant la technologie Flash. Pour mémoire, le <div id="attachment_234" class="wp-caption alignright" style="width: 160px"><a href="http://blog.pepita.org/wp-content/uploads/2010/05/Gnu.png"><img src="http://blog.pepita.org/wp-content/uploads/2010/05/Gnu-150x150.png" alt="The Gnu Guru" title="Gnu" width="150" height="150" class="size-thumbnail wp-image-234" /></a><p class="wp-caption-text">The Gnu Guru</p></div>PDG de la firme de Cupertino s&#8217;était exprimé  au travers d&#8217;un communiqué de presse afin de justifier l&#8217;absence de Flash sur l&#8217;iPhone, l&#8217;iPod Touch et l&#8217;iPad. Steve Jobs déclarait en effet que l&#8217;avenir des technologies mobiles devait passer par des standards ouverts tel que HTML, CSS et JavaScript plutôt que par une technologie propriétaire telle que Flash.</p>
<p>De son côté Adobe soulignait la compatibilité de son lecteur avec une multitude de plateformes simplifiant alors la tâche pour l&#8217;éditeur qui ne devra pas développer une version de son application spécifiquement pour le système propriétaire de l&#8217;iPhone OS.</p>
<p>C&#8217;est désormais au tour de la Free Software Foundation, l&#8217;organisme chargé de défendre et promouvoir les valeurs du logiciel libre, de s&#8217;exprimer sur le sujet au travers d&#8217;un communiqué de presse. En effet, le porte -parole et activiste John Sullivan, invité sur le magazine Arstechnica, pointe du doigt l&#8217;hypocrisie des deux sociétés promouvant des standards ouverts sans pour autant suivre leurs propres principes. John Sullivan souligne en effet que Steve Jobs n&#8217;a fourni aucune explication pour le choix de technologies web ouvertes. « S&#8217;il avait dit quoique ce soit sur l&#8217;importance de la liberté de l&#8217;utilisateur sur le web, son hypocrisie serait devenue explicite », déclare ainsi M.Sullivan.</p>
<p>Sullivan rappelle également qu&#8217;Apple utilise le format vidéo H.264 et non le codec open source Ogg Theora choisi par Firefox et Opera. Par ailleurs le web libre que Steve Jobs souhaite déployer ne reste accessible qu&#8217;au travers d&#8217;un système propriétaire, qu&#8217;il s&#8217;agisse de l&#8217;iPhone OS ou de Mac OS X. John Sullivan conclut ainsi : « un web libre nécessite un logiciel libre. Vous n&#8217;aurez pas d&#8217;Internet libre si votre logiciel accédant à la Toile est limité à un nombre arbitraire d&#8217;ordinateurs ». Au sein du débat pour un Internet libre et ouvert, la fondation souhaite alors recentrer ce dernier vers le logiciel libre. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=233</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bacula, Sauvegarde sur Disque Dur</title>
		<link>http://blog.pepita.org/?p=230</link>
		<comments>http://blog.pepita.org/?p=230#comments</comments>
		<pubDate>Tue, 06 Apr 2010 06:19:57 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[NX]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[Bacula]]></category>
		<category><![CDATA[sauvegarde]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=230</guid>
		<description><![CDATA[Introduction
Le volume de données utilisées en entreprise croît de façon exponentielle depuis   plusieurs années, leur criticité aussi.
Quand on sait que 70% des entreprises qui subissent un crach informatique majeur   font faillite dans les 2ans, on comprend que préserver l&#8217;intégrité des données   est primordial.
 Un système de sauvegarde fiable, robuste [...]]]></description>
			<content:encoded><![CDATA[<h1>Introduction</h1>
<p>Le volume de données utilisées en entreprise croît de façon exponentielle depuis   plusieurs années, leur criticité aussi.</p>
<p>Quand on sait que 70% des entreprises qui subissent un crach informatique majeur   font faillite dans les 2ans, on comprend que préserver l&#8217;intégrité des données   est primordial.<br />
 Un système de sauvegarde fiable, robuste et performant n&#8217;est donc pas du luxe   pour quiconque manipule plusieurs giga octets de données quotidiennement.</p>
<p>La sauvegarde est une tâche gourmande en place et en temps de réalisation, il   faut donc trouver une solution de sauvegarde mutualisée qui rende cette tâche   la plus sûre et la moins fastidieuse possible.<br />
 Cette article est basé sur la suite logiciel Bacula qui vous allez le voir est   une solution de sauvegarde de niveau profesionnel.</p>
<p><span id="more-230"></span></p>
<h1>1. Les différentes solutions de sauvegarde</h1>
<h2>1.1. Solutions libres</h2>
<p>Il existe un grand nombre de projets de sauvegarde mutualisée client/serveur en open source, parmi  lesquels <strong>Amanda</strong>, <strong>Remote Backup</strong> &amp; <strong>Bacula</strong>.<br />
Nombre de ces projets sont encore en developpement et comportent des bugs, il convient donc d&#8217;être très vigilant quand à la solution à adopter en production puisqu&#8217;il serait cocace que votre système de sauvegarde, sur lequel vous misez tous vos espoirs en cas de coup dur souffre d&#8217;un bug au moment de la récupération des données critiques.</p>
<p>J&#8217;ai choisi le projet <strong>Bacula</strong> <a href="http://www.bacula.org/">(www.bacula.org</a>) car il a acquit une certaine maturité et est développé par une équipe de professionnels. De plus, il possède un panel de fonctionnalités epoustouflant, bien que certaines ne soient pas encore implémentées.<br />
Ce projet est porté sur la distribution Debian, il est donc très aisé à maintenir.<br />
Sa prise en main et sa configuration restent néanmoins deux choses particulièrement délicates et déroutantes, je vous invite donc à vous réferez au copieux manuel (491 pages) après avoir lu cet article.</p>
<h2>1.2. Solutions commerciales</h2>
<p>Tous les grands constructeurs de matériel informatique proposent des matériels accompagnés de solutions logicielles de sauvegardes, propriétaires ou non.<br />
Vu la spécificité de chacune des ces solutions et surtout leur coût de déploiement et de fonctionnement, je ne m&#8217;y interesserais pas dans cet article.</p>
<h2>1.3. Pourquoi un système de sauvegarde sur Disque?</h2>
<p>Historiquement la sauvegarde utilisait comme media les bandes magnétiques, permettant de stocker un volume collossal de données.<br />
La donne a légérement changé ces dernières années, en effet : <br />
- La taille des Disques Durs a considérablement augmenté (de quelques Gigaoctets il y a peu à plusieurs centaines maintenant).<br />
- Le prix de revient du Gigaoctet sur disque dur à baissé de façon significative.<br />
- Les disques IDE durs nouvelle génération ont gagné indéniablement en fiabilité.</p>
<p>La sauvegarde sur Disque Dur permet donc :<br />
- Une sécurité des données proche de celle des Bandes magnétiques avec l&#8217;utilisation de la technologie RAID.<br />
- Une vitesse des phases de sauvegarde mais surtout de restauration multipliée par 30 par rapport aux sauvegardes sur bandes.<br />
- Une mise en place à moindre coût puisqu&#8217;il n&#8217;est plus nécessaire d&#8217;acheter de matériel onéreux, toutes les cartes mères sont équipées de controleurs IDE, il suffit donc d&#8217;acheter les disques nécessaires à la sauvegarde.</p>
<p>L&#8217;utilisation des Bandes magnétiques permet cependant une fiabilité supérieure de part la nature du support (insensible aux chocs) et offre la possibilité d&#8217;emmener les bandes quotidiennement dans un lieu sécurisé, permettant une récupération en cas de gros dégats matériels sur le serveur de stockage.<br />
L&#8217;utilisation couplée de ces 2 systèmes est une éventualité qui offre une très grande souplesse, mais peut se révéler complexe a mettre en oeuvre au début.</p>
<h1>2. Le projet Bacula</h1>
<h2>2.1. Présentation</h2>
<p>Bacula est un projet de sauvegarde réseau client/serveur professionel ambitieux.<br />
Il offre une modularité hors du commun, en effet chaque étape de la sauvegarde est décomposée en un &#8220;daemon&#8221; associé et permet donc d&#8217;assouplir considérablement l&#8217;architecture du sytème de sauvegarde.<br />
Il permet de sauvegarder sur de nombreux médias (Disques dur, bandes magnétiques, prise en charge des chargeurs de bandes&#8230;), cependant je ne traiterais ici que les fonctionnalités de sauvegarde sur disques puisque c&#8217;est le thème de cet article.</p>
<p>On peut assimilier Bacula à une suite de plusieurs logiciels, chacun affecté à une tâche propre (une des bases de la philosophie linux).<br />
Bacula est sous licence GPLv2.</p>
<h2>2.2. Architecture du logiciel</h2>
<p>Un schéma vaut parfois mieux que de longues explication, je reprend ici celui du manuel qui est très bien fait :</p>
<p><img src="http://www.supinfo-projects.com/fr/2005/bacula/2/architecture.jpg" alt="" /></p>
<h3>2.2.1 Le directeur</h3>
<p>C&#8217;est le coeur du système de sauvegarde, c&#8217;est lui qui &#8220;commande&#8221; et qui unit les différents éléments.<br />
Il se présente sour la forme d&#8217;un daemon : <em>bacula-dir</em> qui écoute sur le port 9101.<br />
Il ne peut y avoir qu&#8217;un directeur par architecture de sauvegarde (pas de réplication).</p>
<h3>2.2.2 Le Storage Daemon</h3>
<p>Il est chargé de l&#8217;enregistrement physique des données qui lui sont fournies, c&#8217;est lui qui gère l&#8217;interaction avec le matériel, dans cet article il s&#8217;agira de disques durs. Le matériel doit donc être connecté &#8220;logiquement&#8221; au serveur qui éxécute ce storage daemon (il doit être &#8220;monté&#8221;).<br />
Ce daemon, <em>bacula-sd</em>, écoute sur le port 9103.<br />
Il reçoit les ordres du directeur mais aussi et surtout les données directement du Filer Daemon (voir ci dessous).<br />
A noter qu&#8217;il peut evidemment y avoir plusieurs storage daemon par architecture de sauvegarde.</p>
<h3>2.2.3 Le Filer Daemon</h3>
<p>C&#8217;est la partie cliente à proprement parler du logiciel puisque c&#8217;est ce daemon qui sera executé sur les machines contenant les données à sauvegarder.<br />
Il s&#8217;appelle <em>bacula-fd</em>, écoute sur le port 9102, reçoit les ordres du directeur et envoie les données directement au Storage Daemon.<br />
La compression (optionnelle) a lieu au niveau de ce daemon, limitant ainsi la charge sur les machines executant le directeur et les storage daemon et permettant aussi de limiter le volume de données transitant sur le réseau.</p>
<p>Note : il existe en version Unix/linux &amp; windows</p>
<h3>2.2.4 La console</h3>
<p>C&#8217;est elle qui permet de contrôler le directeur, mais aussi directement les filer et storage daemons.<br />
Elle peut être executée sur une machine disctinte (connexion par le port 9101).<br />
Il existe une version gnome, mais celle ci ne présente pour l&#8217;instant que très peu d&#8217;intérêt.</p>
<h3>2.2.5 Le catalogue</h3>
<p>C&#8217;est la base de données du système de sauvegarde, elle contient les attributs et caractéristiques de vos fichiers et de vos différentes sauvegardes, elle est stockée dans une base de type MySQL, SQLLite ou postgresql qui peut être hebergée sur une machine tierce. (communication par le port 3106 avec le directeur).<br />
SQLLite est implétmenté en natif dans le projet Bacula, c&#8217;est donc lui qui est proposé par défaut et qui est conseillé si aucun sgbd n&#8217;est installé sur la machine.</p>
<p><br class="spacer_" /></p>
<h1>3. Définition d&#8217;un plan de sauvegarde</h1>
<h2>3.1. Les types de sauvegarde</h2>
<p>Je vais faire ici un rappel des différents types de sauvegarde qui existent et que l&#8217;on retrouve dans Bacula.</p>
<h3>3.1.1 Sauvegarde complète</h3>
<p>Tous les fichiers selectionnés sont sauvegardés, qu&#8217;ils aient changé ou pas, et sont marqués comme tels dans le catalog.<br />
Ce niveau de sauvegarde est de loin le plus gourmand en temps et en espace disque, mais il est evidemment nécessaire à tout plan de sauvegarde, c&#8217;est la base de la sauvegarde.</p>
<h3>3.1.2 Sauvegarde differentielle</h3>
<p>Seuls les fichiers ayant été crées ou modifiés depuis la dernière sauvegarde COMPLETE sont sauvegardés. <br />
Ce niveau de sauvegarde permet de ne sauvegarder que les modifications et est donc plus rapide à executer et moins gourmand en terme de place.</p>
<h3>3.1.3 Sauvegarde incrementielle</h3>
<p>Tout comme la sauvegarde differentielle, la sauvegarde incrementielle ne concerne que les fichiers crées ou modifiés.<br />
Ce qui différencie ces 2 niveaux de sauvegarde c&#8217;est qu&#8217;à l&#8217;instar de la sauvegarde differentielle qui se réfère à la derniere sauvegarde complete connue, la sauvegarde incrementielle se réfère à la dernière sauvegarde quelque soit son type, qu&#8217;elle soit complete, differentielle ou même incrementielle.<br />
Le gros avantage est que l&#8217;on gagne encore en place et en temps de sauvegarde.</p>
<h3>3.1.4 Différences pratiques entre sauvegardes differentielle et incrementielle</h3>
<p>Nous l&#8217;avons vu precedemment, le sauvegarde incrementielle ne sauvegarde que ce qui a été modifié depuis la derniere sauvegarde, ce qui permet donc de sauvegarder moins.<br />
Le principal risque est que si vous perdez un volume sur lequel est stockée une sauvegarde incrementielle à laquelle une autre sauvegarde incrementielle plus recente s&#8217;est référée, vous perdez l&#8217;historique des données.<br />
Alors que dans le cas de 2 sauvegardes différentielles, vous n&#8217;auriez rien perdu puisque la seconde se serait référée non pas à la premiere mais directement à la sauvegarde complete originale.<br />
Il y a dans ce cas redondance de l&#8217;information concernant les modification effectuées, mais aussi plus grande sécurité.</p>
<h2>3.2. Exemples de stratégies</h2>
<p>Une stratégie de sauvegarde est essentielle, elle permet de définir les données à sauvegarder, les eventuels historiques à conserver et elle permet surtout d&#8217;approximer l&#8217;espace nécessaire. Attention, prévoyez toujours très large! L&#8217;espace occupé par les données est toujours fortemment croissant!<br />
De plus, il est toujours très difficile d&#8217;estimer la quantité de données crées ou modifiées chaque jour, il s&#8217;agira là d&#8217;approximations.<br />
Afin d&#8217;éclaircir les choses, mettons en pratique les différents types de sauvegarde à travers des plans de sauvegarde concrets.</p>
<h3>3.2.1 Cas concret n°1</h3>
<p>Vous possédez 100Go de données critiques, accédées quotidiennement du lundi au samedi.<br />
Ces données sont frequemment modifiées, à raison d&#8217;environ 1Go / jour et du fait de leur criticité vous souhaitez conserver un certain historique de ces modifications.</p>
<p>Exemple de plan de sauvegarde:<br />
- sauvegarde complete mensuelle le premier dimanche du mois, convervée 2 mois.<br />
- sauvegarde différentielle hebdomadaire le dimanche, conservée 5 semaines.<br />
- sauvegarde incrementielle journaliere la nuit, conservée 14 jours.</p>
<p>Espace necessaire:</p>
<p>2 sauvegardes completes : 2*100Go = 200Go<br />
&#8212;&gt; On conserve la sauvegarde complete en cours et la précendente.<br />
5 sauvegardes différentielles : 6+12+18+24+30 = 90Go<br />
&#8212;&gt; On conserve 5 semaines d&#8217;historique de sauvegarde différentielle hedbomadaire.</p>
<p><strong>RAPPEL</strong> : cette sauvegarde se base sur la derniere sauvegarde  complete, le volume de données augmente donc d&#8217;autant plus que la sauvegarde complète  est ancienne.</p>
<p>12 sauvegardes incrementielles : 12*1Go = 12Go<br />
&#8212;&gt; On conserve 2 semaines soit 12 jours (le dimanche la sauvegarde differentielle  a lieu) de sauvegarde incrementielle.</p>
<p><strong>Total</strong> : 302Go nécessaires soit environ 3 fois la taille  de vos données.</p>
<p>Ceci permet à n&#8217;importe quel moment d&#8217;avoir:<br />
- un historique journalier des modifications pour les 14 derniers jours<br />
- un historique hebdomadaire des modifications pour les 5 dernieres semaines<br />
- deux historiques mensuels.</p>
<h3>3.2.2 Cas concret n°2</h3>
<p>Vous possédez 20Go de données critiques, ces données bougent peu (env. 100Mo modifiés/jour) et le suivi des modifications n&#8217;est pas essentiel pour vous.</p>
<p>Exemple de plan de sauvegarde:<br />
- sauvegarde complete hebdomadaire, conservée 2 semaines.<br />
- sauvegarde incrementielle journaliere, conservée 7 jours.</p>
<p>Espace necessaire:<br />
2 sauvegarde complètes : 2*20Go = 40Go<br />
6 sauvegardes incrementielles : 6*100Mo = 600Mo</p>
<p><strong>Total</strong> : 40,6Go</p>
<p><br class="spacer_" /></p>
<h1>4. Configuration de Bacula</h1>
<h2>4.1. Installation</h2>
<h3>4.1.1 Debian</h3>
<p>Bacula est porté sur la distribution Debian, il est donc très facile à installer.</p>
<p>Pour installer la suite complète :<br />
<strong><em>DebianBox:~#Apt-get install bacula</em></strong></p>
<p>A noter qu&#8217;avec cette méthode c&#8217;est le paquet bacula-director-sqlite qui sera  installé par défaut, libre à vous de choisir bacula-director-mysql ou bacula-director-pgsql.</p>
<p>Pour n&#8217;installer que la partie FD (FilerDaemon) sur un serveur &#8220;à sauvegarder&#8221;:<br />
<strong><em>DebianBox:~#Apt-get install bacula-fd</em></strong></p>
<p>Pour n&#8217;installer que la console d&#8217;administration, sur une machine qui servira à controler le directeur, les StorageDaemons ou FilerDaemons:<br />
Pour la version texte :<br />
<strong><em>DebianBox:~#Apt-get install bacula-console</em></strong></p>
<p>Pour la version Gnome :<br />
<strong><em>DebianBox:~#Apt-get install bacula-console-gnome</em></strong></p>
<h3>4.1.2 Rpm &amp; &#8220;from source&#8221;</h3>
<p>Bacula existe aussi en RPM, pour cela je vous conseille <a href="http://www.rpmfind.net/">www.rpmfind.net</a> afin de trouver le paquet le plus récent.<br />
Si vous souhaitez compiler Bacula à partir des sources afin qu&#8217;il corresponde exactement à vos attentes en environnement de production, je vous invite à vous reporter au manuel officiel sur <a href="http://www.bacula.org/">www.bacula.org</a>, le nombre d&#8217;options étant assez conséquent.</p>
<h2>4.2. Configuration des FD</h2>
<p>Une fois Bacula installé sur vos différents serveurs, il faut configurer les Filer Daemons qui tourneront, je vous le rappelle, sur les machines contenant les données à sauvegarder.<br />
Le fichier de configuration se nomme <em>bacula-fd.conf</em> et se trouve dans  <em>/etc/bacula</em> sous debian.<br />
Il est composé de 3 éléments : <br />
- la définition des Directeurs autorisés à l&#8217;administrer<br />
- la configuration du FD en lui-même<br />
- la configuration de l&#8217;envoi des messages.</p>
<p>Pour autoriser un Directeur à se connecter à un FD, il faut donner le nom du directeur et lui associer un mot de passe:<br />
<strong><em>Director {<br />
Name = nom-du-serveur-executant-le-directeur<br />
Password = &#8220;password&#8221;<br />
}</em></strong></p>
<p>Le champ FilerDaemon traite de la configuration en elle-même du FD<br />
Il faut définir le nom qui sera utilisé pour l&#8217;identifier depuis la console d&#8217;administration et spécifier le port sur lequel il va écouter (9102 par défaut).</p>
<p>Le champ Messages gère les messages spontanemment envoyés au directeur par le FD, indiquez ici le nom du directeur qui doit recevoir ces messages.</p>
<p><strong>Info</strong> : par défaut, debian configure ce fichier en mettant partout  le nom de la machine sur lequel le paquet est installé, veuillez donc à rectifier  si la machine n&#8217;est pas le directeur.</p>
<p>ATTENTION, ces fichiers de configuration sont à placer en local sur les  machines executant les FD, c&#8217;est à dire les machines &#8220;à sauvegarder&#8221;.</p>
<p><a href="http://www.supinfo-projects.com/fr/2005/bacula/4/serveur1_bacula-fd.zip">Télécharger le fichier d&#8217;exemple de configuration du FD du serveur 1</a></p>
<p><a href="http://www.supinfo-projects.com/fr/2005/bacula/4/serveur2_bacula-fd.zip">Télécharger le fichier d&#8217;exemple de configuration du FD du serveur 2</a></p>
<h2>4.3. Configuration du SD</h2>
<p>Sur le même principe que le FD, le fichier de configuration du SD (bacula-sd.conf) possède un objet Storage dans lequel il faut définir un nom pour ce Storage Daemon et un port sur lequel il tournera, un objet Director dans lequel il faut indiquer le directeur autorisé à administrer ce SD et un objet Messages concernant les messages envoyés au directeur.</p>
<p>Il possède en plus des objets Device qui concernent dans notre cas le(s) volume(s) Disque sur lequel vous souhaitez stocker vos sauvegardes.<br />
Il peut y avoir autant de Device que necessaire et idéalement un par serveur sauvegardé.</p>
<p><a href="http://www.supinfo-projects.com/fr/2005/bacula/4/bacula-sd.zip">Télécharger le fichier d&#8217;exemple de configuration du Storage Daemon</a></p>
<h2>4.4. Configuration du directeur</h2>
<p>Le SD et le FD sont maintenant configurés, il nous reste le gros du travail : le Directeur qui est au centre du système.<br />
Le fichier de configuration se nomme<em> bacula-dir.conf</em></p>
<p>L&#8217;objet <strong>Director</strong> touche à la configuration du directeur lui-même,  comme partout il faut le nommer et définir le password (necessaire pour contrôler  ce directeur depuis la console).<br />
A noter la propriété <em>&#8220;Maximum Concurrent Jobs&#8221;</em> qui définit le nombre de tâches que Bacula peut lancer simultanement.</p>
<p>L&#8217;objet <strong>FileSet</strong> définit l&#8217;ensemble des fichiers à sauvegarder,  généralement pour un serveur donné. (les chemins d&#8217;accès aux données étant différent  d&#8217;un serveur à l&#8217;autre).<br />
Il convient donc d&#8217;en créer autant que necessaire, en incluant de préférence le nom du serveur concerné dans le nom de FileSet afin de savoir de quoi il retourne.<br />
C&#8217;est à ce niveau que l&#8217;on définit la compression et/ou la signature des fichiers.<br />
Bacula gère les algorythmes SHA1 et MDA pour la signature et GZIP(GZIP6) et GZIP9 pour la compression.<br />
Je vous rappelle que cette compression a lieu en local sur le serveur de fichiers  avant l&#8217;envoi des données par le réseau, elle impactera donc sur la charge de  celui-ci.</p>
<p>L&#8217;objet <strong>Schedule</strong> définit un modèle de planification (voir exemple).</p>
<p>L&#8217;objet <strong>Client</strong> donne les informations concernant les différents  FD au directeur (nom, adresse, mot de passe, port&#8230;)<br />
On définit à ce niveau combien de temps les fichiers et les jobs sont conservé dans le Catalog.<br />
Si l&#8217;option <em><strong>AutoPrune</strong></em> est définit à <strong><em>YES</em></strong>,  ces infos sont effacées automatiquement du Catalog lorsque le laps de temps est  ecoulé.</p>
<p>L&#8217;objet <strong>Storage</strong> donne les informations concernant les différents  SD au directeur, et se réfère a un Device (précedemment définis dans le fichier  <em>bacula-sd.conf</em>).<br />
Dans notre cas, il faut mettre <strong><em>Media Type = File</em></strong> puisque  l&#8217;on va sauvegarder sur un Disque Dur.</p>
<p>L&#8217;objet <strong>Catalog</strong> contient les paramètres de la base de donnée utilisée  pour stocker les informations.</p>
<p>L&#8217;objet <strong>pool</strong> définit des ensembles de volumes(dans notre cas  un volume sera un fichier) et permet par exemple de stocker toutes les sauvegardes  de type &#8220;Full&#8221; ensembles etc.<br />
A noter qu&#8217;un pool par défaut est necessaire.</p>
<p>Il reste maintenant l&#8217;objet <strong>Job</strong> qui definit une tâche de sauvegarde  à proprement parler, il y en aura donc autant que nécéssaire.<br />
Un job peut être de plusieurs types : Backup, Restore, Verify &amp; Admin.<br />
- Backup, comme son nom l&#8217;indique définira une tâche de sauvegarde.<br />
- Verify permet de vérifier que les informations de sauvegardes stockées dans le Catalog correspondent bien à ce qui est stocké physiquement sur le support.<br />
- Restore permet de récuperer des données sauvegardées.</p>
<p>ATTENTION, je vous conseille fortemment de définir vos jobs &#8220;restore&#8221; en même temps  que vos jobs &#8220;Backup&#8221;, il n&#8217;est en effet pas possible de restaurer quelques données  que ce soit sans qu&#8217;un job restore soit convenablement défini et il est rageant  de perdre un temps précieux à définir ce type de job lorsque l&#8217;on a besoin de  restaurer des données.</p>
<p>Je ne traiterais pas du type Admin dans cet article.</p>
<p>Pour un Job de type Backup, il vous faut spécifier les Client, FileSet, Schedule, Storage et Pool que nous avons précedemment déclarés.<br />
L&#8217;option Write Boostrap permet de conserver le Bootstrap d&#8217;un disque dur sauvegardé avec Bacula, de façon a pouvoir remettre sur pied un système crashé le plus rapidement possible.<br />
L&#8217;option Priority définit quel Job s&#8217;executera en premier lorsque plusieurs Jobs  sont planifiés en même temps.</p>
<p><a href="http://www.supinfo-projects.com/fr/2005/bacula/4/bacula-dir.zip">Télécharger le fichier d&#8217;exemple de configuration du Director</a></p>
<h2>4.5. Prise en main de la console</h2>
<p>Autant vous le dire tout de suite, la console d&#8217;administration n&#8217;est pas le point fort de Bacula. Elle existe en version Gnome mais n&#8217;offre selon moi aucun interet supplémentaire par rapport à la version texte.<br />
Pour la lancer, placer vous dans /etc/bacula et executez bconsole.<br />
Voici une liste non-exhaustive des commandes qui vous permetront de démarrer:<br />
<strong>HELP</strong> : permet de lister toutes les commandes disponibles ainsi  qu&#8217;une description sommaire.<br />
<strong>RUN</strong> : permet de forcer le démarrage d&#8217;un job, à des fins de tests  par exemple.<br />
<strong>LIST</strong> (pools | jobs | jobtotals | media  | files jobid=)  : affiche le contenu du catalog.<br />
<strong>STATUS</strong> : affiche l&#8217;état des jobs en cours. Cette commande se  connecte directement au directeur, au SD ou au FD.</p>
<p><a href="http://www.supinfo-projects.com/fr/2005/bacula/4/bconsole.zip">Télécharger le fichier d&#8217;exemple de configuration de la console</a></p>
<p><br class="spacer_" /></p>
<h1>Conclusion</h1>
<p>Cet article vous a présenté les principales fonctionnalités de Bacula dans son utilisation en tant que serveur de sauvegarde sur Disque dur.<br />
J&#8217;espère que ce logiciel vous aura convaincu et je vous invite si c&#8217;est le cas à vous plonger dans le copieux mais complet manuel d&#8217;utilisation.<br />
A noter que la sauvegarde mutualisée sur disque n&#8217;est qu&#8217;une infime partie des possibilités qu&#8217;offre Bacula, cet article n&#8217;a pas la prétention d&#8217;en faire une présentation exhausitive.</p>
<p>Infos et téléchargements : <a href="http://www.bacula.org/">www.bacula.org</a></p>
<p>[filebase:file:file4]</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" src="http://img.zemanta.com/pixy.gif?x-id=27268ffa-43bd-8ba4-a677-39c6d785850c" alt="" /></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=230</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SVK versionning</title>
		<link>http://blog.pepita.org/?p=227</link>
		<comments>http://blog.pepita.org/?p=227#comments</comments>
		<pubDate>Mon, 05 Apr 2010 18:12:43 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[CVS]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[versionning]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=227</guid>
		<description><![CDATA[SVK
Article publié dans Linux Magazine 94, mai 2007.
Copyright © 2007 &#8211; Nicolas Chuche


 

Index
Introduction
Installation
Utilisation simple

Création d&#8217;un dépôt local
Travailler sur un projet déjà dans un dépôt
Créer un nouveau projet à partir de fichiers existants
Travailler sur votre projet
Mettre à jour les fichiers locaux à partir du dépôt
Regarder l&#8217;historique des modifications
Quelques autres commandes
Quelques options bien utiles


Utilisation avancée

Les branches [...]]]></description>
			<content:encoded><![CDATA[<h1>SVK</h1>
<p>Article publié dans Linux Magazine 94, mai 2007.</p>
<p>Copyright © 2007 &#8211; Nicolas Chuche</p>
<p><span id="more-227"></span></p>
<div></div>
<p><!-- INDEX BEGIN --> </p>
<ul id="index">
<li id="index-toc">Index</li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h1">Introduction</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h2">Installation</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3">Utilisation simple</a>
<ul>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.1">Création d&#8217;un dépôt local</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.2">Travailler sur un projet déjà dans un dépôt</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.3">Créer un nouveau projet à partir de fichiers existants</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.4">Travailler sur votre projet</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.5">Mettre à jour les fichiers locaux à partir du dépôt</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.6">Regarder l&#8217;historique des modifications</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.7">Quelques autres commandes</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h3.8">Quelques options bien utiles</a></li>
</ul>
</li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4">Utilisation avancée</a>
<ul>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.1">Les branches et les tags</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.2">Travailler en mode déconnecté</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.3">Proposer des modifications quand vous n&#8217;avez pas les droits d&#8217;écriture sur le dépôt</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.4">Répliquer un dépôt local sur un dépôt distant</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.5">Métadonnées ou propriétés</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h4.6">Configuration de SVK</a></li>
</ul>
</li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h5">Éléments de méthode de travail</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h6">SVK version 2</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h7">Quelques idées en l&#8217;air</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h8">Conclusion</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h9">Les liens</a></li>
<li><a href="http://articles.mongueurs.net/magazines/linuxmag94.html#h10">Ours</a></li>
</ul>
<p><!-- INDEX END --></p>
<div>
<h1>Chapeau de l&#8217;article</h1>
<p>Cet article est un tutoriel pour le logiciel de gestion de versions SVK, qui est parti du constat que, ayant besoin de SVK et ne le connaissant pas bien, le meilleur moyen de le maîtriser était d&#8217;approfondir mes connaissances et de les organiser dans un tutoriel à destination d&#8217;un public le plus large possible.</p>
</div>
<div><a name="h1"></a></p>
<h1><a name="h1">Introduction</a></h1>
<p><a name="h1">Pour Wikipédia, la gestion de versions est « une activité qui consiste à maintenir l&#8217;ensemble des versions d&#8217;un logiciel ». Si vous êtes développeur, il y a de bonnes chances que vous ayez à gérer cette activité et que vous connaissiez déjà un outil de gestion de versions comme CVS, Subversion ou équivalent.</a></p>
<p><a name="h1">Écrit il y a plus de 20 ans, CVS est sans doute le grand-père le plus connu des outils de gestion de versions libre. Bien qu&#8217;encore très utilisé de par le monde, il a un certain nombre de faiblesses gênantes (impossible de déplacer des fichiers en conservant l&#8217;historique, pas d&#8217;atomicité des transactions, pas de dépôts décentralisés, etc.) que les nouveaux outils n&#8217;ont plus.</a></p>
<p><a name="h1">De nombreux remplaçants ont vu le jour. Certains sont généralistes (Bazaar, Subversion, SVK, Mercurial, etc.) tandis que d&#8217;autres sont développés spécifiquement pour un projet (Git pour le noyau linux).</a></p>
<p><a name="h1">Dans cet article, je parlerai de SVK qui est un client. Pourquoi  celui-ci et pas un autre ? Plusieurs raisons à cela :</a></p>
<ul>
<li>
<p><a name="h1">ça fait un certain temps que j&#8217;en entends parler dans la communauté Perl ;</a></p>
</li>
<li>
<p><a name="h1">il apporte des fonctionnalités déterminantes par rapport à ses concurrents (dépôts décentralisés, permet de réaliser des opérations même si l&#8217;on a pas accès au réseau, systèmes de branches et de fusions très évolués, etc.) ;</a></p>
</li>
<li>
<p><a name="h1">SVK est un client qui sait communiquer avec plusieurs serveurs de gestion de versions dont Subversion, logiciel de plus en plus répandu, mais aussi CVS et Perforce même si c&#8217;est avec des fonctionnalités plus réduites ;</a></p>
</li>
<li>
<p><a name="h1">et enfin parce que les Mongueurs de Perl viennent de migrer leur dépôt de CVS vers Subversion (cf point précédent) et que j&#8217;ai besoin d&#8217;y avoir accès.</a></p>
</li>
</ul>
<p><a name="h1">SVK a été développé en 2003 par Chia-liang Kao pour ses besoins. Il s&#8217;est appuyé sur le système de fichiers de Subversion (<code>svn</code>) et a redéveloppé toute la couche haute. Les commandes utilisées sont néanmoins très proches de celle de Subversion et de CVS, les utilisateurs de ces produits ne seront donc pas totalement dépaysés. SVK a été acquis par Best Practical (le fameux éditeur de Request Tracker) en 2006 et Chia-liang Kao est devenu partenaire de Jesse Vincent chez Best Practical.</a></p>
</div>
<div><a name="h2"></a></p>
<h1><a name="h2">Installation</a></h1>
<p><a name="h2">L&#8217;installation de SVK est d&#8217;une simplicité légendaire s&#8217;il est disponible sous forme de paquets :</a></p>
<pre><a name="h2">  % sudo aptitude install svk       # Debian et dérivées
  % sudo urpmi svk                  # Mandriva</a></pre>
<p><a name="h2">Sous Windows il existe un portage trouvable ici </a><a href="http://home.comcast.net/%7Eklight/svk/">http://home.comcast.net/~klight/svk/</a></p>
<p>Si aucun paquet de SVK n&#8217;existe pour votre distribution, vous allez devoir passer par un shell d&#8217;installation Perl, CPAN ou CPANPLUS.</p>
<pre>  % sudo cpan SVK       # avec CPAN.pm
  % cpanp i SVK         # avec CPANPLUS</pre>
<p>Comme me le souffle un camarade, une installation « à la main » n&#8217;est pas des plus simples car il vous faudra installer ou compiler un Subversion avec les bindings Perl. Vous pourrez trouver de l&#8217;aide sur le wiki de SVK : <a href="http://svk.bestpractical.com/view/InstallingSVK">http://svk.bestpractical.com/view/InstallingSVK</a>.</p>
</div>
<div><a name="h3"></a></p>
<h1><a name="h3">Utilisation simple</a></h1>
<p><a name="h3">Avant d&#8217;entrer dans le vif du sujet, nous allons aborder quelques notions utilisées par les logiciels de gestion de versions, et par SVK en particulier.</a></p>
<ul>
<li>
<p><a name="h3">Le dépôt (<em>repository</em> en anglais) est un système de fichiers spécial dans lequel sont stockées toutes les données (fichiers et répertoires) ainsi que toutes les modifications apportées au fur et à mesure. Il est, au choix, local ou déporté sur une machine distante. On peut y accéder par différents protocoles et il peut être utilisé par plusieurs personnes en même temps. C&#8217;est la partie principale d&#8217;un outil de gestion de versions. Un même dépôt peut contenir autant de projets différents que vous le désirez.</a></p>
</li>
<li>
<p><a name="h3">La « copie de travail » est un vrai répertoire contenant des&#8230; fichiers et des répertoires se trouvant également dans le dépôt. C&#8217;est dans ce répertoire que vous travaillerez (seul) sur votre projet avant de publier vos modifications sur le dépôt pour les rendre accessibles à tout le monde (ou du moins à tous les gens qui ont accès au dépôt). Vous pouvez avoir autant de copies de travail que vous voulez.</a></p>
</li>
</ul>
<p><a name="h3">Pour ne pas vous surcharger dès l&#8217;introduction de notions plus ou moins complexes sans avoir pratiqué, je reviendrai au fur et à mesure de cet article sur quelques autres notions importantes.</a></p>
<p><a name="h3.1"></a></p>
<h2><a name="h3.1">Création d&#8217;un dépôt local</a></h2>
<p><a name="h3.1">La première étape est de créer un dépôt sur votre machine :</a></p>
<pre><a name="h3.1">  % svk depotmap --init
  Repository /home/test/.svk/local does not exist, create? (y/n)y</a></pre>
<p><a name="h3.1">Comme indiqué dans le retour de la commande, elle crée votre dépôt dans votre répertoire personnel dans le répertoire <em>.svk/local</em>.</a></p>
<p><a name="h3.1">Afin de promouvoir le plus tôt possible les bonnes pratiques, nous allons dès maintenant structurer le contenu de ce dépôt de façon à organiser judicieusement les travaux à venir. Nous verrons plus tard l&#8217;intérêt direct de l&#8217;organisation proposée.</a></p>
<pre><a name="h3.1">  % svk mkdir //local/ -m 'creation du repertoire local'
  Committed revision 1.</a></pre>
<p><a name="h3.1">Quand je parle de répertoire, il s&#8217;agit bel et bien de cela. Mais celui-ci n&#8217;est pas sur votre système de fichier, il se trouve dans le dépôt SVK, c&#8217;est pour cela qu&#8217;on les appelle <em>« depot path »</em> ou « chemin de dépôt ». Pour ne pas confondre les chemins du système de fichier avec ceux du dépôt SVK, le chemin de dépôt par défaut est préfixé de deux <em>slashes</em> (<em>/</em>). <em>//local</em> est donc votre premier  chemin de dépôt.</a></p>
<p><a name="h3.2"></a></p>
<h2><a name="h3.2">Travailler sur un projet déjà dans un dépôt</a></h2>
<p><a name="h3.2">La syntaxe normale pour récupérer les fichiers d&#8217;un dépôt centralisé est :</a></p>
<pre><a name="h3.2">  % svk checkout protocole://le.serveur.net/le/chemin/mon/appli repertoire</a></pre>
<p><a name="h3.2">Quand vous allez taper cette commande pour la première fois, <code>svk</code> va vous poser trois questions :</a></p>
<ul>
<li>
<p><a name="h3.2">de quoi faire le miroir (en fait l&#8217;action <code>checkout</code> va conserver une copie locale du dépôt). Vous pouvez laisser la configuration par défaut.</a></p>
</li>
<li>
<p><a name="h3.2">quel chemin utiliser pour créer ce miroir. Je vous conseille de le mettre sous <em>//mirror/nomduprojet/</em> nous verrons plus tard pourquoi.</a></p>
</li>
<li>
<p><a name="h3.2">si vous voulez récupérer toutes les versions ou seulement les plus récentes. La réponse par défaut convient dans tous les cas bien que pouvant être plus longue. C&#8217;est donc celle que je vous conseille.</a></p>
</li>
</ul>
<p><a name="h3.2">Juste pour information, nous venons de voir notre second chemin de dépot à savoir <em>//mirror/</em>. Celui-ci est en fait un chemin spécial qui, par convention, sert à stocker tous les miroirs que l&#8217;on va faire avec SVK. Vous pourrez voir la liste de tous les miroirs que vous avez créés en faisant :</a></p>
<pre><a name="h3.2">  % svk mirror --list
  Path                	Source
  ============================================================
  //mirror/mesprojets    	https://mon.serveur.com/svn
  //mirror/mongueurs
       svn+ssh://autre.serveur.com/home/nc/.svk/local/local/mongueurs/trunk</a></pre>
<p><a name="h3.2">Voyons maintenant un exemple (pour redmine, voir dans les références à la fin de cet article) :</a></p>
<pre><a name="h3.2">  % svk checkout svn://rubyforge.org/var/svn/redmine/
  New URI encountered: svn://rubyforge.org/var/svn/redmine/
  Choose a base URI to mirror from (press enter to use the full URI): 

  [...]

  Depot path: [//mirror/redmine] 

  [...]

  a)ll, h)ead, -count, revision? [a]
  Syncing svn://rubyforge.org/var/svn/redmine
  Retrieving log information from 1 to 21
  Committed revision 10297 from revision 1.
  [...]
  Syncing //mirror/redmine(/mirror/redmine) in /home/nc/tmp/redmine to
     10317.</a></pre>
<p><a name="h3.2">Toutes les commandes de <code>svk</code> peuvent être raccourcies. En l&#8217;occurrence, le raccourci de <code>checkout</code> est <code>co</code>.</a></p>
<p><a name="h3.2">Si le dépôt utilise un serveur SVN, le protocole sera <code>svn</code>, si le serveur utilise WebDAV, le protocole sera <code>http</code> ou <code>https</code> :</a></p>
<pre><a name="h3.2">  % svk checkout svn://rubyforge.org/var/svn/redmine/trunk redmine

  % svk checkout https://rubyforge.org/var/svn/redmine/trunk redmine</a></pre>
<p><a name="h3.2">Ou encore si vous avez accès au dépôt par <code>ssh</code> :</a></p>
<pre><a name="h3.2">  % svk checkout svn+ssh://rubyforge.org/var/svn/redmine/trunk redmine</a></pre>
<p><a name="h3.2">Vous avez dû remarquer que j&#8217;ai utilisé le chemin <em>/var/svn/redmine/trunk</em>. Pourquoi <em>trunk</em> (tronc en français), pourquoi pas directement <em>redmine</em> ? Parce que <em>trunk</em> représente le développement principal et qu&#8217;il y a également des répertoires <em>tags</em> et <em>branches</em> permettant des « branches » de développements parallèles ainsi que la conservation de versions particulièrement intéressantes, mais n&#8217;avançons pas trop vite, nous verrons un peu plus loin pourquoi et comment nous en servir.</a></p>
<p><a name="h3.3"></a></p>
<h2><a name="h3.3">Créer un nouveau projet à partir de fichiers existants</a></h2>
<p><a name="h3.3">Vous avez déjà un répertoire que vous souhaitez gérer avec SVK. La commande à utiliser est <code>import</code> :</a></p>
<pre><a name="h3.3">  % svk import --message 'import initial' monprojet/ //local/monprojet</a></pre>
<p><a name="h3.3">Avant de passer cette commande, je vous suggère fortement à la lumière de notre (très) rapide aperçu des branches, tags et trunk d&#8217;organiser un peu vos répertoires. Déplacez vos fichiers de travail dans <em>trunk</em> et créez les répertoires <em>branches</em> et <em>tags</em> afin d&#8217;obtenir dès maintenant une organisation comme celle-ci :</a></p>
<pre><a name="h3.3">  monprojet/branches/
            tags/
            trunk/&lt;tous vos fichiers et répertoires&gt;</a></pre>
<p><a name="h3.3">Nous voyons maintenant à quoi nous sert d&#8217;avoir créé le répertoire <em>//local</em>. Cela permet de placer vos projets dans une arborescence dédiée et de ne pas tout avoir à la racine de votre dépôt.</a></p>
<p><a name="h3.3">Une fois l&#8217;import réalisé, vous allez pouvoir faire un <code>checkout</code> comme vu dans la partie précédente et commencer à travailler réellement. Pour ne récupérer que la version en cours de développement (soit <em>trunk</em>) et non toute l&#8217;arborescence, la commande à passer est :</a></p>
<pre><a name="h3.3">  % svk checkout //local/monprojet/trunk monprojet</a></pre>
<p><a name="h3.3">Vous auriez pu transformer directement le répertoire utilisé en version de travail en ajoutant l&#8217;option <code>--to-checkout</code> (ou <code>-t</code>) :</a></p>
<pre><a name="h3.3">  % svk import --message 'import initial' -t monprojet/ //local/monprojet</a></pre>
<p><a name="h3.4"></a></p>
<h2><a name="h3.4">Travailler sur votre projet</a></h2>
<p><a name="h3.4">Ça y est, vous avez bien avancé sur votre nouvelle implémentation de logiciel de blog et vous voulez passer en revue vos modifications.</a></p>
<p><a name="h3.4">Plusieurs commandes vous seront utiles :</a></p>
<ul>
<li><a name="item_svk_diff"></a><strong>svk diff</strong>
<p>Vous donne un <code>diff</code> entre la version d&#8217;origine du dépôt et votre copie de travail. Cette commande peut prendre en argument un ou plusieurs fichiers/répertoires, vous ne verrez alors que leurs différences.</p>
</li>
<li><a name="item_svk_add"></a><strong>svk add</strong>
<p>Ajoute des fichiers ou des répertoires dans le dépôt</p>
<p>Les fichiers ne seront réellement ajoutés qu&#8217;au prochain commit (cf point suivant).</p>
<pre>  % svk add rep
  A   rep
  A   rep/a
  A   rep/b</pre>
<p>Cette commande est récursive, si vous ajoutez un répertoire, tous les fichiers contenus seront également ajoutés.</p>
<p>Vous pouvez ajouter tous les nouveaux répertoires et fichiers d&#8217;un seul coup en faisant :</p>
<pre>  % svk add .</pre>
<p>Un point intéressant à savoir, <code>svk</code> est (plus ou moins) intelligent, il n&#8217;ajoutera pas les fichiers de finissant par un « ~ » ainsi qu&#8217;un certain nombre d&#8217;autres motifs. La liste complète par défaut est : <code>*.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store</code></p>
</li>
<li><a name="item_svk_commit"></a><strong>svk commit</strong>
<p>Permet d&#8217;enregistrer vos modifications dans le dépôt. Cette commande prend en option un commentaire, ce commentaire sert à décrire la ou les modifications apportées.</p>
<pre>  % svk ci -m 'quelques modifications'
  Committed revision 3.</pre>
<p>Je vous suggère (fortement) d&#8217;être le plus précis possible dans les messages que vous associez aux commits. Cela vous permettra d&#8217;avoir une trace fiable.</p>
<div>
<p>Définition : révision</p>
<p>Cela fait déjà quelques fois que nous rencontrons ce terme de  « révision » dans les sorties écran de <code>svk</code>. À chaque fois que vous faites un commit (ou une opération faisant un commit sans vous le dire comme par exemple <code>pull</code> ou <code>smerge</code> que nous verrons plus tard), <code>svk</code> va créer dans le dépôt un nouvel état du système de fichier contenant toutes vos modifications, ces états sont appelés des révisions.</p>
</div>
</li>
<li><a name="item_svk_delete"></a><strong>svk delete</strong>
<p>Permet de supprimer un fichier dans le dépôt. Supprimer un fichier sur votre système de fichier n&#8217;avertit pas <code>svk</code>, cette commande lui précise que ce fichier n&#8217;existe plus. Dans le dépôt, <code>svk</code> ne supprime pas réellement le fichier, il garde bien sûr une trace de toutes les modifications qui y ont été apportées. Vous pourrez donc retrouver toutes ses versions si besoin est.</p>
</li>
<li><a name="item_svk_rename"></a><strong>svk rename</strong>
<p>Permet de renommer un fichier ou un répertoire. Si vous déplacez le fichier par les commandes liées à votre OS, <code>svk</code> ne pourra pas le savoir. Vous devez utiliser cette commande :</p>
<pre>  % svk rename config/ etc/</pre>
<p>Comme <code>add</code> et <code>delete</code>, cette commande ne prend effet réellement qu&#8217;après le prochain commit.</p>
</li>
<li><a name="item_svk_revert"></a><strong>svk revert</strong>
<p>Permet de « défaire » les éditions locales. Si vous avez modifié un fichier ou bien exécuté une commande <code>add</code> ou <code>delete</code> par exemple mais que vous n&#8217;avez pas encore commité, vous pouvez revenir à l&#8217;état d&#8217;avant ce <code>add</code> ou ce <code>delete</code> :</p>
<pre>  % svk status
  # on crée un nouveau fichier
  % touch yyyyy
  # ce fichier est marqué comme inconnu par svk
  % svk status
  ?   yyyyy
  # on l'ajoute par svk, il le marque comme à ajouter
  % svk add yyyyy
  A   yyyyy
  # on le 'revert'
  % svk revert yyyyy
  Reverted yyyyy
  # il est à nouveau marqué comme inconnu
  % svk status
  ?   yyyyy</pre>
</li>
<li><a name="item_svk_status"></a><strong>svk status</strong>
<p>Vous permet de voir rapidement l&#8217;état de vos fichiers</p>
<pre>  % svk status
  M   a.c
  !   a.h
  ?   b.c
  ?   b.h</pre>
<p>Le <code>M</code> indique que le fichier a été modifié, le <code>!</code> que le fichier n&#8217;existe plus dans les fichiers locaux et le <code>?</code> que le fichier n&#8217;existe pas dans le dépôt. Pour une liste complète, référez vous au <em>SVK Book</em>.</p>
</li>
</ul>
<p><a name="h3.5"></a></p>
<h2><a name="h3.5">Mettre à jour les fichiers locaux à partir du dépôt</a></h2>
<p><a name="h3.5">Si vous êtes plusieurs à travailler sur votre projet, vous allez vouloir à un moment ou à un autre mettre à jour vos fichiers. Pour cela, utilisez la commande suivante depuis le répertoire de travail :</a></p>
<pre><a name="h3.5">  % svk update</a></pre>
<p><a name="h3.5">Le problème que vous voyez peut-être déjà c&#8217;est comment ça se passe si votre collègue/copain a modifié un fichier que vous avez modifié localement vous aussi. Voyons ça :</a></p>
<pre><a name="h3.5">  % svk update
  Syncing //local/monprojet/trunk(/local/monprojet/trunk) in
  /home/test/monprojet to 6.
  Conflict found in a.c:
  e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e]</a></pre>
<p><code><a name="h3.5">svk</a></code><a name="h3.5"> s&#8217;est rendu compte du problème et vous propose plusieurs choix. Dans l&#8217;immédiat nous n&#8217;allons utiliser qu&#8217;une des options (je vous laisse découvrir les autres), à savoir l&#8217;option <code>"s"</code>. Cette dernière intègre les modifications apportées par les co-éditeurs du fichiers. À vous de rêgler le conflit :</a></p>
<div>
<p><a name="h3.5">Verrouillage ou conflit ?</a></p>
<p><a name="h3.5">Les logiciels de gestion de versions se séparent en deux catégories, ceux qui verrouillent (<em>« lock »</em>) les fichiers pour éviter les conflits et ceux qui autorisent les conflits et laissent les utilisateurs les gérer. Si la première catégorie semble plus sure, elle n&#8217;est pas forcément la plus efficace. À l&#8217;usage on se rend compte que les conflits ne sont ni si courants ni si graves et que cela apporte une souplesse non négligeable. Si néanmoins vous constatez que vous avez beaucoup de conflits, allez lire les conseils méthodologiques à la fin de cet article.</a></p>
</div>
<pre><a name="h3.5">  % cat a.c
  &gt;&gt;&gt;&gt; YOUR VERSION a.c 115722413378427
  #include "d.h"
  ==== ORIGINAL VERSION a.c 115722413378427
  #include "b.h"
  ==== THEIR VERSION a.c 115722413378427
  #include "e.h"
  &lt;&lt;&lt;&lt; 115722413378427</a></pre>
<p><a name="h3.5">Comme indiqué dans le texte, <code>svk</code> indique les différentes versions à l&#8217;origine du conflit à savoir, votre version actuelle, la dernière version commitée ainsi que la version du co-éditeur.</a></p>
<p><a name="h3.5">La résolution d&#8217;un conflit de ce type n&#8217;est pas tant un problème informatique que humain. Pour le résoudre vous aurez sans doute besoin de contacter la personne ayant fait la modification pour en parler avec elle avant de garder ou de modifier la version adéquate.</a></p>
<p><a name="h3.5">Après avoir résolu le conflit, vous devrez prévenir <code>svk</code> avec :</a></p>
<pre><a name="h3.5">   % svk resolved a.c</a></pre>
<p><a name="h3.5">Et ensuite vous pourrez commiter cette modification afin de ne pas laisser traîner le conflit :</a></p>
<pre><a name="h3.5">  % svk commit a.c</a></pre>
<p><a name="h3.5">Une chose à savoir, les commandes <code>commit</code> et <code>update</code> ne sont pas liées. Vous pouvez faire (et ferez souvent) l&#8217;une sans l&#8217;autre.</a></p>
<p><a name="h3.6"></a></p>
<h2><a name="h3.6">Regarder l&#8217;historique des modifications</a></h2>
<p><a name="h3.6">Pour voir toutes les actions réalisées, vous pouvez faire <code>svk log</code>.</a></p>
<p><a name="h3.6">Cette commande ne fait que vous afficher les commentaires que vous mettez quand vous commitez, c&#8217;est donc dans votre intérêt d&#8217;être le plus précis possible.</a></p>
<p><a name="h3.6">Par défaut <code>svk log</code> ne vous montre que l&#8217;historique que depuis la dernière copie effectuée. Si vous travaillez sur un miroir, vous devrez utiliser l&#8217;option <code>--cross</code> qui permet de voir également les modifications recopiées depuis un autre dépôt. L&#8217;option <code>--verbose</code> permet d&#8217;avoir une sortie un peu plus complète (fichiers concernés entre autre).</a></p>
<p><a name="h3.6">Pour regarder plus précisément un fichier, la commande <code>svk annotate</code> peut vous aider, elle permet de voir quelles lignes viennent de quelle version.</a></p>
<p><code><a name="h3.6">svk cat</a></code><a name="h3.6"> permet de voir l&#8217;état d&#8217;un fichier dans le dépôt. Nous verrons un peu plus loin un argument idéal à utiliser avec cette commande.</a></p>
<p><a name="h3.7"></a></p>
<h2><a name="h3.7">Quelques autres commandes</a></h2>
<p><a name="h3.7">Voici quelques autres commandes qui pourront vous être utiles au cours de votre utilisation de <code>svk</code> :</a></p>
<ul>
<li>
<p><a name="h3.7">Si vous voulez exporter un projet sans le conserver dans la gestion de versions, vous pouvez utilisez l&#8217;option <code>--export</code> :</a></p>
<pre><a name="h3.7">  % svk checkout --export //local/redmine/trunk redmine</a></pre>
</li>
<li>
<p><a name="h3.7">Si vous voulez voir ce qu&#8217;il y a dans votre dépôt vous pouvez utiliser la commande <code>list</code> avec le chemin de dépôt qui vous intéresse :</a></p>
<pre><a name="h3.7">  % svk list //mirror
  articles/
  monprojet/
  mongueurs/
  redmine/
  tracks/</a></pre>
<p><a name="h3.7">Cette commande accepte plusieurs options dont une peut vous intéresser tout de suite : <code>svk list -R //</code> liste récursivement tous les répertoires. Très pratique pour avoir une visualisation en arbre de votre arborescence de dépôt.</a></p>
</li>
<li>
<p><a name="h3.7">Si vous avez besoin de créer un nouveau répertoire dans votre copie de travail, vous pouvez utiliser directement la commande <code>svk mkdir</code>, le répertoire sera ajouté au prochain commit. Et comme nous l&#8217;avons vu au début de cet article, elle permet également de créer un nouveau répertoire de dépôt (pour organiser un peu votre dépôt par exemple) :</a></p>
<pre><a name="h3.7">  % svk mkdir monrepertoire
  % svk mkdir //local/quelquechose</a></pre>
</li>
<li>
<p><a name="h3.7">Parfois vous voudrez savoir d&#8217;où vient telle copie de travail ou tel répertoire de votre dépôt. <code>svk info</code> vous donnera toutes les informations utiles :</a></p>
<pre><a name="h3.7">  % svk info
  Checkout Path: /home/nc/travail/rails/redmine
  Depot Path: //local/redmine/trunk/redmine
  Revision: 10389
  Last Changed Rev.: 10389
  Copied From: /mirror/redmine/trunk/redmine, Rev. 10375
  Merged From: /mirror/redmine/trunk/redmine, Rev. 10388

  % svk info //mirror/redmine
  Depot Path: //mirror/redmine
  Revision: 10410
  Last Changed Rev.: 10388
  Mirrored From: svn://rubyforge.org/var/svn/redmine, Rev. 22</a></pre>
</li>
</ul>
<p><a name="h3.8"></a></p>
<h2><a name="h3.8">Quelques options bien utiles</a></h2>
<p><a name="h3.8">Un certain nombre de commandes acceptent des arguments. Vous trouverez la liste complète dans le <em>SVK Book</em> mais je vais rapidement donner ici celles qui peuvent vous être utile tout de suite :</a></p>
<p><a name="h3.8">Les commandes <code>diff</code>, <code>log</code>, <code>update</code> et <code>cat</code> acceptent un argument <code>-r</code> pour indiquer une révision. Cet argument est soit le numéro de révision, soit une date. Par exemple, pour avoir les modifications faites entre le 9 juillet et le 10 juillet il suffit de faire :</a></p>
<pre><a name="h3.8">  % svk diff -r {2006-07-09}:{2006-07-10}
  === redmine/app/helpers/search_filter_helper.rb
  ==================================================================
  --- redmine/app/helpers/search_filter_helper.rb (revision 10337)
  +++ redmine/app/helpers/search_filter_helper.rb (revision 10340)
  @@ -29,10 +29,12 @@
     end</a></pre>
<p><a name="h3.8">Pour préciser que vous voulez comparer par rapport à la dernière version utilisez HEAD :</a></p>
<pre><a name="h3.8">  % svk diff -r {2006-07-09}:HEAD</a></pre>
<p><a name="h3.8">Et comme promis antérieurement, cette option est très pratique avec <code>svk cat</code> pour voir l&#8217;état d&#8217;un fichier dans telle révision ou à telle date :</a></p>
<pre><a name="h3.8">  % svk cat -r {2006-07-09} redmine/app/helpers/search_filter_helper.rb</a></pre>
<p><code><a name="h3.8">checkout</a></code><a name="h3.8"> et <code>update</code> acceptent également un argument <code>-r</code> qui permet de préciser à partir de quelle révision on veut se mettre à jour.</a></p>
<p><a name="h3.8">Nous avons déjà vu la commande <code>checkout</code>. Elle dispose d&#8217;une option bien pratique au bout de quelque temps pour retrouver ses petits, il s&#8217;agit de <code>--list</code> qui affiche la liste des répertoires de travail :</a></p>
<pre><a name="h3.8">  % svk checkout --list
    Depot Path                            Path
  ========================================================================
    //local/mesprojets/bbrails/trunk         /home/nc/travail/rails/bbrails
    //local/mesprojets/fpw2006               /home/nc/travail/rails/fpw2006
    //local/mesprojets/gestapp/trunk         /home/nc/travail/rails/gestapp
    //local/mongueurs/trunk               /home/nc/travail/mongueurs
    //local/redmine/trunk/redmine         /home/nc/travail/rails/redmine
  ? //local/mesprojets/test                  /home/nc/tmp/prosper</a></pre>
<p><a name="h3.8">Le <code>?</code> indique que le répertoire de travail n&#8217;existe plus. Vous pouvez alors supprimer cette référence en faisant :</a></p>
<pre><a name="h3.8">  % svk checkout --purge
  Purge checkout of //local/mesprojets/test to non-existing directory
  /home/nc/tmp/prosper?
  (y/n) y
  Checkout path '/home/nc/tmp/prosper' detached.</a></pre>
<p><a name="h3.8">Ça y est vous maîtrisez les commandes de base et vous pouvez utiliser SVK au quotidien mais il serait dommage de s&#8217;arrêter là alors qu&#8217;il y a tant à faire. Ceci nous amène naturellement sur le chapitre suivant &#8216;utilisation avancée</a></p>
</div>
<div><a name="h4"></a></p>
<h1><a name="h4">Utilisation avancée</a></h1>
<p><a name="h4.1"></a></p>
<h2><a name="h4.1">Les branches et les tags</a></h2>
<p><a name="h4.1">Cette partie demande quelques explications. Imaginons que vous écriviez un nouveau logiciel allant révolutionner le monde (un logiciel de blog par exemple). Vous venez de sortir la version 1.0 et vous voudriez bien pouvoir développer la future version 2.0, tout en continuant à corriger les bugs de la version 1.0. Pour utiliser le jargon, vous aimeriez bien avoir plusieurs branches de développement, une branche stable et une branche instable. Une solution simple existe dans la plupart des logiciels de gestion de versions, la notion de tag et de branches.</a></p>
<p><a name="h4.1">Les mises en œuvre de ces mécanismes différent d&#8217;un logiciel à l&#8217;autre mais pour SVK, cela se traduit tout simplement par trois répertoires créés dans le dépôt (et non au niveau du système de fichier) :</a></p>
<pre><a name="h4.1">  branches/ - les différentes versions de développement
  tags/     - des images figées
  trunk/    - la dernière version en cours de développement</a></pre>
<p><a name="h4.1">Dans SVK nous verrons que branches et tags sont gérés de la même façon, ils ne différent que par l&#8217;utilisation que l&#8217;on en fait : les branches sont utilisées pour développer les différentes versions en parallèle, tandis que les tags servent à conserver des versions spécifiques sur lesquelles vous ne travaillez pas. On ne commite pas dans les tags.</a></p>
<p><a name="h4.1.1"></a></p>
<h3><a name="h4.1.1">Création de branches et de tags</a></h3>
<p><a name="h4.1.1">La commande utilisée pour créer des tags et des branches est la même, il s&#8217;agit de <code>svk copy</code> :</a></p>
<pre><a name="h4.1.1">  % svk copy //local/monprojet/trunk \
    //local/monprojet/branches/monprojet-1.0 \
    -m 'creation de la branches 1.0'
  Committed revision 5.</a></pre>
<p><a name="h4.1.1">Comme tout le monde s&#8217;en doutait, cela va créer un nouveau répertoire de dépôt dans <em>branches</em> contenant tous les fichiers dans l&#8217;état actuel de trunk :</a></p>
<pre><a name="h4.1.1">  % svk list //local/monprojet/branches/
  monprojet-1.0/</a></pre>
<p><a name="h4.1.1">Vous allez pouvoir faire un <code>checkout</code> de cette version 1.0 et travailler dessus tout en continuant à développer la version future dans trunk.</a></p>
<p><a name="h4.1.1">Une fois votre version 1.0 prête à être diffusée, vous voudriez bien garder une trace exacte de cette version. Bien sûr, vous pourriez utiliser l&#8217;option <code>-r</code>, que nous avons vue à la fin du chapitre précédent, avec le numéro de révision ou bien la date mais ça n&#8217;est pas très intuitif. Une meilleure façon est de tagger cette version :</a></p>
<pre><a name="h4.1.1">  % svk copy //local/monprojet/branches/monprojet-1.0 \
     //local/monprojet/tags/monprojet-1.0 -m 'version 1.0 diffusée'
  Committed revision 7.</a></pre>
<p><a name="h4.1.1">Un utilisateur vous soumet un bug ? Vous corrigez le bug dans la branche <em>version-1.0</em> et quand vous diffusez une version 1.0.1 vous n&#8217;avez qu&#8217;à la copier dans <em>tags</em> sous le nom <em>monprojet-1.0.1</em> pour en garder une trace.</a></p>
<p><a name="h4.1.1">Même si SVK s&#8217;arrêtait là la notion de tags et de branches serait un outil fantastique mais heureusement, SVK va beaucoup plus loin&#8230;</a></p>
<p><a name="h4.1.2"></a></p>
<h3><a name="h4.1.2">Passer votre copie de travail d&#8217;une branche à une autre</a></h3>
<p><a name="h4.1.2">Si votre copie de travail est un <em>checkout</em> d&#8217;une branche et que vous voulez passer dans une autre, placez-vous dans le répertoire de la copie de travail et utilisez la commande <code>svk switch</code> :</a></p>
<pre><a name="h4.1.2">  % svk switch //local/monprojet/branches/monprojet-1.0/</a></pre>
<p><a name="h4.1.2">Pour repasser dans <em>trunk</em> il suffit de faire :</a></p>
<pre><a name="h4.1.2">  % svk switch //local/monprojet/trunk/</a></pre>
<p><a name="h4.1.3"></a></p>
<h3><a name="h4.1.3">La fusion</a></h3>
<p><a name="h4.1.3">Vous avez vos deux versions, celle de <em>trunk</em> et celle de <em>version-1.0</em>. Vous corrigez plusieurs bugs dans <em>version-1.0</em> et vous aimeriez bien les corriger aussi dans <em>trunk</em>. Plutôt que de reporter vos corrections à la main dans trunk, vous pouvez utilisez la fonction smerge :</a></p>
<pre><a name="h4.1.3">  % svk smerge -Il //local/monprojet/branches/monprojet-1.0 \
    //local/monprojet/trunk
  Auto-merging (0, <img src='http://blog.pepita.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> /local/monprojet/branches/monprojet-1.0 to
     /local/monprojet/trunk (base /local/monprojet/trunk:4).
  ===&gt; Auto-merging (0, 5) /local/monprojet/branches/monprojet-1.0 to
     /local/monprojet/trunk (base /local/monprojet/trunk:4).
  Empty merge.
  ===&gt; Auto-merging (5, <img src='http://blog.pepita.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> /local/monprojet/branches/monprojet-1.0 to
     /local/monprojet/trunk (base /local/monprojet/trunk:4).
  U   db/migrate/001_setup.rb
  New merge ticket:
  0aca4fd4-bb1c-0410-adf5-ecdeea5a58f8:
     /local/monprojet/branches/monprojet-1.0:8
  Committed revision 9.</a></pre>
<p><a name="h4.1.3">Cette commande va reporter toutes les modifications que vous avez faites dans <em>version-1.0</em> dans le <em>trunk</em>. Évidemment, si vous avez déjà modifié le <em>trunk</em> dans un endroit où vous avez également corrigé un bug vous risquez d&#8217;avoir un conflit, charge à vous de le résoudre.</a></p>
<p><a name="h4.1.3">Attention, contrairement à la résolution de conflit que nous avons vue précédemment, vous ne pourrez pas faire <code>skip</code> pour résoudre votre problème plus tard. Vous devrez le résoudre tout de suite grâce aux options <code>diff</code> (pour voir le conflit) et <code>edit</code> (pour le modifier). Si vous faites <code>skip</code>, cette partie ne sera pas fusionnée, néanmoins vous pourrez la refusionner plus tard. Suite à votre édition, <code>svk</code> vous demandera si vous voulez accepter la modification :</a></p>
<pre><a name="h4.1.3">  % svk smerge -Il //local/monprojet/branches/monprojet-1.0 \
       //local/monprojet/trunk
  Auto-merging (8, 11) /local/monprojet/branches/monprojet-1.0 to
   /local/monprojet/trunk (base /local/monprojet/branches/monprojet-1.0:8).
  ===&gt; Auto-merging (8, 11) /local/monprojet/branches/monprojet-1.0 to
   /local/monprojet/trunk (base /local/monprojet/branches/monprojet-1.0:8).
  Conflict found in config/config_custom.rb:
  e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] e
  Waiting for editor...
  Merged config/config_custom.rb:
  a)ccept, e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [a] a
  G   config/config_custom.rb
  New merge ticket: 0aca4fd4-bb1c-0410-adf5-ecdeea5a58f8:
   /local/monprojet/branches/monprojet-1.0:11
  Committed revision 12.</a></pre>
<p><a name="h4.1.3">Une bonne méthode de travail consiste à regarder avant de faire le <code>svk smerge</code> si vous allez avoir des conflits en faisant utilisant l&#8217;option <code>-C</code> : <code>svk smerge -C</code>.</a></p>
<p><a name="h4.1.3">Quelques jours après cette fusion corrigeant des bugs, vos utilisateurs vous soumettent à nouveau plusieurs bugs bloquants. Vous les corrigez et vous aimeriez bien pouvoir faire la même manipulation pour les corriger dans <em>trunk</em>. Et bien j&#8217;ai une bonne nouvelle, vous pouvez la recommencer autant de fois que vous le voulez. Contrairement à certains autres logiciels (dont SVN et CVS entre autres) pour lesquels les fusions à répétitions entre branches sont non triviales (il faut préciser à la fonction <code>merge</code> la dernière révision pour laquelle on a déjà fait une fusion), SVK implémente dans <code>smerge</code> une fonction de fusion sophistiquée, appelée <em>star-merge</em>, qui permet de fusionner successivement les mêmes branches sans se poser de question.</a></p>
<p><a name="h4.1.3">Vous pouvez utiliser <code>svk smerge</code> entre deux dépôts comme nous venons de le voir mais aussi entre un dépôt et une copie de travail en spécifiant le chemin de votre copie de travail en seconde position comme ceci :</a></p>
<pre><a name="h4.1.3">  % svk smerge -Il //local/monprojet/branches/monprojet-1.0 \
    /ma/copie/de/travail</a></pre>
<p><a name="h4.1.4"></a></p>
<h3><a name="h4.1.4">Fusionner seulement quelques révisions</a></h3>
<p><a name="h4.1.4">Aussi parfois appelé <em>« cherry picking »</em> (cueillette de cerise).</a></p>
<p><a name="h4.1.4">Imaginons maintenant le cas inverse, vous développez dans <em>trunk</em> et trouvez des bugs. Après correction vous aimeriez bien les reporter dans votre branche <em>monprojet-1.0</em>. Seul problème, vous avez aussi fait des modifications substantielles dans d&#8217;autres parties de <em>trunk</em> que vous ne voulez pas voir apparaître dans la branche.</a></p>
<p><code><a name="h4.1.4">smerge</a></code><a name="h4.1.4"> ne sait pas faire ça, il va falloir se rabattre sur la commande <code>merge</code>.</a></p>
<p><a name="h4.1.4">Avant toute chose on va chercher les révisions que l&#8217;on veut fusionner dans notre branche, la commande <code>log</code> va nous trouver ça :</a></p>
<pre><a name="h4.1.4">  % svk log
  ----------------------------------------------------------------------
  r16:  test | 2006-09-06 15:23:04 +0200

  ajout d'une fonctionnalite pour la v2.0
  ----------------------------------------------------------------------
  r15:  test | 2006-09-06 15:22:32 +0200

  correction bug bloquant
  ----------------------------------------------------------------------
  r14:  test | 2006-09-06 15:22:14 +0200

  ajout d'une fonctionnalite pour la v2.0</a></pre>
<p><a name="h4.1.4">Le bug a été corrigé dans la révision 15, nous pouvons vérifier la correction de bug en faisant un <code>diff</code> :</a></p>
<pre><a name="h4.1.4">  % svk diff -r 14:15 //local/monlogiciel/trunk/
  === generate
  ==================================================================
  --- generate    (revision 14)
  +++ generate    (revision 15)
  @@ -1,4 +1,4 @@
   #!/usr/bin/env ruby
   # commentaire
  -requir File.dirname(__FILE__) + '/../config/boot'
  +require File.dirname(__FILE__) + '/../config/boot'
   require 'commands/generate'</a></pre>
<p><a name="h4.1.4">C&#8217;est bien cette correction de bug que nous voulons fusionner. Nous pouvons donc appliquer le patch. Nous pouvons l&#8217;appliquer soit directement sur le dépôt (comme vu avec <code>smerge</code>), soit en se plaçant directement dans un répertoire de travail contenant notre branche et en faisant :</a></p>
<pre><a name="h4.1.4">  % svk merge  -r 14:15 //local/monlogiciel/trunk/
  U   generate</a></pre>
<p><a name="h4.1.4">Il vous faudra alors commiter ces modifications.</a></p>
<p><a name="h4.1.4">L&#8217;avantage de faire la fusion directement sur le dépôt est que vous n&#8217;aurez pas à faire le commit ensuite.</a></p>
<p><a name="h4.1.4">Cette partie suppose que vos <code>commit</code>s forment un tout homogène. Un commit pour les corrections de bug, un commit pour l&#8217;ajout de tel fonctionnalité, etc.</a></p>
<p><a name="h4.1.5"></a></p>
<h3><a name="h4.1.5">Gérer des modifications locales dans un logiciel</a></h3>
<p><a name="h4.1.5">Nous allons étudier un cas relativement classique : vous utilisez un logiciel que vous avez adapté à votre environnement. À chaque nouvelle version vous devez réintégrer vos modifications à la main ce qui est long, fastidieux et contrevient clairement à une des vertus cardinales de l&#8217;informaticien, la paresse. SVK peut vous aider.</a></p>
<ul>
<li>
<p><a name="h4.1.5">Créez une arborescence standard branches/tags/trunk</a></p>
<pre><a name="h4.1.5">  mkdir -p monlogiciel/{branches,tags,trunk}</a></pre>
</li>
<li>
<p><a name="h4.1.5">Récupérez une archive de votre logiciel et décompactez-la directement dans trunk.</a></p>
</li>
<li>
<p><a name="h4.1.5">faites un import de toute l&#8217;arborescence</a></p>
<pre><a name="h4.1.5">  % svk import -m "premier import de monlogiciel" monlogiciel \
     //local/monlogiciel</a></pre>
</li>
<li>
<p><a name="h4.1.5">faites une copie de <em>trunk</em> vers une branche sur laquelle vous ferez vos modifications :</a></p>
<pre><a name="h4.1.5">  % svk copy -m "creation de la copie locale" //local/monlogiciel/trunk \
     //local/monlogiciel/branches/monlogiciel-local</a></pre>
</li>
<li>
<p><a name="h4.1.5">Faites un <code>checkout</code> de cette branche et faites toutes les modifications désirées dans cette branche et commitez-les.</a></p>
</li>
<li>
<p><a name="h4.1.5">Une nouvelle version de monlogiciel est sortie, récupérez-la à nouveau et décompactez-la.</a></p>
<pre><a name="h4.1.5">  % svk import -m "import de monlogiciel v1.2" monlogiciel \
    //local/monlogiciel/trunk</a></pre>
</li>
<li>
<p><a name="h4.1.5">Essayez de fusionner le nouveau <em>trunk</em> avec votre version locale :</a></p>
<pre><a name="h4.1.5">  % svk smerge -C //local/monlogiciel/trunk \
    //local/monlogiciel/branches/monlogiciel-local
  Auto-merging (2, 5) /local/monlogiciel/trunk to
    /local/monlogiciel/branches/monlogiciel-local
    (base /local/monlogiciel/trunk:2).
  U   console
  New merge ticket: 6d4c1533-f1fa-4670-b606-7b3ba989afbe:
    /local/monlogiciel/trunk:5</a></pre>
<p><a name="h4.1.5">Seul le fichier <em>console</em> a été modifié et SVK ne détecte aucun conflit. Vous pouvez donc faire le <code>smerge</code> en toute confiance :</a></p>
<pre><a name="h4.1.5">  % svk smerge -Il //local/monlogiciel/trunk \
     //local/monlogiciel/branches/monlogiciel-local
  Auto-merging (2, 5) /local/monlogiciel/trunk to
     /local/monlogiciel/branches/monlogiciel-local (base
     /local/monlogiciel/trunk:2).
  ===&gt; Auto-merging (2, 5) /local/monlogiciel/trunk to
     /local/monlogiciel/branches/monlogiciel-local (base
     /local/monlogiciel/trunk:2).
  U   console
  New merge ticket: 6d4c1533-f1fa-4670-b606-7b3ba989afbe:
     /local/monlogiciel/trunk:5
  Committed revision 6.</a></pre>
</li>
<li>
<p><a name="h4.1.5">Recommencez la procédure ci-dessus ad-nauseam à chaque nouvelle version de votre logiciel.</a></p>
<p><a name="h4.1.5">Évidemment, si la nouvelle version est une réécriture complète cela risque de ne pas marcher aussi bien que voulu mais si c&#8217;est une version de bugfix le travail sera nettement moins fastidieux qu&#8217;à la main.</a></p>
</li>
</ul>
<p><a name="h4.2"></a></p>
<h2><a name="h4.2">Travailler en mode déconnecté</a></h2>
<p><a name="h4.2">Un des gros problèmes rencontrés quand vous utilisez un dépôt sur Internet est comment travailler quand vous n&#8217;avez pas accès à Internet pendant quelque temps. Vous pouvez revenir aux (pas si) bonnes vieilles méthodes, à savoir copier vos fichiers modifiés avec une extension précisant la date de modification ou la modification, et vous retrouvez rapidement avec des répertoires comme celui-ci :</a></p>
<pre><a name="h4.2">  projet/a.c
        /a.c-version_de_debuggage
        /a.c-1
        /a.c-2
        /a.c-bug_machin
        /...</a></pre>
<p><a name="h4.2">Cela devient vite horrible et inutilisable (bien que des gens utilisent encore cette méthode).</a></p>
<p><a name="h4.2">SVK propose une solution simple et esthétique, un dépôt déconnecté. Pour faire cela il faut utiliser la notion de miroir.</a></p>
<pre><a name="h4.2">  % svk mirror https://rubyforge.org/var/svn/redmine/ //mirror/redmine
  % svk sync //mirror/redmine</a></pre>
<p><a name="h4.2">La première commande va créer le miroir, la seconde va importer toutes les données du dépôt distant dans votre miroir. Quand vous faites un <code>checkout</code> directement depuis un serveur Subversion, c&#8217;est en fait ce  que <code>svk</code> fait dans votre dos (rappelez-vous les questions qu&#8217;il vous  a posées au début de ce tutoriel).</a></p>
<p><a name="h4.2">Une fois cette étape réalisée, vous allez faire une copie locale des données récupérées :</a></p>
<pre><a name="h4.2">  % svk copy //mirror/redmine //local/redmine</a></pre>
<p><a name="h4.2">À partir de ce moment, vous pouvez faire un <code>checkout</code> de votre projet et commencer à travailler dessus hors-ligne en commitant régulièrement vos modifications.</a></p>
<p><a name="h4.2">Oui, mais si c&#8217;est en mode hors-ligne, comment répliquer vos modifications sur le dépôt central et récupérer les dernières modifications du dépôt central ? En utilisant les commandes <code>svk push</code> et <code>svk pull</code>.</a></p>
<p><a name="h4.2">Vous revenez de deux semaines sans accès à Internet, vous avez commité de nombreuses modifications et vous voudriez bien que vos petits collègues en profitent. Commencez par récupérer leurs modifications :</a></p>
<pre><a name="h4.2">  % svk pull</a></pre>
<p><a name="h4.2">Cette commande va d&#8217;abord mettre à jour votre miroir et ensuite faire un <code>update</code> de votre répertoire de travail. Vous aurez peut-être des conflits à résoudre. Une fois ces conflits résolus et commités, vous pouvez leur envoyer vos modifications :</a></p>
<pre><a name="h4.2">  % svk push</a></pre>
<p><a name="h4.2">Ces commandes sont en fait des habillages un peu plus sexy d&#8217;autres commandes, mais ne vous préoccupez pas trop de ça si vous n&#8217;en avez pas besoin. Et si vous en avez besoin, lisez le <em>SVK Book</em>.</a></p>
<p><a name="h4.2">Vous pouvez voir les modifications en attente d&#8217;être poussées en utilisant la commande <code>diff</code> comme ceci :</a></p>
<pre><a name="h4.2">  % svk diff //mirror/monprojet/ //local/monprojet/</a></pre>
<p><a name="h4.3"></a></p>
<h2><a name="h4.3">Proposer des modifications quand vous n&#8217;avez pas les droits d&#8217;écriture sur le dépôt</a></h2>
<p><a name="h4.3">Il n&#8217;est pas rare de proposer des patchs sur des projets pour lesquels vous n&#8217;avez pas les droits d&#8217;écriture sur le dépôt. Vous pouvez bien sûr utiliser la commande <code>diff</code> présente sur votre système ou bien la commande <code>diff</code> de SVK mais ce dernier vous permet de faire mieux avec l&#8217;option <code>--patch</code> utilisable avec <code>commit</code>, <code>push</code> et <code>smerge</code>.</a></p>
<p><a name="h4.3">Pour l&#8217;utiliser, commitez vos modifications normalement dans votre dépôt local et ensuite utilisez <code>push</code> avec l&#8217;option <code>--patch</code> :</a></p>
<pre><a name="h4.3">  % svk push --patch svk_correction_bug
  Auto-merging (10574, 10606) /local/mongueurs/trunk to
     /mirror/mongueurs/trunk (base /mirror/mongueurs/trunk:10604).
  Patching locally against mirror source svn://svn.mongueurs.net/articles.
  U   magazines/Applications/svk.pod
  Patch svk_correction_bug created.</a></pre>
<p><a name="h4.3">Le patch est déposé dans <em>~/.svk/patch</em>.</a></p>
<p><a name="h4.3">Vous pouvez lister vos patchs en faisant :</a></p>
<pre><a name="h4.3">  % svk patch --list
  svk.pod@1:
  svk_correction_bug@1:</a></pre>
<p><a name="h4.3">Quand votre correspondant recevra le fichier de patch il n&#8217;aura qu&#8217;a le déposer dans son fichier <em>~/.svk/patch</em> et le rejouer en faisant :</a></p>
<pre><a name="h4.3">  % svk patch apply svk_correction_bug</a></pre>
<p><a name="h4.4"></a></p>
<h2><a name="h4.4">Répliquer un dépôt local sur un dépôt distant</a></h2>
<p><a name="h4.4">Ça y est, votre logiciel est prêt à affronter la critique de vos contemporains et vous voudriez leur donner accès aux sources. Vous avez juste deux problèmes : votre dépôt est sur votre disque et vous ne voulez pas donner accès à tous vos projets. La solution, répliquer votre projet sur un autre serveur SVN, par exemple sur une forge sur internet.</a></p>
<p><a name="h4.4">Pour cette recette, vous avez normalement besoin d&#8217;un serveur svn extérieur mais nous allons contourner le problème en créant un autre dépot local.</a></p>
<p><a name="h4.4">D&#8217;abord, un petit mot sur les dépôts. Au début de cet article nous en avons créé un en faisant <code>svk depotmap --init</code>. Cette commande créé un dépôt par défaut que l&#8217;on peut ensuite utilisé en utilisant <code>//</code>. Même si cette possibilité est rarement utile et n&#8217;est pas forcément recommandée, SVK peut gérer plusieurs dépôts.</a></p>
<p><a name="h4.4">Créons donc ce second dépôt nommé « remote » dans le répertoire <em>/tmp/remote</em> (chemin pas forcément judicieux si vous comptez faire plus qu&#8217;un test&#8230;)</a></p>
<pre><a name="h4.4">  % svk depotmap remote /tmp/remote
  New depot map saved.
  Repository /tmp/remote does not exist, create? (y/n)y</a></pre>
<p><a name="h4.4">Le dépôt est créé. On peut voir la liste des dépôts gérés par SVK en faisant :</a></p>
<pre><a name="h4.4">  % svk depotmap --list
  Depot                   Path
  ============================================================
  //                      /home/nc/.svk/local
  /remote/                /tmp/remote</a></pre>
<p><a name="h4.4">Ce nouveau dépôt est accessible en préfixant les chemins par <code>/remote/</code> à la place de <code>//</code> mais nous allons l&#8217;utiliser comme si c&#8217;était un dépôt distant et commencer par créer un miroir dans le dépôt par défaut :</a></p>
<pre><a name="h4.4">  % svk list file:///tmp/remote</a></pre>
<p><code><a name="h4.4">svk</a></code><a name="h4.4"> va vous poser des questions pour créer un miroir local dans le dépôt par défaut <code>//</code>. Répondez par défaut, cela va créer un nouveau chemin de dépôt <em>//mirror/remote</em>.</a></p>
<p><a name="h4.4">Synchronisez vos deux dépôts :</a></p>
<pre><a name="h4.4">  % svk sync //mirror/remote</a></pre>
<p><a name="h4.4">Créez le répertoire <em>monprojet</em> qui va accueillir votre projet sur le miroir :</a></p>
<pre><a name="h4.4">  % svk mkdir //mirror/remote/monprojet/ \
        -m 'creation du repertoire de monprojet'</a></pre>
<p><a name="h4.4">Faites un <em>smerge</em> de votre dépôt local vers votre dépôt :</a></p>
<pre><a name="h4.4">  % svk smerge --baseless --incremental //local/monprojet \
       //mirror/remote/monprojet</a></pre>
<p><a name="h4.4">L&#8217;option <em>baseless</em> indique que <code>svk</code> doit faire le <code>smerge</code> même si les deux projets n&#8217;ont pas de racine commune et <em>incremental</em> que chaque changement doit être appliqué individuellement.</a></p>
<p><a name="h4.4">Ça y est le miroir est fait. Vous aurez juste à penser à mettre à jour votre dépôt externe en lançant de temps en temps la commande :</a></p>
<pre><a name="h4.4">  % svk smerge --incremental -m "mise a jour" //local/monprojet/ \
     //mirror/remote/monprojet/</a></pre>
<p><a name="h4.4">Malheureusement vous ne pourrez pas utiliser la commande <code>svk push</code> pour mettre à jour cette copie. À ce niveau, plusieurs solutions s&#8217;offre à vous :</a></p>
<ul>
<li>
<p><a name="h4.4">soit vous faites le <code>smerge</code> vu ci-dessus à la main de temps en temps.</a></p>
</li>
<li>
<p><a name="h4.4">soit vous voulez vraiment utiliser les commandes <code>push</code> et <code>pull</code>. Vous devez alors utiliser ce nouveau dépôt comme dépot « racine » et créer une nouvelle copie dans //local comme vu dans la section « travailler en mode déconnecté ». Vous pourrez alors supprimer l&#8217;ancienne copie locale (pensez à commiter toutes vos modifications avant de commencer cette manipulation) :</a></p>
<pre><a name="h4.4">  % svk copy -m "creation" //mirror/remote/monprojet/ \
    //local/monprojet-nouveau</a></pre>
<p><a name="h4.4">(Attention, avec la version 2 de SVK que j&#8217;utilise, je ne peux pas réutiliser le même chemin de dépôt dans <em>//local</em>, d&#8217;où le « -nouveau ».)</a></p>
<p><a name="h4.4">Voila, vous pouvez maintenant faire un <code>checkout</code> de <em>//local/monprojet-nouveau</em> et travailler dessus :</a></p>
<pre><a name="h4.4">  % svk checkout //local/monprojet-nouveau
  % cd monprojet-nouveau
  % svk push
  Auto-merging (0, 13238) /local/monprojet-nouveau to
      /mirror/remote/monprojet (base /mirror/remote/monprojet:13223).
  ===&gt; Auto-merging (0, 13238) /local/monprojet-nouveau to
      /mirror/remote/monprojet (base /mirror/remote/monprojet:13223).
  Merging back to mirror source file:///tmp/remote.
  Empty merge.</a></pre>
</li>
<li>
<p><a name="h4.4">soit, dernière solution, vous utilisez une nouvelle notion pour vous, les hooks, pour mettre à jour automatiquement le miroir.</a></p>
<p><a name="h4.4">Les hooks sont des programmes déclenchés par SVK sur certains évènements précis. Vous pouvez les trouver dans <em>~/.svk/local/hooks</em> qui par défaut ne contient que des modèles :</a></p>
<pre><a name="h4.4">  % ls ~/.svk/local/hooks
  post-commit.tmpl  post-revprop-change.tmpl  pre-commit.tmpl
  pre-revprop-change.tmpl start-commit.tmpl</a></pre>
<p><a name="h4.4">Voici le hook utilisé dans le cas présent :</a></p>
<pre><a name="h4.4">  % cat ~/.svk/local/hooks/post-commit
  #!/bin/sh

  svk smerge --incremental //local/monprojet //mirror/remote/monprojet</a></pre>
<p><a name="h4.4">Pensez à le rendre exécutable :</a></p>
<pre><a name="h4.4">  % chmod +x ~/.svk/local/hooks/post-commit</a></pre>
<p><a name="h4.4">Et voilà, celui-ci va lancer la commande <code>smerge</code> pour mettre à jour votre miroir à chaque commit que vous ferez y compris ceux ne concernant pas monprojet. Nous pourrions sans doute affiner cela mais je vous laisse regarder ça vous même.</a></p>
<p><a name="h4.4">L&#8217;inconvénient de cette dernière solution est que, si certaines personnes écrivent dans le nouveau dépôt, vous devrez penser à synchroniser les deux dépôts avec <code>svk sync //mirror/remote</code> pour récupérer leurs modifications. Néanmoins, dans le cadre d&#8217;un dépôt en lecture seule cela ne pose pas vraiment de problème&#8230;</a></p>
</li>
</ul>
<p><a name="h4.5"></a></p>
<h2><a name="h4.5">Métadonnées ou propriétés</a></h2>
<p><a name="h4.5">Les métadonnées sont des données servant à décrire ou à ajouter de l&#8217;information à d&#8217;autres données. Dans un système de fichiers, les droits du fichier sont un exemple de métadonnées, ils ne font pas partie du fichier mais servent à ajouter une information à ce fichier.</a></p>
<p><a name="h4.5">SVK (ainsi que Subversion) appelle ces métadonnées des « propriétés ». Ces propriétés sont manipulables avec les commandes <code>proplist</code>, <code>propget</code>, <code>propset</code>, <code>propedit</code> et <code>propdel</code> qui respectivement, liste toutes les propriétés et retourne, modifie, lance un éditeur pour modifier et enfin supprime une propriété. Voyons un exemple :</a></p>
<pre><a name="h4.5">  % svk proplist README
  % svk propset copyright 'NBC 2007' script/server
   M  script/server
  % svk propset copyright 'NBC 2007' README
   M  README
  % svk proplist README
  Properties on README:
    copyright
  % svk propget copyright README
  NBC 2007
  % svk propdel copyright README
   M  README
  % svk proplist README</a></pre>
<p><a name="h4.5">Les propriétés sont représentées par un nom et une valeur. Ces propriétés sont versionnées exactement comme le fichier. Vous pouvez faire dessus des <code>commit</code>, des <code>revert</code> et toutes les opérations classiques. Elles seront également accessible à toutes les personnes utilisant SVK ou Subversion pour travailler sur votre projet.</a></p>
<p><a name="h4.5">Si vous faites un <code>svk diff</code> sur un fichier auquel vous avez ajouté une propriété, vous verrez quelque chose comme :</a></p>
<pre><a name="h4.5">  % svk diff README 

  Property changes on: README
  ___________________________________________________________________
  Name: copyright
   +NBC 2007</a></pre>
<p><a name="h4.5">Voici un certain nombre de propriétés utiles :</a></p>
<ul>
<li><a name="item_svn_executable"></a><strong>svn:executable</strong>
<p>permet de rendre un fichier exécutable</p>
<pre>  % svk propset svn:executable 1 script/*</pre>
<p>rendra tous les fichiers du répertoire script exécutables suite à une commande <code>checkout</code> ou <code>update</code>.</p>
</li>
<li><a name="item_svn_eol_style"></a><strong>svn:eol-style</strong>
<p>permet de traiter le « problème » des fins de ligne qui sont différentes suivant les systèmes d&#8217;exploitation. En utilisant la valeur « native », SVK utilisera automatiquement la fin de ligne normale du système sur lequel vous travaillez au moment de créer un fichier et non celle utilisée par le créateur du fichier :</p>
<pre>  % svk propset svn:eol-style native **/*.rb</pre>
<p>Vous pouvez aussi forcer un type de fin de ligne en utilisant les valeurs CRLF, CR ou LF.</p>
</li>
<li><a name="item_svn_ignore"></a><strong>svn:ignore</strong>
<p>permet d&#8217;ignorer certains répertoires et fichiers qui n&#8217;ont pas à être journalisés :</p>
<pre>  % svk propset svn:ignore "*" tmp/</pre>
<p>ignorera tous les fichiers créés dans tmp/</p>
</li>
</ul>
<p>Vous pourrez trouver une liste plus complète des propriétés dans la documentation de Subversion <a href="http://svnbook.red-bean.com/">http://svnbook.red-bean.com/</a>. Attention, toutes les propriétés existantes dans Subversion ne sont pas forcément implémentées dans SVK.</p>
<p><a name="h4.6"></a></p>
<h2><a name="h4.6">Configuration de SVK</a></h2>
<p><a name="h4.6">Comme nous l&#8217;avons déjà vu, SVK s&#8217;appuie sur Subversion pour la partie système de fichiers et pour la gestion des propriétés. Il s&#8217;appuie également dessus pour la partie configuration. Le fichier utilisé pour le configurer est <em>~/.subversion/config</em>. Par défaut il est entièrement commenté.</a></p>
<p><a name="h4.6">Nous avons vu un peu plus haut (dans la section parlant de la commande <code>add</code>) que SVK ignorait certains fichiers. Cette liste est évidemment paramétrable. Pour cela, ajoutez dans le fichier de configuration :</a></p>
<pre><a name="h4.6">  [miscellany]
  global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store</a></pre>
<p><a name="h4.6">Une deuxième configuration potentiellement intéressante est de fixer automatiquement les propriétés des fichiers suivants leur extension :</a></p>
<pre><a name="h4.6">  [miscellany]
  enable-auto-props = yes
  [auto-props]
  *.rb = svn:eol-style=native
  *.pl = svn:eol-style=native
  *.png = svn:mime-type=image/png
  ...</a></pre>
<p><a name="h4.6">À ma connaissance, ce sont les deux seules configurations possibles dans SVK. Ceci dit, l&#8217;information étant difficile à trouver en dehors du code source, j&#8217;ai pu en louper certaines.</a></p>
</div>
<div><a name="h5"></a></p>
<h1><a name="h5">Éléments de méthode de travail</a></h1>
<p><a name="h5">Cette partie n&#8217;essaye pas de proposer une méthode de travail générique, elle donne juste quelques pistes pour travailler le mieux possible avec SVK. Elle s&#8217;applique sans doute à beaucoup d&#8217;autres outils de gestion de versions.</a></p>
<ul>
<li>
<p><a name="h5">évitez de travailler directement sur un dépôt miroir, préférez une copie locale.</a></p>
</li>
<li>
<p><a name="h5">faites des update régulièrement et entre autre avant chaque commit, cela réduit les risques de conflit si vous travaillez à plusieurs.</a></p>
</li>
<li>
<p><a name="h5">un commit doit porter sur un changement unitaire (ne mélangez pas corrections de bugs et ajout de nouvelles fonctionnalités), doit être accompagné d&#8217;un message explicite des modifications apportées et doit laisser le logiciel dans un état stable (lancez vos tests unitaires avant de commiter).</a></p>
</li>
<li>
<p><a name="h5">Ne versionnez que les fichiers utiles au projet, i.e. ne versionnez pas les journaux, les fichiers intermédiaires, etc. Pour cela, vous pouvez bien sur utiliser la propriété <code>svn:ignore</code> vu dans la section sur les propriétés au niveau de chaque projet ou bien le <code>global-ignores</code> vu dans la section sur configuration au niveau global.</a></p>
</li>
<li>
<p><a name="h5">SVK ne remplace pas la communication inter-humain.</a></p>
</li>
</ul>
<p><a name="h5">Voici un diagramme récapitulant les flux des commandes importantes de SVK :</a></p>
<div><a name="h5"><img src="http://articles.mongueurs.net/magazines/svk/svk-distant.png" alt="" /> </a></div>
</div>
<div><a name="h6"></a></p>
<h1><a name="h6">SVK version 2</a></h1>
<p><a name="h6">Pour écrire cet article je me suis appuyé sur la version 1 mais le développement est très actif et la version 2 est sortie le 28 décembre 2006. Elle apporte, en plus des corrections de bogues, plusieurs fonctionnalités dont certaines sont vraiment très intéressantes comme :</a></p>
<ul>
<li><a name="item_les_commits_interactifs"></a><strong>les commits interactifs</strong>
<p>Sans doute la plus intéressante à première vue, la commande (<code>svk commit --interactive</code>) vous montre les différentes modifications effectuées et vous permet de sélectionner celles que vous voulez effectivement commiter, les autres restant à l&#8217;état de modifications dans votre copie de travail ;</p>
</li>
<li><a name="item_l_am_lioration_de_la_sortie_des_journaux"></a><strong>l&#8217;amélioration de la sortie des journaux</strong>
<p>Vous pouvez maintenant y appliquer des filtres (recherche par exemple) et modifier la sortie (standard, XML, &#8230;) ;</p>
</li>
<li><a name="item_l_apparition_des_vues"></a><strong>l&#8217;apparition des vues</strong>
<p>Les vues peuvent être vues comme les vues des bases de données ou comme des liens symboliques unix. Elles permettent de référencer une arborescence sous un autre nom (plus parlant).</p>
</li>
</ul>
<p>Une liste complète des modifications de la version 2 est disponible sur le CPAN : <a href="http://search.cpan.org/src/CLKAO/SVK-v2.0.0/CHANGES">http://search.cpan.org/src/CLKAO/SVK-v2.0.0/CHANGES</a></p>
<p>Seul inconvénient, mais de taille à mon avis, cette version n&#8217;est, sauf erreur, pas encore disponible en paquetage (sauf peut-être pour Mac OS X), vous devrez donc l&#8217;installer à la main. À moins d&#8217;en avoir besoin et de savoir ce que vous faites, je vous conseille de rester à la version installée par votre système de gestion de paquetages et d&#8217;attendre qu&#8217;elle soit disponible dans votre système d&#8217;exploitation ou distribution préféré. Ceci étant dit, cette nouvelle version fonctionne très bien pour moi depuis quelque temps déjà.</p>
</div>
<div><a name="h7"></a></p>
<h1><a name="h7">Quelques idées en l&#8217;air</a></h1>
<p><a name="h7">Si les outils de gestion de versions sont généralement utilisés pour gérer les sources d&#8217;un programme, il serait dommage de les limiter à cela. Ils peuvent être détournés pour faire plein de choses intéressantes et SVK a certains atouts non négligeables à détourner :</a></p>
<ul>
<li>
<p><a name="h7">Plutôt Plutôt que de sauvegarder le répertoire <em>~/.svk</em>, utilisez toute la puissance de SVK en faisant une copie de <em>//local</em> sur un autre serveur. Vous pouvez par exemple sur ce second serveur faire :</a></p>
<pre><a name="h7">  svk ls svn+ssh://mon.serveur.principal/home/nc/.svk/local/</a></pre>
<p><a name="h7">et reprendre ce que nous avons vu précédemment pour déclarer ce miroir. Vous aurez une sauvegarde à peu de frais entièrement gérée par SVK en lançant régulièrement</a></p>
<pre><a name="h7">  svk pull //mirror/serveurprincipal/</a></pre>
<p><a name="h7">Vous pouvez aussi bien sur utiliser la recette pour répliquer un dépôt local sur un dépôt distant. À vous de voir ce qui vous convient le mieux.</a></p>
</li>
<li>
<p><a name="h7">comme il n&#8217;est pas limité aux fichiers textes, il peut gérer les versions d&#8217;images ou de documents d&#8217;une suite bureautique. Bien sûr vous ne pourrez pas faire de <code>diff</code> entre deux versions.</a></p>
<p><a name="h7">Quoique, si vous utilisez OpenOffice.org et le format OpenDocument, il devrait être possible d&#8217;écrire un <code>oodiff</code> et d&#8217;utiliser la variable SVKDIFF pour l&#8217;utiliser à la place du <code>diff</code> standard&#8230;</a></p>
<p><a name="h7">Et comme il peut être associé à un serveur HTTP ou Subversion, il peut même servir à faire du travail collaboratif à plus ou moins grande échelle.</a></p>
</li>
<li>
<p><a name="h7">pour gérer plus facilement la traduction de documents comme expliqué par le développeur de SVK lui-même : </a><a href="http://www.onlamp.com/pub/a/onlamp/2004/09/09/svk_translation.html">http://www.onlamp.com/pub/a/onlamp/2004/09/09/svk_translation.html</a>.</p>
</li>
<li>
<p>vous pouvez imaginer versionner tout ou partie de votre répertoire personnel sous SVK et faire un miroir de tout cela sur vos différents ordinateurs. Cela permet d&#8217;avoir un backup à peu de frais et/ou de synchroniser certains fichiers intéressants (.zshrc, &#8230;)</p>
</li>
<li>
<p>il peut servir à un administrateur système pour versionner les fichiers de configuration de ses serveurs avec le gros avantages sur certains autres outils du même type de ne pas avoir besoin d&#8217;un répertoire spécial comme <em>CVS</em> ou <em>.svn</em> et de pouvoir importer sur place un répertoire. Imaginez par exemple que sur tous vos serveurs vous fassiez :</p>
<pre> % svk import --to-checkout /etc/ //local/etc-serveur1</pre>
<p>et qu&#8217;ensuite pour poussiez tout cela sur un serveur SVK centralisé grâce à la recette vu plus haut pour répliquer un dépot local sur un dépot distant. Cerise sur le gateau, vous pouvez même le faire sans ouvrir de trou dans votre pare-feu en utilisant les redirections de <code>SSH</code>.</p>
<p>Depuis votre serveur central vous pouvez voir toutes les modifications apportées à vos fichiers de configuration (bonjour ITIL). Vous pouvez comparer la version locale avec la version distante pour vérifier que rien n&#8217;a changé (voire automatiser cela et envoyer un mail en cas de changement).</p>
</li>
</ul>
<p>Comme vous le voyez, les possibilités sont larges.</p>
</div>
<div><a name="h8"></a></p>
<h1><a name="h8">Conclusion</a></h1>
<p><a name="h8">Notre tour d&#8217;horizon de SVK s&#8217;arrête là, il resterait bien sûr encore des choses à dire pour être complet, comme développer tout ce que l&#8217;on peut faire avec les hooks par exemple, mais cela n&#8217;a jamais été l&#8217;ambition de cet article. J&#8217;espère seulement qu&#8217;il vous aura donné envie d&#8217;utiliser un outil de gestion de versions si vous n&#8217;en utilisez pas encore que ça soit pour développer ou pour gérer vos serveurs, et de regarder de plus près SVK si vous en utilisez déjà un.</a></p>
</div>
<div><a name="h9"></a></p>
<h1><a name="h9">Les liens</a></h1>
<div>
<ul>
<li>
<p><a href="http://svk.elixus.org/">http://svk.elixus.org/</a> &#8212; La page du projet</p>
</li>
<li>
<p><a href="http://svkbook.elixus.org/">http://svkbook.elixus.org/</a> &#8212; Le manuel (en cours d&#8217;écriture)</p>
</li>
<li>
<p><a href="http://svk.bestpractical.com/">http://svk.bestpractical.com/</a> &#8212; Le wiki de SVK</p>
</li>
<li>
<p><a href="http://www.redmine.org/">http://www.redmine.org</a> &#8212; rien à voir avec SVK mais c&#8217;est un application web de gestion de  projets GPL qui mérite vraiment le détour. Simple, de bon  gout et pourtant vraiment puissant.</p>
</li>
</ul>
</div>
</div>
<div><a name="h10"></a></p>
<h1><a name="h10">Ours</a></h1>
<ul>
<li>
<p><a name="h10">Nicolas Chuche &#8211; &lt;nchuche@barna.be&gt;</a></p>
<p><a name="h10">Nicolas Chuche est ingénieur système au ministère de l&#8217;Équipement et utilisateur de systèmes GNU/Linux et Unix depuis une dizaine d&#8217;années.</a></p>
</li>
</ul>
<p><a name="h10">Merci aux Mongueurs de toute la Francophonie qui ont assuré la relecture de cet article.</a></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=227</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sed Text filtering</title>
		<link>http://blog.pepita.org/?p=222</link>
		<comments>http://blog.pepita.org/?p=222#comments</comments>
		<pubDate>Wed, 31 Mar 2010 12:52:20 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[sed]]></category>
		<category><![CDATA[Vi]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=222</guid>
		<description><![CDATA[Quelques commandes utiles avec Sed:


filtrage des commantaires:
sed &#8216;/^#/d;; s/#.*$//&#8217;

Suppression des lignes vides ou pleine d&#8217;espace
sed &#8216;/^[[:space:]]*$/d&#8217;

Mise en colonnes avec Awk:
df -m &#124; awk &#8216;{printf &#8220;%-20s \t %-9s \t %-4s \t %s\n&#8221;,$1,$3,$4,$7}&#8217;


]]></description>
			<content:encoded><![CDATA[<p><strong><span style="font-size: medium;"><span style="text-decoration: underline;">Quelques commandes utiles avec Sed:</span></span></strong></p>
<p><br class="spacer_" /></p>
<ul style="padding-left: 30px;">
<li>filtrage des commantaires:</li>
<blockquote><p>sed &#8216;/^#/d;; s/#.*$//&#8217;</p>
</blockquote>
<li>Suppression des lignes vides ou pleine d&#8217;espace</li>
<blockquote><p>sed &#8216;/^[[:space:]]*$/d&#8217;</p>
</blockquote>
<li>Mise en colonnes avec Awk:</li>
<blockquote><p>df -m | awk &#8216;{printf &#8220;%-20s \t %-9s \t %-4s \t %s\n&#8221;,$1,$3,$4,$7}&#8217;</p>
</blockquote>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=222</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memo éditeur de texte VI et VIM</title>
		<link>http://blog.pepita.org/?p=218</link>
		<comments>http://blog.pepita.org/?p=218#comments</comments>
		<pubDate>Wed, 31 Mar 2010 12:34:14 +0000</pubDate>
		<dc:creator>stratus</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[editeur]]></category>
		<category><![CDATA[Vi]]></category>
		<category><![CDATA[Vim]]></category>

		<guid isPermaLink="false">http://blog.pepita.org/?p=218</guid>
		<description><![CDATA[
Commandes  d&#8217;insertion de texte 
 i insert insertion avant le curseur 
  I insert insertion au début de la ligne 
  a append insertion après le curseur 
  A append insertion à la fin de la ligne 
  o open ouvre une ligne blanche en dessous de la ligne  [...]]]></description>
			<content:encoded><![CDATA[<div>
<p><strong>Commandes  d&#8217;insertion de texte </strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> i insert insertion avant le curseur <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> I insert insertion au début de la ligne <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> a append insertion après le curseur <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> A append insertion à la fin de la ligne <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> o open ouvre une ligne blanche en dessous de la ligne  courante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> O open ouvre une ligne blanche au dessus de la ligne courante</p>
<p><span id="more-218"></span></p>
<p>Pour abandonner le mode insertion et retourner au mode  commande, appuyer sur la touche</p>
<p>insert insertion d&#8217;un caractère de contrôle</p>
<p><strong>Commande de concaténation</strong></p>
<p>J concatenate concatène la ligne suivante à la fin de la  ligne courante</p>
<p><strong>Commandes de déplacements</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> /\ curseur déplacement d&#8217;une ligne vers le haut <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> \/ curseur déplacement d&#8217;une ligne vers le bas <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> &lt;= curseur déplacement d&#8217;un caractère vers la gauche <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> =&gt; curseur déplacement d&#8217;un caractère vers la droite <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> w word avance au début du mot suivant <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> F forward page suivante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> B backward page précédente <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> ^ ou 0 début de la ligne courante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> $ fin de la ligne courante</p>
<p><strong>Recherche d&#8217;un chaîne de caractères</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> /toutou recherche la chaîne &#8220;toutou&#8221; à partir de la position  actuelle du curseur vers le bas du fichier <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> ?toutou recherche la chaîne &#8220;toutou&#8221; à partir de la position  actuelle du curseur vers le haut du fichier <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> n new recherche la prochaine occurence de la chaîne &#8220;toutou&#8221;  recherche vers le bas du fichier <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> N new recherche l&#8217;occurence précédente de la chaîne &#8220;toutou&#8221;  recherche vers le haut du fichier</p>
<p><strong>Suppression et utilisation du  buffer</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> x suppression du caractère sous le curseur <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> X suppression du caractère précédent le curseur <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> dd delete suppression de la ligne courante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> yy yank copie la ligne courante dans le buffer <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> p paste colle la ligne contenu dans le buffer après la ligne  courante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> P paste colle la ligne contenu dans le buffer avant la ligne  courante <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> u undo annule la dernière commande et seulement la dernière</p>
<p>Les commandes x, X, dd, et yy peuvent être précédées  d&#8217;un facteur multiplicateur de leur action. Par exemple 7dd supprimera  la ligne courante et les 6 lignes suivantes.</p>
<p><strong>Remplacement</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> r replace remplace le caractère sous le curseur par un  nouveau caractère <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> R replace remplace tous les caractères par de nouveaux  caractères. Pour terminer appuyer sur la touche  <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> C change remplace la fin de la ligne par de nouveaux  caractères. Pour terminer appuyer sur la touche</p>
<p><strong>Expressions régulières et mode  commande globale</strong></p>
<p>Les expressions régulières servent à manipuler le  fichier texte dans son ensemble.</p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> . représente un caractère quelconque <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> * multiplicateur du caractère précédent <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> ^ début de ligne <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> $ fin de ligne ou fin de fichier <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> \ permet de représenter les caractères . * ^ $ en le mettant  devant. Exemple : \* ou \$ <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> \1 permet la réécriture de l&#8217;expression régulière lors d&#8217;une  substitution <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> s commande de substitution <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> d commande de destruction de lignes <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> : passage en mode commande globale <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> g parcours global du fichier ou de la ligne</p>
<p><strong>Exemples :</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :1,$s/neant/bof/g de la ligne 1 à la dernière ligne,  substitution de la chaîne neant par la chaîne bof <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :1,$s/neant/bof/ idem mais seulement pour la première  occurence de la chaîne neant par ligne <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :1,3s/^.*=/BRAVO/ de la ligne 1 à la ligne 3, substitution du  début de la ligne (^) jusqu&#8217;au (.*) caractère = par la chaîne BRAVO <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> 1,$s/B.*O/\1 Veinard/ rajoute aux mots commençant par B et  terminant par O, le mot &#8220;Veinard&#8221; <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :1,$s/.$// suppression du dernier ($) caractère quel qu&#8217;il  soit (.) <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :10,20d suppression des lignes 10 à 20 <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :g/^#/d suppression des lignes commençant par un # <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :g/^M/s//^M/g suppression des ^M en  milieu de ligne et substitution par un vrai retour à la ligne. Taper sur  &#8220;Enter&#8221; pour obtenir le ^M.</p>
<p><strong>Divers mais utiles</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :set showmode indique le mode (insertion ou commande) en bas  de la fenêtre <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :set number affiche le numéro de chaque ligne <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :155 positionne sur la ligne 155 <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :set filetype=unix transforme le type DOS d&#8217;un fichier en  type UNIX</p>
<p><strong>Sauvegarder et quitter</strong></p>
<p><img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :w write sauvegarde le fichier en cours d&#8217;édition <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :q quit abandonne l&#8217;édition <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> :q ! quit abandonne l&#8217;édition sans sauvegarder le fichier <br />
 <img style="height: 11px; width: 8px;" src="http://www.karlesnine.com/local/cache-vignettes/L8xH11/puce-53a1d.gif" alt="-" width="8" height="11" /> <img src='http://blog.pepita.org/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' />  exit sauvegarde le fichier en cours d&#8217;édition et abandonne  l&#8217;édition (idem :wq)</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepita.org/?feed=rss2&amp;p=218</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
