<?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>Linux Attitude&#187; Commande</title>
	<atom:link href="http://linux-attitude.fr/tag/commande/feed" rel="self" type="application/rss+xml" />
	<link>http://linux-attitude.fr</link>
	<description>Le libre est un état d&#039;esprit</description>
	<lastBuildDate>Tue, 20 Jul 2010 19:54:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Présentation, cours</title>
		<link>http://linux-attitude.fr/post/presentation-cours</link>
		<comments>http://linux-attitude.fr/post/presentation-cours#comments</comments>
		<pubDate>Thu, 15 Jul 2010 21:07:02 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/?p=949</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;: script, scriptreplay


Vous voulez préparer un cours ou une présentation à base de ligne de commande, espionner quelqu'un ...&#160;?


Ça vous ennuie de taper les commandes en direct&#160;?


J'ai la solution&#160;: script.


Script

Script est une commande qui crée un faux terminal virtuel et duplique tout ce qui s'y passe dans un fichier typescript.


Exemple&#160;:

$ [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;: script, scriptreplay</p>


<p>Vous voulez préparer un cours ou une présentation à base de ligne de commande, espionner quelqu'un ...&nbsp;?</p>


<p>Ça vous ennuie de taper les commandes en direct&nbsp;?</p>


<p>J'ai la solution&nbsp;: script.</p>


<h3>Script</h3>

<p>Script est une commande qui crée un faux terminal virtuel et duplique tout ce qui s'y passe dans un fichier typescript.</p>


<p>Exemple&nbsp;:</p>
<pre>
$ script
# on est ici dans un terminal
$ echo coucou
&gt; coucou
$ exit
# on est sorti du terminal
$ cat typescript
&gt; $ echo coucou
&gt; coucou
&gt; $ exit
</pre>


<p>Dit comme ça, ça ne semble pas très utiles mais 2 choses vont tout changer. La première c'est que script fait un vrai terminal virtuel et pas seulement une redirection, ce qui veut dire que contrairement aux pipe (|) et autres redirections (&gt;), il est capable d'enregistrer ce qui va sur le terminal (Il est important de savoir faire la différence entre le terminal et stdout).</p>


<p>Exemple&nbsp;: la commande time. Cette commande écrit le temps d'exécution directement sur le terminal et pas dans la sortie standard, on ne peut donc pas la récupérer facilement, script le peut.
<span id="more-949"></span></p>


<h3>Scriptreplay</h3>

<p>La 2e commande qui va tout changer&nbsp;: scriptreplay.</p>


<p>Maintenant faites le même test mais enregistrez vos commande avec le paramètre -t (la sortie de -t va dans stderr, ça pourrait être mieux, mais c'est comme ça)&nbsp;:</p>
<pre>
$ script -t 2&gt; timer
</pre>


<p>Et cette fois utilisez scriptreplay pour lire ce qui a été généré&nbsp;:</p>
<pre>
$ scriptreplay timer typescript
</pre>


<p>Et là vous avez out ce qu'il faut pour faire une présentation qui dure exactement le même temps que celui qui vous a été nécessaire pour taper les commandes.</p>


<p>Si vous voulez adapter les timer vous pouvez, le script est éditable, mais bon à la main c'est un peu chiant. Par contre vous pouvez utiliser ctrl-s (pause) et ctrl-q (unpause) pour contrôler l'exécution du rendu.</p>


<p><strong>PS</strong>&nbsp;: pour ceux qui suivent, il est possible de remplacer mon ssh -t de l'article sur <a href="/post/test-de-bootloader-a-distance">le test de bootloader</a> par une commande script, ce qui est un peu plus propre.</p>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/presentation-cours/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Postscript est un langage &#8230; de script</title>
		<link>http://linux-attitude.fr/post/postscript-est-un-langage-de-script</link>
		<comments>http://linux-attitude.fr/post/postscript-est-un-langage-de-script#comments</comments>
		<pubDate>Wed, 28 Apr 2010 17:25:46 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/?p=411</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;:


Savez-vous vraiment utiliser postscript ?
Savez-vous ce qu'est postscript&#160;?


Postscript est avant tout un langage, relativement complet. Ce langage se destine à l'affichage et à l'impression. Il contient donc de nombreuses primitives pour l'affichage, principalement vectoriel. Mais rien ne vous force à l'utiliser pour ça. Il existe bien des gens qui utilisent [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;:</p>


<p>Savez-vous vraiment utiliser postscript ?<br />
Savez-vous ce qu'est postscript&nbsp;?</p>


<p>Postscript est avant tout un langage, relativement complet. Ce langage se destine à l'affichage et à l'impression. Il contient donc de nombreuses primitives pour l'affichage, principalement vectoriel. Mais rien ne vous force à l'utiliser pour ça. Il existe bien des gens qui utilisent php pour faire des scripts d'administration ...</p>


<h3>Interprétation</h3>


<p>Le postscript s'interprète, les imprimantes sont donc des interpréteurs postscript, ce qui veut dire qu'on peut les programmer comme on veut. Il existe bien des gens qui programment leur carte graphique pour faire du calcul parallèle ...</p>


<p>Apprenons donc à interpréter un fichier nommé toto.ps&nbsp;:</p>
<pre>
# technique simple pour en faire un pdf
$ ps2pdf toto.ps

# ancienne technique chamane qui passe par l'imprimante
$ gs -dSAFER -dNOPAUSE -sDEVICE=deskjet -sOutputFile=\|lpr toto.ps
</pre>


<p>Vous pouvez aussi passer par l'interface de cups à la place de lpr.</p>


<p>Notez bien qu'ici l'interpréteur est ghostscript (gs) et qu'on a du spécifier le type d'imprimante, type qu'on n'a pas choisi au hasard. Pour avoir la liste des imprimantes supportées, tapez&nbsp;:</p>
<pre>
$ gs -help
</pre>

<p>Et lisez bien la liste vous verrez des bizarreries comme jpeg, png256, bmpgray ... Ce ne sont pas vraiment des imprimantes, donc vous devinez bien qu'il est donc possible de convertir très facilement un fichier postscript en image jpeg (enfin la première page en tout cas)&nbsp;:</p>
<pre>
$ gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=jpeg -sOutputFile=fichier.jpg toto.ps
</pre>


<p>Pour avoir les autres pages et la résolution de l'image, voici la commande&nbsp;:</p>
<pre>
# scriptez le si ca vous sert
$ gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=jpeg -r72 -sOutputFile=fichier-%d.jpg toto.ps
</pre>


<p>Un peu plus de détail sur les paramètres et les sorties possibles ici&nbsp;: <a href="http://pages.cs.wisc.edu/~ghost/doc/AFPL/8.00/Devices.htm" title="http://pages.cs.wisc.edu/~ghost/doc/AFPL/8.00/Devices.htm">http://pages.cs.wisc.edu/~ghost/doc...</a> ou dans le manuel.</p>


<p>Voila, on n'a pas trop parlé de script ici, mais il en sera question dans le prochain article. D'ailleurs si vous voulez développer dès à présent, il suffit de lancer gs sans -dBATCH et sans fichier postscript pour obtenir une console interactive.</p>


<p><strong>PS</strong>&nbsp;: Notez au passage qui toutes les commandes gs fonctionnent aussi avec du PDF car ce dernier est un autre langage compris par gs.</p>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/postscript-est-un-langage-de-script/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Prompt String</title>
		<link>http://linux-attitude.fr/post/prompt-string</link>
		<comments>http://linux-attitude.fr/post/prompt-string#comments</comments>
		<pubDate>Thu, 29 Oct 2009 21:51:18 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/?p=574</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;: export PS1="&#62; "


Désolé de ne pas écrire plus souvent. Et ca risque de durer encore un peu puisque je pars en vacances ...



PS veut dire prompt string.  Les 4 prompt string de bash sont les chaines de caractères affichées par le shell en différentes situations. Nous allons nous [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;: export PS1="&gt; "</p>


<p>Désolé de ne pas écrire plus souvent. Et ca risque de durer encore un peu puisque je pars en vacances ...</p>



<p>PS veut dire prompt string.  Les 4 prompt string de bash sont les chaines de caractères affichées par le shell en différentes situations. Nous allons nous intéresser à PS1  mais sachez que la suite vaut pour toutes les autres.</p>


<h3>Exemples</h3>

<p>Je vais faire simple&nbsp;: des exemples de chaînes ainsi que la capture d'écran associée, il ne vous reste plus qu'a choisir et à copier/coller dans votre .bashrc</p>


<p>Toutes les captures ont été faites avec les settings suivants&nbsp;:</p>
<ul>
<li>user&nbsp;: peck</li>
<li>hostname&nbsp;: mamachine.linux-attitude.fr</li>
</ul>

<h4>Exemples unilignes</h4>
<table>
<tr><th>PS1</th><th>Fond noir / Fond Blanc</th></tr>
<tr>
<td>"[\t] \[\e[01;32m\]\u\[\e[01;33m\]@\h\[\e[00m\]:\[\e[01;34m\]\w\[\e[00m\]\$ "</td>
<td><img src="/public/Prompt/b01.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w01.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td>"\[\033[01;32m\]\u@\h \[\033[01;34m\]\W \$ \[\033[00m\]"</td>
<td><img src="/public/Prompt/b02.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w02.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

</tr>
<tr>
<td>"\[\033[0;34m\][\[\033[0;31m\]$(date +%H%M)\[\033[0;34m\]]\[\033[0;34m\][\[\033[1;31m\]\u@\h:\w\[\033[0;34m\]]\[\033[1;37m\]$\[\033[0m\] "</td>
<td><img src="/public/Prompt/b03.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w03.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

</tr>
<tr>
<td></td>
<td>
&nbsp;<br />&nbsp;
</td>
</tr>
</table>



<p><span id="more-574"></span></p>


<h4>Exemples multilignes</h4>

<table>
<tr><th>PS1</th><th>Fond noir / Fond Blanc</th></tr>
<tr>
<td>"\[\e]0;\u@\h \w\a\]\[\e[1;31m\]\u\[\e[1;34m\]@\[\e[0;32m\]\h \[\e[0;33m\]\w \[\e[0;31m\]$(uptime|sed -e 's/.*: \([^,]*\), \([^,]*\), \([^,]*\).*/\1 \2 \3/') \[\e[0;34m\]\D{%Y-%m-%d %H:%M:%S} \[\e[0m\]\n\$ "</td>
<td><img src="/public/Prompt/b04.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w04.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td></td>
<td>
&nbsp;<br />&nbsp;
</td>
</tr>
</table>



<h4>Exemples monochromes</h4>

<table>
<tr><th>PS1</th><th>Fond noir / Fond Blanc</th></tr>

<tr>
<td>"[\t][\u@\h:\w]\$ "</td>
<td><img src="/public/Prompt/b05.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w05.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td>"\u@\h \w> "</td>
<td><img src="/public/Prompt/b06.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w06.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td>"\!|\h|$(uname -r)|\$?> "</td>
<td><img src="/public/Prompt/b07.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w07.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td>"\[\e[1;34m\]\u@\h \w>\[\e[0m\] "</td>
<td><img src="/public/Prompt/b08.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w08.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
</td>
</tr>

<tr>
<td>"\[\e]2;\u@\H \w\a\e[32;1m\]>\[\e[0m\] "</td>
<td><img src="/public/Prompt/b09.png" alt="black" title="black" class="alignnone size-full wp-image-578" />
<br /><img src="/public/Prompt/w09.png" alt="white" title="white" class="alignnone size-full wp-image-578" />
<br />(Ici tout est dans le titre)
</td>
</tr>
</table>




<p>Faites votre choix</p>


<h3>Cookbook</h3>


<p>Si les exemples ne vous conviennent pas, voici un ensemble de recettes pour créer un prompt qui vous ressemble&nbsp;:</p>

<ul>
<li>load average&nbsp;: "\$(cut -d ' ' -f 1-3 /proc/loadavg)"</li>
<li>uptime&nbsp;: "\$(uptime | cut -d, -f1 | sed -e 's/.*up//')"</li>
<li>un prompt qu'on peut copier/coller sans provoquer d'erreurs&nbsp;: ": &lt;texte&gt; ;"</li>
<li>user@host:/répertoire&nbsp;: "\u@\h:\w"</li>
<li>date et heure&nbsp;: "[\d \t]"</li>
<li>un bip à chaque ligne&nbsp;: "\[\a\]"</li>
<li>changer la couleur du texte (code couleur voir ci dessous)&nbsp;: "\[\e[&lt;code_couleur&gt;m\]"</li>
<li>revenir à la couleur originale du shell (en fin de ligne)&nbsp;: "\[\e[0m\]"</li>
<li>code de retour de la dernière commande&nbsp;: "-&gt; \$?"</li>
<li>nombre de jobs mis en background par le shell&nbsp;: "[\j]"</li>
<li>nombre de jobs en pause&nbsp;: "\$(jobs | wc -l | awk '{print $1}')"</li>
<li>nombre de processus en cours d'exécution&nbsp;: "\$(ps ax | wc -l | tr -d ' ')"</li>
<li>afficher le tty en cours&nbsp;: "$(temp=$(tty)&nbsp;; echo ${temp:5})"</li>
<li>chemin limité à 20 caractères&nbsp;: "\$(a='\w';b=\${a: -20};b=\${b:+..\$b};echo \${b:-\$a})"</li>
<li>changer le texte de titre du terminal (xterm, konsole ...)&nbsp;: "\[\e]0;&lt;Texte&gt;\a\]"</li>
<li>afficher l'état de la gestion de version en cours (voir ci dessous)&nbsp;: "$(__vcs_dir)"</li>
<li>afficher la sortie d'une commande&nbsp;: "\$(&lt;commande&gt;)"</li>
</ul>


<h4>Codes couleur ANSI</h4>


<p>Il est possible d'indiquer plusieurs codes simultanément en les séparant par un ';'.</p>


<p>From <a href="http://en.wikipedia.org/wiki/ANSI_escape_code" hreflang="en">wikipedia</a>&nbsp;:</p>

<table class="wikitable">
<caption>Code couleur</caption>
<tbody><tr>
<th>Code</th>
<th>Effect</th>
<th>Note</th>
</tr>
<tr>
<td>0</td>
<td>Reset / Normal</td>
<td>all attributes off</td>
</tr>
<tr>
<td>1</td>
<td>Intensity: Bold</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>Intensity: Faint</td>
<td>not widely supported</td>
</tr>
<tr>
<td>3</td>
<td>Italic: on</td>
<td>not widely supported. Sometimes treated as inverse.</td>
</tr>
<tr>
<td>4</td>
<td>Underline: Single</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>Blink: Slow</td>
<td>less than 150 per minute</td>
</tr>
<tr>
<td>6</td>
<td>Blink: Rapid</td>
<td>MS-DOS ANSI.SYS; 150 per minute or more</td>
</tr>
<tr>
<td>7</td>
<td>Image: Negative</td>
<td>inverse or reverse; swap foreground and background</td>
</tr>
<tr>
<td>8</td>
<td>Conceal</td>
<td>not widely supported</td>
</tr>
<tr>
<td>21</td>
<td>Underline: Double</td>
<td>not widely supported</td>
</tr>
<tr>
<td>22</td>
<td>Intensity: Normal</td>
<td>not bold and not faint</td>
</tr>
<tr>
<td>24</td>
<td>Underline: None</td>
<td></td>
</tr>
<tr>
<td>25</td>
<td>Blink: off</td>
<td></td>
</tr>
<tr>
<td>27</td>
<td>Image: Positive</td>
<td></td>
</tr>
<tr>
<td>28</td>
<td>Reveal</td>
<td>conceal off</td>
</tr>
<tr>
<td>30–39</td>
<td>Set foreground color, normal intensity</td>
<td>3x, where x is from the color table below</td>
</tr>
<tr>
<td>40–49</td>
<td>Set background color, normal intensity</td>
<td>4x, where x is from the color table below</td>
</tr>
<tr>
<td>90–99</td>
<td>Set foreground color, high intensity</td>
<td>aixterm</td>
</tr>
<tr>
<td>100–109</td>
<td>set background color, high intensity</td>
<td>aixterm</td>
</tr>
</tbody></table>


<table class="wikitable">
<caption>Table des couleurs</caption>
<tbody><tr>
<th>Intensité</th>
<th>0</th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>9</th>
</tr>
<tr>
<th>Normal</th>
<td style="background: black; color: white;">Black</td>
<td style="background: maroon; color: white;">Red</td>
<td style="background: green; color: white;">Green</td>
<td style="background: olive; color: white;">Yellow<sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span>[</span>5<span>]</span></a></sup></td>
<td style="background: navy; color: white;">Blue</td>
<td style="background: purple; color: white;">Magenta</td>
<td style="background: teal; color: white;">Cyan</td>
<td style="background: silver; color: black;">White</td>
<td>reset</td>
</tr>
<tr>
<th>Brillant</th>
<td style="background: gray; color: white;">Black</td>
<td style="background: red; color: black;">Red</td>
<td style="background: lime; color: black;">Green</td>
<td style="background: yellow; color: black;">Yellow</td>
<td style="background: blue; color: white;">Blue</td>
<td style="background: fuchsia; color: black;">Magenta</td>
<td style="background: cyan; color: black;">Cyan</td>
<td style="background: white; color: black;">White</td>
</tr>
</tbody></table>





<h4>Gestion de version</h4>


<p>Pour que la méthode de gestion de version fonctionne, il faut ajouter le code suivant dans son .bashrc&nbsp;:</p>
<pre>
alias svnwdiff=&quot;svn diff --diff-cmd /home/spaillar/vimdiff-wrapper.sh&quot;
function cvswdiff { vimdiff $1 &lt;(cvs co -p $2 $(cat $(dirname $1)/CVS/Repository)/$(basename $1)) ;} 

function vlog { 
# cvs
cvs_log() {
   [ -d &quot;CVS&quot; ] || return 1
   cvs log &quot;$@&quot; | vim -
}

# subversion
svn_log() {
    [ -d &quot;.svn&quot; ] || return 1
    svn log -v &quot;$@&quot; | vim -
}
# git
git_log() {
    base_dir=$(git rev-parse --show-cdup 2&gt;/dev/null) || return 1
    git log --name-status &quot;$@&quot; | vim -
}

git_log &quot;$@&quot; || svn_log &quot;$@&quot; || cvs_log &quot;$@&quot;

}

function vwdiff {
vim -c &quot;:VCSVimDiff&quot; $1
}

function vpull { 
# cvs
cvs_pull() {
   [ -d &quot;CVS&quot; ] || return 1
   cvs -q up -d
}

# subversion
svn_pull() {
    [ -d &quot;.svn&quot; ] || return 1
    svn up 
}
# git
git_pull() {
    base_dir=$(git rev-parse --show-cdup 2&gt;/dev/null) || return 1
    git pull 
}

git_pull &quot;$@&quot; || svn_pull &quot;$@&quot; || cvs_pull &quot;$@&quot;

}



_bold=$(tput bold)
_normal=$(tput sgr0)
_yellow=$(tput setaf 3)
_green=$(tput setaf 2)

__vcs_dir() {
  local vcs base_dir sub_dir ref
  sub_dir() {
  local sub_dir
  sub_dir=$(readlink -f &quot;${PWD}&quot;)
  sub_dir=${sub_dir#$1}
  echo ${sub_dir#/}
  }

  # git
  git_dir() {
      base_dir=$(git rev-parse --show-cdup 2&gt;/dev/null) || return 1
      if [ -n &quot;$base_dir&quot; ]; then
        base_dir=`cd $base_dir; pwd`
      else
        base_dir=$PWD
      fi
      sub_dir=$(git rev-parse --show-prefix)
      sub_dir=&quot;/${sub_dir%/}&quot;
      ref=$(git symbolic-ref -q HEAD || git name-rev --name-only HEAD 2&gt;/dev/null)
      ref=${ref#refs/heads/}
      vcs=&quot;git&quot;
      alias pull=&quot;git pull&quot;
      alias commit=&quot;git commit&quot;
      alias push=&quot;git push&quot;
#     alias revert=&quot;svn revert&quot;
    }

  # subversion
  svn_dir() {
      [ -d &quot;.svn&quot; ] || return 1
      base_dir=&quot;.&quot;
      while [ -d &quot;$base_dir/../.svn&quot; ]; do base_dir=&quot;$base_dir/..&quot;; done
      base_dir=`cd $base_dir; pwd`
      sub_dir=&quot;/$(sub_dir &quot;${base_dir}&quot;)&quot;
      ref=$(svn info &quot;$base_dir&quot; | awk '/^URL/ { sub(&quot;.*/&quot;,&quot;&quot;,$0); r=$0 } /^Revision/ { sub(&quot;[^0-9]*&quot;,&quot;&quot;,$0); print r&quot;:&quot;$0 }')
      vcs=&quot;svn&quot;
      alias pull=&quot;svn up&quot;
      alias commit=&quot;svn commit&quot;
      alias push=&quot;svn ci&quot;
      alias revert=&quot;svn revert&quot;
    }

  # mercurial
  hg_dir() {
      base_dir=&quot;.&quot;
      while [ ! -d &quot;$base_dir/.hg&quot; ]; do base_dir=&quot;$base_dir/..&quot;; [ $(readlink -f &quot;${base_dir}&quot;) = &quot;/&quot; ] &amp;&amp; return 1; done
      base_dir=$(readlink -f &quot;$base_dir&quot;)
      sub_dir=&quot;/$(sub_dir &quot;${base_dir}&quot;)&quot;
      ref=$(&lt; &quot;${base_dir}/.hg/branch&quot;)
      hgqtop=$(hg qtop)
      if [[ $hgqtop == 'No patches applied' ]]; then 
        extra=&quot;&quot;;
      else 
        extra=&quot; &gt;&gt; $hgqtop&quot;
      fi
      vcs=&quot;hg&quot;
  }

  # cvs
  cvs_dir() {
      [ -d &quot;CVS&quot; ] || return 1
      base_dir=&quot;.&quot;
      while [ -d &quot;$base_dir/../CVS&quot; ]; do base_dir=&quot;$base_dir/..&quot;; done
      base_dir=`cd $base_dir; pwd`
      sub_dir=&quot;/$(sub_dir &quot;${base_dir}&quot;)&quot;
      vcs=&quot;cvs&quot;
      alias pull=&quot;cvs -q up -d&quot;
      alias commit=&quot;cvs commit&quot;
      alias push=&quot;cvs ci&quot;
      alias revert=&quot;cvs revert&quot;


  }

  # hg_dir || git_dir || svn_dir || cvs_dir || base_dir=&quot;$PWD&quot;
  git_dir || svn_dir || cvs_dir || base_dir=&quot;$PWD&quot;
  echo &quot;${_green}${_bold}${vcs:+($vcs)}${_yellow}${_bold}${vcs:+[$ref]}${_normal}${base_dir/$HOME/~}${_yellow}${_bold}${vcs:+${_bold}${sub_dir}${_normal}$extra}&quot;
}

PS1='${debian_chroot:+($debian_chroot)}\u@\h:$(__vcs_dir)${_normal}\$ '
</pre>



<p>Et vous quel prompt utilisez vous&nbsp;?</p>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/prompt-string/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Propager son home</title>
		<link>http://linux-attitude.fr/post/propager-son-home</link>
		<comments>http://linux-attitude.fr/post/propager-son-home#comments</comments>
		<pubDate>Fri, 16 Oct 2009 16:23:11 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[Ssh]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/?p=495</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;:


Aujourd'hui nous allons mettre en valeur deux articles précédents. J'espère que vous avez déjà mis votre home sous un système de suivi de version pour suivre ses évolutions. J'ai déjà décrit à dans un article précédent. En résumé&#160;:

$ cd
$ git init
$ git add .bashrc # et tout ce que vous [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;:</p>


<p>Aujourd'hui nous allons mettre en valeur deux articles précédents. J'espère que vous avez déjà mis votre home sous un système de suivi de version pour suivre ses évolutions. J'ai déjà décrit à dans <a href="/post/Git-pour-tous">un article précédent</a>. En résumé&nbsp;:</p>
<pre>
$ cd
$ git init
$ git add .bashrc # et tout ce que vous voulez
$ git commit
</pre>


<p>Le but étant de propager tout cela automatiquement sur différentes machines. Il est difficile de toujours penser à mettre a jour lorsqu'on fait une modification. C'est pourquoi nous allons mettre à profit l'article précédent et <a href="/post/interception-silencieuse-de-ssh-2">intercepter ssh</a>. Grâce à cela le home de toutes nos machines seront à jour sans qu'on ait à s'en préoccuper.</p>


<h3>Mise en place</h3>

<p>Cette fois nous allons modifier le script en question pour lancer automatiquement une mise à jour de git de façon furtive à chaque connexion ssh. La méthode run était prévue pour&nbsp;:</p>
<pre>
# test permettant de savoir qu'on est bien sur le bon dépôt git pour les mises à jour (id du premier commit)
MASTER=11edf02e95ceac1fa58d4444f82f8cd4ae9c1cf5
# command tu run via the ssh socket
run()
{
    # no test if running init
    if [ &quot;$MASTER&quot; != &quot;&quot; ]
    then
        # test if distant has OUR git
        ssh -S &quot;$1&quot; XXX '[ -e /usr/bin/git ] &amp;&amp; [ -d .git ] &amp;&amp; git rev-list --reverse master 2&gt;/dev/null | head -1' | grep &quot;$MASTER&quot; &gt; /dev/null
    else
        ssh -S &quot;$1&quot; XXX '[ -e /usr/bin/git ]'
    fi
    if [ $? -eq 0 ]
    then
        # if yes push updates
        tmp=$(mktemp ~/.sshgit.XXXXXX)
        echo &quot;#!/bin/sh&quot; &gt; $tmp
        echo &quot;exec ssh -S $1 \&quot;\$@\&quot;&quot; &gt;&gt; $tmp
        chmod +x $tmp
        GIT_SSH=$tmp git push --all ssh://XXX/~ &gt; /dev/null 2&gt; /dev/null
        rm -f $tmp
        ssh -S &quot;$1&quot; XXX 'git checkout -f &gt; /dev/null'
    fi
}
</pre>


<p><span id="more-495"></span></p>


<p>De plus j'ai ajouté un paramètre spécial permettant d'initialiser le dépôt de la machine en face. En effet, on ne va pas forcer la mise à jour si le home en face n'a pas de dépôt, il se peut que l'utilisateur ne le veuille pas. C'est aussi pour ce qu'on vérifie que le dépôt git utilisé contient bien le bon commit initial.</p>
<pre>
            ssh -S &quot;$2&quot; XXX '[ -e /usr/bin/git ] &amp;&amp; [ ! -d .git ] &amp;&amp; git init &gt; /dev/null'
</pre>


<p><a href="/wp-content/uploads/sshalias">Le script complet</a>.</p>


<h3>Usage</h3>


<p>Pour que ça fonctionne on ajoute un alias et tant qu'à faire, on ajoute le script au dépôt&nbsp;:</p>
<pre>
$ alias ssh='~/.sshgit' # à mettre aussi dans le .bashrc
$ git add .sshgit
$ git commit
</pre>


<p>Et maintenant on initialise la machine en face&nbsp;:</p>
<pre>
$ ssh -= autremachine.net
</pre>


<p>Et voila, tout ssh ultérieur résultera en un git push suivi d'un git checkout, plus besoin de réfléchir. Ce qui veut dire qu'au fur et à mesure de vos ssh votre home se propagera un peu partout, que le réseau où vous êtes soit privé ou non car c'est la connexion normale du ssh qui est empruntée. Reste juste à faire un ssh de temps en temps un peu partout pour mettre à jour :-)</p>


<h3>Autre</h3>


<p>Si vous n'avez pas git sur toutes les machines, vous pouvez aussi utiliser autre chose pour synchroniser automatiquement vos home. rsync par exemple (regardez l'option -u pour les mises à jour) ou scp.</p>


<p>Mais pour le coup je vous laisse écrire la méthode :)</p>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a>, <a href="http://linux-attitude.fr/tag/ssh" title="Ssh" rel="tag">Ssh</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/propager-son-home/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interception silencieuse de ssh</title>
		<link>http://linux-attitude.fr/post/interception-silencieuse-de-ssh-2</link>
		<comments>http://linux-attitude.fr/post/interception-silencieuse-de-ssh-2#comments</comments>
		<pubDate>Mon, 21 Sep 2009 19:13:29 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[Ssh]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/?p=493</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé :alias ssh='ssh macommande &#38;&#38; ssh'


Aujourd'hui interceptons les commandes ssh. Alors ne commencez pas à penser que je suis passé du côté obscur de la force. Il y a des usage bien pratique ce script et je vous en proposerai un dans le prochain article.


Tout d'abord le problème&#160;: on veut [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong> :alias ssh='ssh macommande &amp;&amp; ssh'</p>


<p>Aujourd'hui interceptons les commandes ssh. Alors ne commencez pas à penser que je suis passé du côté obscur de la force. Il y a des usage bien pratique ce script et je vous en proposerai un dans le prochain article.</p>


<p>Tout d'abord le problème&nbsp;: on veut pouvoir intercepter une commande ssh de façon silencieuse pour pouvoir utiliser la connexion qui va s'établir et lancer les commandes qu'on veut sur la machine distante. Cela implique une acceptation implicite de l'utilisateur puisqu'on va utiliser un simple alias pour "intercepter" la commande. Bien sûr rien ne vous empêche de modifier l'alias d'un ami selon les moyens qui sont à votre disposition ;-)</p>


<h3>Principe de fonctionnement</h3>

<p>Vous vous dites qu'il suffit de reprendre les paramètres de la commande et de la relancer. Non, habitués que vous êtes à <a href="/post/Connexion-sans-mot-de-passe">l'agent ssh</a>, vous avez oublié qu'en son absence l'utilisateur devra taper un mot de passe pour que la commande passe.</p>


<p>Pour récupérer la connexion ssh, openssh met à notre disposition tout ce qu'il faut. L'option s'appelle <strong>ControlMaster</strong>, elle crée une socket sur laquelle ssh peut ensuite se connecter pour ouvrir un nouveau terminal sans repasser toute la chaine de connexion au serveur.</p>


<p>La méthode est donc fait simple&nbsp;:</p>
<ul>
<li>on intercepte la commande ssh (alias)</li>
<li>on lance notre script en background ($0 &amp;)</li>
<li>on ajoute un option -M et -S si besoin à la commande ssh pour créer la socket</li>
<li>on garde les options originales et le processus original (exec ssh -M -S "$@")</li>
<li>dans le script en background on peut ensuite utiliser directement la socket en question pour faire ce qu'on veut</li>
</ul>

<p><span id="more-493"></span></p>


<h3>Résultat</h3>


<p>Donc résumons&nbsp;: un alias</p>
<pre>
alias ssh='~/.sshalias'
</pre>


<p>Et un script nommé <strong>~/.sshalias</strong> (commentaires en anglais par habitude). Modifiez la commande run pour metre ce que vous voulez dedans</p>
<pre>
#!/bin/sh

# GPLv2 
# author : peck

#  command tu run via the ssh socket
run()
{
        # example ssh command
        ssh -S &quot;$1&quot; XXX 'hostname'
}

# test if we are the child which can connect via the master
if [ &quot;$1&quot; == &quot;-=0&quot; ]
then
    go=0
    # limit to 60 retries x 1s
    for i in $(seq 1 60)
    do
        sleep 1
        # try to connect via master
        ssh -S &quot;$2&quot; -O check xxx 2&gt;/dev/null
        if [ $? -eq 0 ]
        then
            go=1
            break
        fi
    done
    # run the stealth command
    if [ $go -eq 1 ]
    then
        sleep 1 # bug if we go too fast
        run &quot;$2&quot;
    fi
    # remove master socket if we created it
    if [ &quot;$3&quot; == &quot;0&quot; ]
    then
        rm -f &quot;$2&quot;
    fi
    exit 0
fi

# we are in a real ssh command
master=0
sock=&quot;&quot;
for i in &quot;$@&quot;
do
    # test if master is already provided
    if [ &quot;$i&quot; == &quot;-M&quot; ]
    then
        master=1
    fi
    # retrieve socket if provided
    if [ &quot;$i&quot; == &quot;-S&quot; ]
    then
        sock=&quot;.&quot;;
    fi
    if [ &quot;$i&quot; == &quot;.&quot; ]
    then
        sock=&quot;$i&quot;
    fi
done

# create socket name if needed
if [ &quot;$sock&quot; == &quot;&quot; ]
then
    sock=$(mktemp -u -t sshx.XXXXXX)
fi

# launch child which will use our master socket
$0 -=0 &quot;$sock&quot; &quot;$master&quot; &amp;

# run original command adding a master socket
if [ $master -eq 1 ]
then
    exec ssh &quot;$@&quot;
else
    exec ssh -S &quot;$sock&quot; -M &quot;$@&quot;
fi
</pre>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a>, <a href="http://linux-attitude.fr/tag/ssh" title="Ssh" rel="tag">Ssh</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/interception-silencieuse-de-ssh-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>En vrac (24)</title>
		<link>http://linux-attitude.fr/post/en-vrac-24</link>
		<comments>http://linux-attitude.fr/post/en-vrac-24#comments</comments>
		<pubDate>Tue, 30 Jun 2009 14:42:00 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/post/en-vrac-24</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;: perl -0777pe&#160;; ps kstart_time&#160;; stty -echo&#160;; expr&#160;; bc -l&#160;; tar c - &#124; ssh tar x -


Petite pause.


Appliquer une expression régulière en une seule fois sur tout un fichier (comme s'il ne faisait qu'une ligne)&#160;:

$ perl -0777pe 's/expression/remplacement/'



Connaitre les processus qui sont lancés "en ce moment", par exemple pendant [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;: perl -0777pe&nbsp;; ps kstart_time&nbsp;; stty -echo&nbsp;; expr&nbsp;; bc -l&nbsp;; tar c - | ssh tar x -</p>


<p>Petite pause.</p>


<p>Appliquer une expression régulière en une seule fois sur tout un fichier (comme s'il ne faisait qu'une ligne)&nbsp;:</p>
<pre>
$ perl -0777pe 's/expression/remplacement/'
</pre>


<p>Connaitre les processus qui sont lancés "en ce moment", par exemple pendant un script d'installation&nbsp;:</p>
<pre>
# listes les processus par date de création toutes les 2s
$  watch &quot;ps kstart_time aux |tail&quot;
</pre>


<p>Éviter d'afficher les mots de passe lorsque vous les demandez à l'utilisateur dans vos scripts shell&nbsp;:</p>
<pre>
$ stty -echo
$ read password
$ stty echo
</pre>


<p>Faire un calcul en ligne de commande (installé partout, même sur les vieux unix)&nbsp;:</p>
<pre>
$ expr 1 + 5
</pre>


<p>Faire un calcul en ligne de commande, mais en mieux&nbsp;:</p>
<pre>
# à mettre dans votre bashrc de préférence
$ bcl() { echo &quot;scale=2; $@&quot; | bc -l ; }
$ bcl 1+2
</pre>


<p>Tar over ssh (rsync quoi)&nbsp;:</p>
<pre>
$ tar cf - /repertoire | ssh mamachine.net &quot;cd /destination &amp;&amp; tar xvf -&quot;
</pre>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/en-vrac-24/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>En vrac (22)</title>
		<link>http://linux-attitude.fr/post/en-vrac-22</link>
		<comments>http://linux-attitude.fr/post/en-vrac-22#comments</comments>
		<pubDate>Tue, 14 Apr 2009 18:57:00 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Commande]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/post/en-vrac-22</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;: moreutils&#160;; ts&#160;; vidir&#160;; mispipe&#160;; isutf8&#160;; lckdo&#160;; vipe&#160;; ifdata&#160;; pee


Ces commandes sont dans le paquet moreutils sur debian.


Ajouter un timestamp sur chaque ligne pour lire une commande un peu lente&#160;:

$ ./commande &#124; ts &#124; tail




Éditer en masse les entrées d'un répertoire (pour renommer des images par exemple)&#160;:

# Tout le répertoire
$ [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;: moreutils&nbsp;; ts&nbsp;; vidir&nbsp;; mispipe&nbsp;; isutf8&nbsp;; lckdo&nbsp;; vipe&nbsp;; ifdata&nbsp;; pee</p>


<p>Ces commandes sont dans le paquet moreutils sur debian.</p>


<p>Ajouter un timestamp sur chaque ligne pour lire une commande un peu lente&nbsp;:</p>
<pre>
$ ./commande | ts | tail
</pre>



<p>Éditer en masse les entrées d'un répertoire (pour renommer des images par exemple)&nbsp;:</p>
<pre>
# Tout le répertoire
$ vidir repertoire
# Seulement les images 
$ vidir *.jpg
</pre>



<p>Retourner le code d'erreur du premier élément d'un pipe et non du dernier (très utile en scripting)&nbsp;:</p>
<pre>
# Retourne une erreur si $dir n'existe pas
$ mispipe &quot;ls $dir&quot; &quot;tail&quot;
</pre>



<p>Vérifier qu'un fichier utf8 est valide&nbsp;:</p>
<pre>
$ isutf8 fichier &amp;&amp; echo OK || echo &quot;Not OK&quot; 
</pre>



<p>Ne pas écraser un fichier de destination avant la fin de la commande&nbsp;:</p>
<pre>
# Version fonctionnelle de cat a b &gt; a
$ cat a b | sponge a
</pre>



<p>Créer un script de type cron avec un lock sans effort&nbsp;:</p>
<pre>
$ lckdo -W 10 /var/lock/mylock /usr/local/bin/myscript
</pre>



<p>Éditer le contenu d'un pipe (très pratique pour le debug de script)&nbsp;:</p>
<pre>
$ commande1 | vipe | commande2
</pre>



<p>Éviter les envois de mail de rapport lorsqu'il n'y a rien à rapporter&nbsp;:</p>
<pre>
$ /usr/local/bin/rapport.pl | ifne mail -s &quot;Synchro en retard&quot; sysadmins@mynnet.net
</pre>



<p>Permettre (optionnelle ment) de passer des fichiers compressés en argument à un script (comme pour zless)&nbsp;:</p>
<pre>
# Recoder zless
$ zrun less $1
</pre>



<p>Éviter de parser le résultat de ifconfig ou de ip dans un script (nombreuses options, de sortie, lire le man)&nbsp;:</p>
<pre>
# Afficher le nombre d'octets reçus
$ ifdata -sib eth0
</pre>



<p>Passer le résultat d'une commande à plusieurs autres</p>
<pre>
# Attention si commande1 et commande2 produit du texte, rien ne garantit leur ordre
$ commande | pee &quot;commande1&quot; &quot;commande2&quot;
</pre>



<p>Comparer ligne par ligne deux fichiers avec des opérateurs plus évolués que comm&nbsp;:</p>
<pre>
$ combine fichier1 xor fichier2
</pre>
	Tags:<a href="http://linux-attitude.fr/tag/commande" title="Commande" rel="tag">Commande</a>, <a href="http://linux-attitude.fr/tag/planet-libre" title="planet-libre" rel="tag">planet-libre</a>, <a href="http://linux-attitude.fr/tag/scripting" title="Scripting" rel="tag">Scripting</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/en-vrac-22/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using apc (user agent is rejected)
Database Caching 7/30 queries in 0.024 seconds using apc

Served from: linux-attitude.fr @ 2010-07-31 04:02:13 -->