<?xml version='1.0' encoding='iso-8859-1' standalone='no'?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
                  "/usr/local/share/xml/docbook/4.2/docbookx.dtd"
[
<!ENTITY ccdil "&ccedil;">
<!ENTITY organ "Néotech III">

<!ENTITY unix   "<productname>Unix</productname>">
<!ENTITY ie     "<abbrev>i.e.</abbrev>">
<!ENTITY cf     "<abbrev>c.f.</abbrev>">
<!ENTITY shell  "<foreignphrase>shell</foreignphrase>">
<!ENTITY todo   "<command>--- T O  D O :</command>">

<!ENTITY glinux "<emphasis>GNU/Linux</emphasis>">
<!ENTITY fshell "<emphasis>GNU/bash</emphasis>">

<!ENTITY _fcomp  SYSTEM "./fcomp.sh">
<!ENTITY _fdate  SYSTEM "./fdate.sh">
<!ENTITY _ftestp SYSTEM "./ftestparm.sh">
<!ENTITY _ftestv SYSTEM "./ftestvect.sh">

<!ENTITY _aut_Pre     "<firstname>Pascal</firstname>">
<!ENTITY _aut_Nom     "<surname>Picard</surname>">
<!ENTITY _aut_eMail   "<email>pascal@seth.homeunix.net</email>">
<!ENTITY _aut_Init    "<authorinitials>P.P.</authorinitials>">

<!ENTITY _affiliat    "<affiliation><orgname>Corto E.T.F., K&amp;M</orgname><address>Sainte-Clotilde, Ile de la Réunion</address></affiliation>">
<!ENTITY _holder      "<holder>Pascal PICARD, <emphasis>pascal@seth.homeunix.net</emphasis></holder>"> 

]>

<article class="techreport" lang="fr" revisionflag="changed">

  <articleinfo>    
    <releaseinfo>$Id: C-bash.xml,v 1.2.1.2 2005/05/14 06:10:47 pascal Exp $</releaseinfo>

    <author>
      &_aut_Pre;
      &_aut_Nom;
      &_affiliat;
    </author>
    
    <date>Last Updated: $Date: 2005/05/14 06:10:47 $</date> 
    &_aut_Init;
    
    <title>GNU/Bash</title>
    
    <copyright>
      <year>2002-2005, 2006</year>
      &_holder;
    </copyright>

    <legalnotice>
<para>
Permission to use, copy, modify, and distribute this documentation for any purpose with or without fee is here by granted, provided that the above copyright notice and this permission notice appear in all copies.
</para>        

<para>
THE DOCUMENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS DOCUMENTATION INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS DOCUMENTATION.
</para>      
    </legalnotice>
    
    <keywordset>
      <keyword>interprète de commande, shell, bash, completion, historique</keyword>
    </keywordset>
  </articleinfo>
  
  <abstract>
    <para>Le &shell; est d'abord l'interpréteur de commande d'un système &unix; mais c'est aussi un quasi langage de programmation interpreté autorisant la récursivité.
</para> 
    <para> Historiquement le premier &shell; du système &unix; est le <application>Bourne-Shell</application> (<command>sh</command>). Ce &shell; n'a cessé d'être amélioré et l'université de Berkeley qui a beaucoup contribué à la branche <emphasis><abbrev>BSD</abbrev></emphasis> d'&unix; a développé le <acronym>C-Shell</acronym>, un successeur de <command>sh</command> munit de fonctionnalités étendues par rapport à son ancêtre. 
&fshell; est un shell compatible <command>sh</command>, développé dans le cadre du projet GNU. C'est une amélioration de <command>csh</command> et <command>ksh</command>, tant dans l'utilisation interactive qu'au niveau de la programmation. Il se conforme au standard <emphasis>IEEE POSIX P1003.2/ISO 9945.2</emphasis> et c'est le shell par défaut des systèmes &glinux;.</para> 
    
    <para>Me joindre : &_aut_eMail; </para>
  </abstract>

  




<!-- 1e PARTIE -->

  <sect1>
    <title>Principes de fonctionnement de <command>&fshell;</command></title>    
    <sect2>      
      <title>Rôle d'un &shell; </title>
      <para>
Le &shell; est un interpréteur de commande en ligne. Chaque entrée sur un terminal est analysée et décomposée en terme d'instructions à exécuter. Ces instructions peuvent impliquer des commandes internes que le &shell; connaît et est en mesure d'exécuter directement, ou bien d'autres commandes déclenchant des programmes que le &shell; va tenter de localiser et de lancer. Le &shell; dispose d'instructions (structures de contrôle, ...) et de variables qui le rend, en partie, comparable à un langage de programmation, de sorte que l'on peut écrire des <foreignphrase>shell scripts</foreignphrase>, littérallement de petits ou moyens programmes rédigé en &shell;. 
      </para>

      <para>Un interpréteur &shell; exécutent trois types de commandes : </para>
      <orderedlist numeration="lowerroman" spacing="compact">
	<listitem><para>Les <emphasis>commandes internes</emphasis> [<foreignphrase>built-in commands</foreignphrase>], comme par exemple : <command>cd</command>, <command>pwd</command>, <command>umask</command> ... ou bien encore les éléments algorithmiques tels <command>if .. then .. else .. fi</command>, <command>for ...</command> ...</para></listitem>
	<listitem><para>Les <emphasis>commandes externes</emphasis> indépendantes du &shell; et localisées dans les répertoires, comme par exemple : <command>ls</command> (<filename>/bin/ls</filename>), <command>find</command> (<filename>/usr/bin/find</filename>) ... Ces commandes nécessitent la création d'un nouveau &shell; pour leur exécution contrairement à celles relevant de la première catégorie.</para></listitem>
	<listitem><para>Les commandes définies par un <command>alias</command> ou par une <command>fonction</command>.</para></listitem>
      </orderedlist>
    </sect2>
    
    <sect2>
      <title>Caractéristiques de <command>&fshell;</command></title>
      <para>
	  <itemizedlist>
	  <listitem><para>il possède un mécanisme d'historisation, de rappel et d'éditions des commandes ; </para></listitem>
	  <listitem><para>il permet le contrôle des processus/jobs (suspension), reprise asynchrone (<foreignphrase>background</foreignphrase>) ou interactive (<foreignphrase>foreground</foreignphrase>)) ; </para></listitem>
	  <listitem><para>il permet de traiter les tableaux de caractères ;</para></listitem>
	  <listitem><para>il permet de définir des fonctions et des variables locales aux fonctions ;</para></listitem>
	  <listitem><para>il gère l'arithmétique des entiers dans les bases 2 à 64 ;</para></listitem>
	  <listitem><para>il possède un mécanisme de <foreignphrase>completion</foreignphrase>. </para></listitem>
	</itemizedlist>
</para>
    </sect2>
    
    <sect2>
      <title>Fichiers de configuration de <command>&fshell;</command></title>

    <para>Lors du <foreignphrase>login</foreignphrase> de connexion, <command>&fshell;</command> exécute les instructions contenues dans le  fichier <filename>/etc/profile</filename> puis celles du fichier <filename>~/bash_profile</filename> s'il existe et sinon <filename>~/.bash_login</filename> s'il existe (et sinon <filename>~/.profile</filename>). Les scripts précédent peuvent éventuellement activer l'exécution de <filename>~/.bashrc</filename>, lequel peut à son tour lancer <filename>/etc/bashrc</filename>.
La signification du caractère <command>~</command> est donnée en <xref linkend="metacar"/>. Lors de la fin de session (<foreignphrase>logout</foreignphrase>) <command>&fshell;</command> exécutent les commandes du fichier <filename>~/bash_logout</filename>.</para>

      <para>Un sous-&shell;, ne lit que le fichier <filename>~/.bashrc</filename> à son démarrage et rien à sa terminaison.</para>

      <para>De ce qui précède, on déduit que les commandes à exécuter une seule fois pendant une session sont à placer dans le fichier <filename>~/.bash_profile</filename> (typiquement les variables d'environnement), tandis que les autres sont à placer dans le fichier <filename>~/.bashrc</filename>. </para>


      <para> Le fichier <filename>~/.bash_profile</filename> contient essentiellement la définition des variables d'environnement.</para>

<para>
<example>
	  <title> fichier <filename>~/.bash_profile</filename> </title>
<programlisting width="80">
<![CDATA[
# ~/.bash_profile: executed by bash(1) for login shells.                        
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

umask 0077

export EDITOR=emacs
export LANG=fr_FR@euro
export LC_CTYPE=fr_FR.ISO8859-15
export PAGER=less

# include .bashrc if it exists
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

# set PATH so it includes user's private bin if it exists
if [ -d ~/bin ] ; then
    PATH=~/bin:"${PATH}"
fi

# do the same with MANPATH
#if [ -d ~/man ]; then
#    MANPATH=~/man:"${MANPATH}"
#fi
]]>
</programlisting>
	</example>
</para>




      <para>Le fichier <filename> ~/.bashrc</filename> contient typiquement :
<itemizedlist>
	  <listitem><para>la définition des alias ; </para></listitem>
	  <listitem><para>la définition des paramètres de fonctionnement ;</para></listitem>
	  <listitem><para>l'initialisation des variables.</para></listitem>
	</itemizedlist>
</para>

      <para>
<example>
	  <title>fichier <filename> ~/.bashrc</filename> </title>
<programlisting width="80">
<![CDATA[
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)      
# for examples

# If running interactively, then:
if [ "$PS1" ]; then

    # don't put duplicate lines in the history. See bash(1) for more options
    # export HISTCONTROL=ignoredups

    # enable color support of ls and also add handy aliases
    eval `dircolors -b`
    alias ls='/bin/ls --color=auto'
    #alias dir='ls --color=auto --format=vertical'
    #alias vdir='ls --color=auto --format=long'

    # some more ls aliases
    alias ll='ls -l'
    alias la='ls -A'
    alias l='ls -CF'
    alias rm='/bin/rm -i'

    # set a fancy prompt
    PS1='\u@\h:\w\$ '

    # If this is an xterm set the title to user@host:dir
    #case $TERM in
    #xterm*)
    #    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
    #    ;;
    #*)
    #    ;;
    #esac

    # enable programmable completion features (you don't need to enable
    # this, if it's already enabled in /etc/bash.bashrc).
    #if [ -f /etc/bash_completion ]; then
    #  . /etc/bash_completion
    #fi

    /usr/bin/X11/xrdb -load ~/.Xdefaults >& /dev/null
fi
]]>
</programlisting>
	</example>
</para>

      

 <para> Le fichier <filename> ~/.bash_logout </filename> contient essentiellement des commandes de suppression de fichiers inutiles, exécutées typiquement à la déconnexion.</para>
     
      <para>
<example>
	  <title> fichier <filename> ~/.bash_logout</filename> </title>
<programlisting width="80">
<![CDATA[
# ~/.bash_logout

echo -n "clean up before logout ..."
find $HOME \( -type f \
              \( -name a.out -o -name "*.bak" -o -name core  -o \
                 -name "#*#" -o -name "#.*#"  -o -name "*.o" -o \
                 -name "*~"  -o -name ".*~" \) -exec /bin/rm -f {} \; > /dev/nul
l \)
echo "... done" 
echo "last connexion at [`date +%Y-%m-%d` a `date +%H:%M:%S`] pour [`logname`] s
ur [`tty`]" > ~/.deconnex
]]>
</programlisting>
	</example>
    </para>
      <qandaset defaultlabel="qanda">
	<qandaentry>

	  <question>
	    <para>Quel est le rôle de la commande <command>find</command> dans le contexte du listing précédent (<filename>~/.bash_logout</filename>) ?</para>
	  </question>

	  <answer>
	    <para/>
	  </answer>

	</qandaentry>
      </qandaset>


      <para>Il est possible à tout moment et notamment après une modification de réexécuter les fichiers au moyen de la commande <command>source</command> (l'exécution se fait dans le contexte du &shell; courant, &ie; modification de l'environnement courant).
<programlisting width="80">
$ source ~/.bash_profile                                                        
$ source ~/.bashrc
</programlisting>

</para>

  </sect2>


    <sect2 id="envvar">
      <title> Variables d'environnement</title>
      <para>On parle de <emphasis>variables d'environnement</emphasis> car elles sont <quote>automatiquement</quote> transmises à tous les processus fils du &shell;, &ie; tous les processus lancés par ce &shell;.</para> 
      <para>
Les variables qui suivent ont un sens particulier pour le &shell; (&fshell;), elles sont utilisées par certaines commandes du &shell; ou du système. </para>

      <para>
          <table> <!-- orient='land' pgwide='0'> -->
	  <title> Variables d'environnement </title>
	  <!-- one of (graphic mediaobject tgroup) -->
	  <tgroup cols="2" align='left'>
	     <colspec colnum="1" colname="c1" colwidth="1*+1"/>
             <colspec colnum="2" colname="c2" colwidth="3*+1"/>

	    <thead valign='middle'>
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'> Variable d'environnement </entry>
		<entry align='center'> Sémantique </entry>
	      </row>
	    </thead>

	    <tbody valign='middle'>
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>BASH</varname></entry>
		<entry>Donne le chemin absolu du shell (typiquement <filename>/bin/bash</filename>).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>BASH_VERSION</varname></entry>
		<entry> Donne la version du shell (ici <emphasis>2.05b.0(1)-release</emphasis>).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>CDPATH</varname></entry>
		<entry>Liste des répertoires explorés par la commande <command>cd</command>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>EUID</varname></entry>
		<entry>UID (identifiant) effectif de l'utilisateur courant.</entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'> <varname>FIGNORE</varname> </entry>
		<entry>Liste de suffixes de fichiers qui ne doivent pas apparaître dans l'expansion. (typiquement <command>*~:*.o:*.bak</command>) </entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'> <varname>HISTCMD</varname></entry>
		<entry> Numéro de la commande courante dans l'historique.</entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HISTCONTROL</varname></entry>
		<entry>Peut prendre trois valeurs : <quote><emphasis>ignoredups</emphasis></quote>, <quote><emphasis>ignorespace</emphasis></quote>, <quote><emphasis>ignoreboth</emphasis></quote> de sémantique respective suivante : la ligne courante n'est pas rajoutée à l'historique si elle est identique à la précédente, une ligne commençant par un blanc n'est pas ajoutée à l'historique, enfin la dernière combine les deux précédentes.</entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HISTFILE</varname></entry>
		<entry>Le fichier historique (typiquement <filename>~/.bash_history</filename>).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HISTFILESIZE</varname></entry>
		<entry>Nombre de lignes maximum de l'historique (par défaut 500).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HISTSIZE</varname></entry>
		<entry>Nombre de commandes mémorisées par la commande <command>history</command> (par défaut 500).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HOSTNAME</varname></entry>
		<entry>Nom (court) de la machine. </entry>
	      </row>

	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HOSTTYPE</varname></entry>
		<entry>Architecture de la machine (pour un PC i386). </entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>HOME</varname></entry>
		<entry>Désigne le répertoire de localisation de celui qui invoque la commande. L'expansion de nom de fichier <command>~</command> se réfère à cette variable.</entry>
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>IFS</varname></entry>
		<entry>(<foreignphrase>Internal Field Separator</foreignphrase>) Contient le/les séparateur(s) de champs, par défaut <quote>&lt;space&gt;&lt;tab&gt;&lt;newline&gt;</quote>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>IGNOREEOF</varname></entry>
		<entry>Contrôle l'action du shell interactif sur réception du caractère EOF. Si cette variable est positionnée (numériquement), elle correspond au nombre consécutif de caractères EOF à taper sur la ligne courante pour sortir de &fshell;. Sa valeur par défaut est de 10 si la variable existe, sinon elle signifie la fin d'une entrée pour le shell.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>MAIL</varname></entry>
		<entry>Indique le fichier dans lequel le &shell;  contrôle l'arrivée de nouveaux messages.</entry>		      
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>MAILCHECK</varname></entry>
		<entry>Définit la fréquence de vérification d'arrivée de nouveaux couriers (par défaut 60s, &ie; une vérification toutes les minutes).</entry>		      	      </row>
	      
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'> <varname>PATH</varname> </entry>
		<entry>Définit l'ensemble des chemins dans lesquels le &shell;  recherche les commandes externes à exécuter.</entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'> <varname>PPID</varname> </entry>
		<entry>PID (<foreignphrase>Process IDentifier</foreignphrase>) père du processus courant.</entry>
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>PS1</varname></entry>
		<entry>Définit l'invite de commandes en mode interactif (par défaut $).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>PS2</varname></entry>
		<entry>Définit l'invite de commandes secondaire en mode interactif (par défaut >).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>PS3</varname></entry>
		<entry>Définit l'invite de la structure de boucle <command>select</command> (par défaut #?).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>PS4</varname></entry>
		<entry>Définit l'invite de trace (par défaut +).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>PWD</varname></entry>
		<entry>Chemin absolu du répertoire courant.</entry>
	      </row>


	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>RANDOM</varname></entry>
		<entry>A chaque appel à cette variable un entier dans l'intervalle [0..32767] est aléatoirement généré.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>SECONDS</varname></entry>
		<entry>Temps écoulé en secondes depuis le lancement du shell courant.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left'><varname>SHLVL</varname></entry>
		<entry>Nombre d'instance(s) de shell lancé(s).</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='left' ><varname>UID</varname></entry>
		<entry>Idenfifiant de l'utilisateur courant.</entry>
	      </row>

	      <row>
		<entry align='left'> <varname>NO_CLOBBER</varname> </entry>
		<entry> Modifie la sémantique des commandes de redirections <command>&gt;</command> et <command>&gt;&gt;</command> permettant ainsi d'éviter un effacement accidentel. L'utilisation de <command>&gt;</command> renvoit une erreur si le fichier existe. Quand à <command>&gt;&gt;</command>, elle se réfère uniquement aux fichiers existants.</entry>
	      </row>

	    </tbody>
	  </tgroup>
	</table>
</para>
    </sect2>

    <sect2 id="metacar">
      <title>Métacaractères et autres caractères spéciaux du &shell;</title>
      <para>Les métacaractères jouent le rôle de classe de représentation des fichiers dans le contexte du répertoire courant si rien n'est précisé ou bien dans celui du répertoire explicitement nommé.</para>
      <itemizedlist>
	<listitem>     
	  <para> Le caractère <command>~</command> placé en première position désigne le répertoire personnel de l'utilisateur courant : </para>
	  <informalexample>
<para>
<programlisting width="80">
<![CDATA[
$ echo ~                                                                        
/home/pascal

$ ls -l ~/documentation
total 3
drwx------  6 pascal  gnu  512 Mar 14 14:43 LaTeX
drwx------  4 pascal  gnu  512 Mar 28 16:06 docbook
drwx------  2 pascal  gnu  512 Mar 20 22:20 docbook-slides
]]>
</programlisting>
</para>
	   </informalexample>
	</listitem>

	<listitem>     
	  <para> Le caractère <command>*</command> est substituable par n'importe quelle combinaison de 0 ou plusieurs caractères.</para>
	  <para> Exemple : Lister l'ensemble des fichiers commençant par le motif <filename>C-csh_n_tcsh</filename> du répertoire courant : </para>
	  <para>

<programlisting width="80">
<![CDATA[
$ ls C-csh_n_tcsh*                                                              
C-csh_n_tcsh.fo  C-csh_n_tcsh.pdf C-csh_n_tcsh.ps  C-csh_n_tcsh.xml  
]]>          
</programlisting>
          </para>

	  <informalexample>
	  <para> Exemple : Lister les fichiers (non cachés) du répertoires courant :</para>
<para>
<programlisting width="80">
<![CDATA[
$ echo *                                                                        
C-csh_n_tcsh.fo C-csh_n_tcsh.pdf C-csh_n_tcsh.ps C-csh_n_tcsh.xml Makefile      
_mystyle.css _mystyle.xsl html images my_print.dsl release test.sh test.tgz
]]> 
</programlisting>
</para>
	  </informalexample>

      <warning><para> Les fichiers commençant par le caractère <command>.</command> ou fichiers cachés d'&unix; [<foreignphrase>dot files</foreignphrase>] ne peuvent être remplacés par aucun caractère, &ie; le caractère <quote><command>*</command></quote> est inopérant.</para></warning>
	
	</listitem>

	<listitem> 
	  <para> Le caractère <command>?</command> est substituable par un unique caractère quelconque.</para>
	  <informalexample>
	  <para> Exemple : Lister les fichiers commençant par le motif <filename>C-csh_n_tcsh</filename> et dont le suffixe est réduit à deux caractères :</para>

<programlisting width="80">
<![CDATA[
$ > echo C-csh_n_tcsh.??                                                        
C-csh_n_tcsh.fo C-csh_n_tcsh.ps
]]>                                              
</programlisting>

	</informalexample>
	</listitem>

	<listitem> 
	  <para> Les caractères <command>[]</command> permettent une substitution par un caractère parmi l'ensemble dénoté par les crochets.</para>

	  <informalexample>

	    <para> Exemple : Lister les fichiers cachés du répertoire <filename>$HOME</filename> de l'utilisateur courant, dont le second caractère est compris entre 'a' et 'e' :

<programlisting width="80">
<![CDATA[
$ ls -d ~/.[a-e]*                                                               
/home/pascal/.acrobat        /home/pascal/.cshrc          /home/pascal/.emacs.d
/home/pascal/.acrorc         /home/pascal/.cvsrc          /home/pascal/.esd
/home/pascal/.adobe          /home/pascal/.deconnex       /home/pascal/.esd_auth
/home/pascal/.autosave       /home/pascal/.dia            /home/pascal/.exit.log
/home/pascal/.bash_history   /home/pascal/.emacs
]]>
</programlisting>
</para>	
	  </informalexample>

	  <informalexample>
	    <para> Autre exemple, utilisation de la négation, marquée par le caractère <command>^</command> : lister les fichiers cachés du répertoire <filename>$HOME</filename> de l'utilisateur courant, dont le second caractère n'est ni '.',  ni 'a', ni 'b', ni 'c', ni 'd' ni 'e' (le premier étant un '.') : 

<programlisting width="80">
<![CDATA[
$ ls -d ~/.[^.a-e]*                                                             
/home/pascal/.fetchmail.pid                /home/pascal/.profile.rc             
/home/pascal/.fetchmailrc                  /home/pascal/.ressources
/home/pascal/.fonts.cache-1                /home/pascal/.rhosts
/home/pascal/.fr                           /home/pascal/.shadow_todo
/home/pascal/.gkrellm                      /home/pascal/.shrc
/home/pascal/.gnupg                        /home/pascal/.sversionrc
/home/pascal/.gv                           /home/pascal/.tcsh_comp
/home/pascal/.history                      /home/pascal/.themeinstaller
/home/pascal/.ispell_francais              /home/pascal/.user60.rdb
/home/pascal/.login                        /home/pascal/.weblink
/home/pascal/.logout                       /home/pascal/.xemacs
/home/pascal/.mail_aliases                 /home/pascal/.xfigrc
/home/pascal/.mailcap                      /home/pascal/.xinitrc
/home/pascal/.mailrc                       /home/pascal/.xmms
/home/pascal/.mgprc                        /home/pascal/.xsession
/home/pascal/.mime.types                   /home/pascal/.xsession-errors
/home/pascal/.mozilla                      /home/pascal/.xwm.msgs
/home/pascal/.mutt
]]>
</programlisting>
</para>
	  </informalexample>

	</listitem>

	<listitem>
	  <para>Les caractères <command>{ }</command> permettent la substitution par un mot de l'énumération dénotée par les accolades.</para>

<informalexample>
	  <para> Exemple : Lister les fichiers se terminant par les suffixes .xml et .pdf et .fo :

<programlisting width="80">
<![CDATA[
$ ls C-csh_n_tcsh.{xml,pdf,fo}                                                  
C-csh_n_tcsh.fo  C-csh_n_tcsh.pdf C-csh_n_tcsh.xml                              
]]>
</programlisting>
</para>

	</informalexample>
	</listitem>

	<listitem><para>Quelques autres caractères spéciaux </para>
	  <table frame="all" orient="port">
	    <title>Autres caractères spéciaux du &shell;</title>
	    <!-- one of (graphic mediaobject tgroup) -->
	    <tgroup cols="2" align='left'>
               <colspec colnum="1" colname="c1" colwidth="1*+1"/>
               <colspec colnum="2" colname="c2" colwidth="3*+1"/>

	      <thead>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'> Caractère </entry>
		  <entry align='center'> Sémantique </entry>
		</row>
	      </thead>
	      
	      <tbody>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>;</command></entry>
		  <entry>Séparateur de commande, &ie; opérateur de séquentialité.</entry>
		</row>
		
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>&amp;</command></entry>
		  <entry>Séparateur de commande qui place la commande qui le précède en arrière-plan, &ie; en exécution asynchrone.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>\</command></entry>
		  <entry>Quote le caractère qui le suit et notamment pour les caractères spéciaux, inhibe leur sémantique particulière.</entry>
		</row>
		
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>$</command></entry>
		  <entry>Accède au contenu de la variable qui le suit immédiatement.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>'</command></entry>
		  <entry>[<foreignphrase>quote</foreignphrase>] Quote le texte qui le suit jusqu'au <command>'</command> fermant.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>`</command></entry>
		  <entry>[<foreignphrase>backquote</foreignphrase>] Considère le texte quoté comme une commande et la remplace par le résultat de son évaluation.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>"</command></entry>
		  <entry>[<foreignphrase>double quote</foreignphrase>] Quote le texte qui le suit en interpolant les éventuelles variables qu'il contient.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>!</command></entry>
		  <entry>Substitution dans l'historique.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>|</command></entry>
		  <entry>Tube [<foreignphrase>pipe</foreignphrase>].</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>&gt;</command> et <command>&gt;&gt;</command></entry>
		  <entry>Redirection de la sortie standard.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>&lt;</command> et <command>&lt;&lt;</command></entry>
		  <entry>Redirection de l'entrée standard.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>#</command></entry>
		  <entry>Marque le début d'un commentaire, &ie; pas d'expansion.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>&amp;&amp;</command></entry>
		  <entry>Et [<foreignphrase>And</foreignphrase>] logique.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry align='center'><command>||</command></entry>
		  <entry>Ou [<foreignphrase>Or</foreignphrase>] logique.</entry>
		</row>


	      </tbody>

	    </tgroup>
	  </table>
</listitem>

      </itemizedlist>
    </sect2>
</sect1>






<!-- 2e PARTIE -->
  <sect1>
    <title>Les commandes internes</title>    

    <sect2>
      <title><command>.</command> et <command>source</command> </title>
      <para>Ces commandes synonymes exécutent le fichier (et ces éventuels arguments) qui leur est passé en argument dans le shell courant (&ie; par de <command>fork</command>).
</para>
      <para>
<programlisting width="80">
<![CDATA[
$ source ~/.bash_profile                                                        

 ou

$ . ~/.bash_profile
]]>
</programlisting>
</para>
    </sect2>

    <sect2 id="export">
      <title><command>export</command> et <command>unset</command></title>
      <para>La commande <command>export</command> permet d'initialiser une variable d'environnement, &ie; une variable qui sera transmise à tous les processus fils du &shell;.</para>      
       <para>
<programlisting width="80">
<![CDATA[
$ export OSTYPE=Linux                                                           
$ export CPUTYPE=K7
$ export PAGER=less
$ echo $OSTYPE $CPUTYPE $PAGER
Linux K7 less
]]>
</programlisting>
    </para>
      <para>La commande <command>unset</command> permet de supprimer le contenu d'une variable (d'environnement ou autre).</para>
       <para>
<programlisting width="80">
<![CDATA[
$ echo $OSTYPE                                                                  
Linux
$ unset OSTYPE    # la variable n'est pas préfixée par le symbole $             
$ echo $OSTYPE

]]>
</programlisting>
</para>
    </sect2>


    <sect2>      
      <title> <command>alias</command>/<command>unalias</command></title>
      <para>Ce mécanisme permet de définir ou de redéfinir une commande. Exemple :

<programlisting width="80">
<![CDATA[
$ alias la='/bin/ls -a --color=auto'   # definition de l'alias la               
$ alias rm='/bin/rm -i'                # definition de l'alias rm
$ alias                                # afficher les alias courants
$ alias la='/bin/ls -a --color=auto'
$ alias rm='/bin/rm -i'
]]>
</programlisting>
      </para>   
      
      <para> En général, on place ces <command>alias</command> dans le fichier <filename>~/.bashrc</filename>. Si on veut supprimer un <command>alias</command> on utilise la commande <command>unalias</command> comme suit :
      
<programlisting width="80">
<![CDATA[
$ unalias rm                                                                    
$ alias                                # afficher les alias courants
$ alias la='/bin/ls -a --color=auto'
]]>
</programlisting>
      </para>
      
      <para>Pour ré-accéder à la commande masquée par son alias, comme dans l'exemple précédent où nous avons surchargé la commande classique <command>rm</command>, il suffit de : 
      <itemizedlist>
	  <listitem><para>Soit utiliser la commande par son nom absolu : <command>/bin/rm</command>.</para></listitem>
	  <listitem><para>Soit faire précéder la commande du caractère <foreignphrase>backslash</foreignphrase> (\), on tape donc toujours dans le cadre de l'exemple précédent : <command>\rm</command></para></listitem>
	</itemizedlist>
        </para>
    </sect2>

    <sect2>
      <title><command>umask</command></title>
      <para>Cette commande permet de spécifier (si elle est suivie d'un argument valide) ou d'afficher la valeur du masque de création des objets &ie; des fichiers.

<programlisting width="80">
<![CDATA[
$ umask  # affiche la valeur telle que prédéfinie dans ~/.bash_profile          
0077
$ umask 0027
$ umask
0027
]]>
</programlisting>
</para>
    </sect2>

        
    <sect2>      
      <title>Historique</title>
      <para>Ce mécanisme a pour rôle de mémoriser les <varname>n</varname> dernières commandes entrées, ce nombre étant un paramètre réglable (&cf; variables d'environnements <varname>HISTSIZE</varname> et <varname>HISTFILESIZE</varname>). Cela permet de visualiser, d'éditer et/ou exécuter à nouveau les commandes mémorisées. 

<programlisting width="80">
<![CDATA[
$ history 10   # liste les 10 dernières commandes mémo. avec leur numéro d'ordre
   93  ulimit -aS
   94  ulimit -Sn 2048
   95  man bash
   96  history
   97  echo $HISTSIZE
   98  history 10
   99  ls -la
  100  cd tmp
  101  ll
  102  history 10
                                                   
]]>
</programlisting>
</para>

<para>Pour relancer une commande, il suffit de l'appeler par son numéro (relativement à l'historique) en la préfixant par le caractère !. Par exemple, si on veut relancer la commande 99, il suffit de faire :

<programlisting width="80">
<![CDATA[
$ !99                                                                           
ls -la
total 8
drwx------    2 pascal   pascal       4096 Aug 11 19:15 .
drwxr-xr-x    4 pascal   pascal       4096 Aug 11 19:15 ..
]]>
</programlisting>

</para>
      <para>
         <table>
	  <title>Quelques commandes de manipulation de l'historique</title>
	  <!-- one of (graphic mediaobject tgroup) -->
	  <tgroup cols="2" align='left'>
              <colspec colnum="1" colname="c1" colwidth="1*+1"/>
              <colspec colnum="2" colname="c2" colwidth="3*+1"/>

	    <thead>
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'> Expression </entry>
		<entry align='center'> Sémantique </entry>
	      </row>
	    </thead>
	    <tbody>
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!!</command></entry>
		<entry>Répéter la dernière commande.</entry>
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!</command><emphasis>n</emphasis></entry>
		<entry>Répéter la commande numéro <emphasis>n</emphasis>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!-</command><emphasis>n</emphasis></entry>
		<entry>Répéter la <emphasis>n<superscript>ième</superscript></emphasis> précédent la dernière de l'historique, &ie; !-2 : avant dernière commande.</entry>
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!</command><emphasis>texte</emphasis></entry>
		<entry>Répéter la dernière commande commençant par <emphasis>texte</emphasis>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!?</command><emphasis>texte</emphasis></entry>
		<entry>Répéter la dernière commande contenant <emphasis>texte</emphasis>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!:</command><emphasis>n</emphasis></entry>
		<entry>Répéter le <emphasis>n<superscript>ième</superscript></emphasis> mot de la dernière commande.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!$</command></entry>
		<entry>Répéter le dernier mot de la dernière commande.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!*</command></entry>
		<entry>Répéter tous les arguments de la dernière commande.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>^</command><emphasis>old</emphasis><command>^</command><emphasis>new</emphasis></entry>
		<entry>Répéter la dernière commande en commençant par remplacer la première occurence de <emphasis>old</emphasis> par <emphasis>new</emphasis>.</entry>
	      </row>

	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!</command><emphasis>n</emphasis><command>:s^</command><emphasis>old</emphasis><command>^</command><emphasis>new</emphasis></entry>
		<entry>Répéter la <emphasis>n</emphasis><superscript>ième</superscript> commande en commençant par remplacer la première occurence de <emphasis>old</emphasis> par <emphasis>new</emphasis>.</entry>
	      </row>
	      
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align='center'><command>!</command><emphasis>n</emphasis><command>:gs^</command><emphasis>old</emphasis><command>^</command><emphasis>new</emphasis></entry>
	<entry>Répéter la <emphasis>n</emphasis><superscript>ième</superscript> commande en commençant par remplacer toutes les occurences 
      de <emphasis>old</emphasis> par <emphasis>new</emphasis> (substitution globale).</entry>
	      </row>

	    </tbody>
	  </tgroup>
	</table>
</para>      
    </sect2>




    <sect2>
      <title><foreignphrase>Completion</foreignphrase></title>
      
      <para>Ce mécanisme permet, selon le contexte, de compléter les noms de fichiers, d'utilisateurs, de machines ou de variables à partir de la saisie d'un préfixe suivi de la frappe du caractère <quote>TAB</quote>. <emphasis role='bold'>Le contexte par défaut étant celui de fichiers</emphasis>.</para>

      <para>Supposons, par exemple, que le contenu du répertoire courant soit le suivant :</para>
<para>
<programlisting width="80">
<![CDATA[
_merge.pl       check.pl             fdate.sh             mytest.pl
_pidof.pl       crlf.pl              gen-meta-index.pl    replace_header_html.pl
_split.pl       extract.pl           idle.pl              rotate.pl
_test.pl        extract_piste.sh     logfile-1.2.pl       rsync.pl
bidir.pl        fcomp.sh             mylock.sh
]]>
</programlisting> 
</para>
<para>Alors la séquence suivante :
<computeroutput>
<![CDATA[
$ ls l<TAB>
]]>
</computeroutput>

est résolue en (seule correspondance possible) :
<computeroutput>
$ ls logfile-1.2.pl
</computeroutput>
</para>

<para>Tandis que la séquence ci-contre :
<computeroutput>
<![CDATA[
$ ls ext<TAB>                                                                 
]]>
</computeroutput>

est résolue partiellement en :
<computeroutput>
<![CDATA[
$ ls extract 
]]>
</computeroutput>
 suivie de l'émission d'un bip qui signale que cette expansion est incomplète puisque deux fichiers correspondent au préfixe saisi. La commande précédente suivie à nouveau de la séquence <command>&lt;TAB&gt;</command> permet d'obtenir l'ensemble des réponses potentielles :</para>

<para>
<programlisting width="80">
<![CDATA[
$ ls extract<TAB><TAB>                              
extract.pl*       extract_piste.sh*                                             
$ ls extract
]]>
</programlisting>
La saisie d'un seul caractère supplémentaire permet dans ce dernier cas de lever l'ambiguïté.  
</para>

      <para>Enfin, il est possible de limiter les correspondances potentielles à la <foreignphrase>completion</foreignphrase> en positionnant la variable <command>FIGNORE</command>. Dans l'exemple suivant, on exclut des correspondances possibles les fichiers suffixés en <command>.o</command>, <command>.out</command> et <command>*~</command>.</para>
<para>
<programlisting width="80">
<![CDATA[
$ export FIGNORE=".o:.out:*~"                                                   
]]>
</programlisting>
    </para>

<formalpara>
<title>Contexte utilisateur :</title>
<para>le mécanisme de <foreignphrase>completion</foreignphrase> peut être utilisé pour compléter les noms d'utilisateurs. Il faut utiliser le préfixe <command>~</command> (il change le contexte de la <foreignphrase>completion</foreignphrase>) :  
<programlisting width="80">
<![CDATA[
$ cd ~pa<TAB>                                                                   
$ cd ~pascal
]]>
</programlisting>
</para>
</formalpara>

<formalpara>
<title>Contexte de variables :</title>
<para>le mécanisme de <foreignphrase>completion</foreignphrase> peut être utilisé pour compléter les noms de variables. Il faut utiliser le préfixe <command>$</command> (il change le contexte de la <foreignphrase>completion</foreignphrase>) :
<programlisting width="80">
<![CDATA[
$ varia_1=10                                                                    
$ echo $var<TAB>
$ echo $varia_1 <ENTREE>
10
]]>
</programlisting>
</para>
</formalpara>

<formalpara>
<title>Contexte de nom d'hôte :</title>
<para>le mécanisme de <foreignphrase>completion</foreignphrase> peut être utilisé pour compléter les noms de machines. Il faut utiliser le préfixe <command>@</command> (il change le contexte de la <foreignphrase>completion</foreignphrase>) :
<programlisting width="80">
<![CDATA[
$ @tu<TAB>                                                                      
$ @tux<TAB>
$ @tux.corto.home 
]]>
</programlisting>
</para>
</formalpara>
    </sect2> 


<sect2>      
      <title>Navigation dans les répertoires </title>
      <sect3>
	<title>Commandes <command>cd</command></title>            
	<para> Supposons qu'un utilisateur ait souvent besoin de se rendre alternativement dans le répertoire <filename>/home/cvsroot/</filename> et dans son propre répertoire <filename>~/projets</filename>, il peut alors : </para>
	
	<itemizedlist>
	  <listitem><para>pour se rendre en <filename>/home/cvsroot/C-network/</filename>, taper : </para></listitem>
	</itemizedlist>

	<para>
<programlisting width="80">
<![CDATA[
$ cd /home/cvsroot/C-network                                                    
]]>
</programlisting>
</para>

	<itemizedlist>
	  <listitem><para>et pour se rendre en <filename>~/projets</filename>, taper :</para></listitem>
	</itemizedlist> 
	<para>
<programlisting width="80">
<![CDATA[
$ cd ~/projets                                                                  
]]>                                                              
</programlisting>
</para>


      <para>Mais, cet utilisateur peut aussi se simplifier la vie en positionnant la variable <command>cdpath</command>, ainsi :</para>
<para>
<programlisting width="80">
<![CDATA[
$ export CDPATH="/home/cvsroot:~"                                               
]]>
</programlisting>
</para>

	<para> Ainsi, il peut se contenter de :
<itemizedlist>
	    <listitem><para> taper dans le premier cas : </para></listitem>
	  </itemizedlist></para>
<para>
<programlisting width="80">
<![CDATA[
$ cd C-network                                                                  
/home/cvsroot/C-network
]]>
</programlisting>
</para>
    
	<itemizedlist>    
	  <listitem><para>et dans le second :</para></listitem>
	</itemizedlist>
	<para>
<programlisting width="80">
<![CDATA[
$ cd projets                                                                    
~/projets
]]>
</programlisting>
</para>
      
      </sect3>
      

      <sect3>
	<title>Pile de répertoires : <command>pushd</command>, <command>popd</command> et <command>dirs</command></title>
	<para> Une pile est une structure de données qui permet de mémoriser des entrées et dont la stratégie d'accès est de  type <foreignphrase><acronym>LIFO</acronym></foreignphrase> (<foreignphrase>Last In, First Out</foreignphrase>), &ie; on accède uniquement au sommet de la pile. </para>
<para>La pile des répertoires est géré par les trois primitives suivantes : 
<itemizedlist>
	    <listitem><para> La commande <command>pushd</command> permet de changer de répertoire (comme <command>cd</command>), mais l'ancien répertoire est conservé dans la pile (il est empilé).</para>
	    </listitem>
	    
	    <listitem><para> La commande <command>popd</command> permet de changer de répertoire (comme <command>cd</command>), en dépilant le sommet de  la pile.</para>
	    </listitem>
	    
	    <listitem><para> La commande <command>dirs</command> permet d'afficher le contenu de la pile.</para>
	    </listitem>
	  </itemizedlist>
	</para>
	
<para>L'exemple suivant permet d'en comprendre le fonctionnement :
 
<programlisting width="80"> <!-- linenumbering='numbered' width='80'> -->
$ pwd <co id="com.pwd.1" linkends="pwd1" /> 
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/csh                               

$ pushd /usr/local/etc <co id="com.pushd"  linkends="pushd" /> 
/usr/local/etc ~/enseignement/NeoTechIII/V2L-PRAI/csh

$ pwd <co id="com.pwd.2" linkends="pwd2" /> 
/usr/local/etc

$ popd <co id="com.popd"  linkends="popd" /> 
~/enseignement/NeoTechIII/V2L-PRAI/csh

$ pwd <co id="com.pwd.3"  linkends="pwd3" /> 
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/csh

$ pushd /usr/local/etc
/usr/local/etc ~/enseignement/NeoTechIII/V2L-PRAI/csh

$ pwd 
/usr/local/etc

$ dirs -v <co id="com.dirsv"  linkends="dirsv" /> 
0       /usr/local/etc
1       ~/enseignement/NeoTechIII/V2L-PRAI/csh
</programlisting>

<calloutlist>
<callout arearefs="com.pwd.1" id="pwd1">
   <para>Affiche le chemin courant.</para>
</callout>

<callout arearefs="com.pushd" id="pushd">
<para> Se rend dans le répertoire spécifié et l'empile au sommet de la pile.</para>
</callout>

<callout arearefs="com.pwd.2" id="pwd2">
   <para>Affiche le chemin courant.</para>
</callout>

<callout arearefs="com.popd" id="popd">
<para> Dépile le sommet et se rend dans le répertoire indiqué.</para>
</callout>

<callout arearefs="com.pwd.3" id="pwd3">
   <para>Affiche le chemin courant.</para>
</callout>

<callout arearefs="com.dirsv" id="dirsv">
<para> Affiche le contenu de la pile, en commençant par le sommet.</para>
</callout>

<!-- <callout arearefs="com.more" id="more"> -->
<!-- <para> Utilisation de la pile pour lire un fichier situé hors du répertoire courant.</para> -->
<!-- </callout> -->
</calloutlist>
</para>
      </sect3>
    </sect2>



<sect2>      
      <title> Gestion des processus </title>
      <sect3>
	<title>Les processus</title>	
      <para>Un processus est l'instance d'un programme en exécution. C'est une structure de données qui contient du code statique, des données statiques et dynamiques et un environnement d'exécution. Un processus possède un cycle de vie marqué par des états comme l'exécution (<foreignphrase>runnable</foreignphrase>), la suspension, l'attente, le sommeil, l'état zombie... Pour se voir allouer des tranches de temps (<foreignphrase>time slice</foreignphrase>) d'exécution sur le <foreignphrase>CPU</foreignphrase>, un processus doit être dans l'état exécutable.</para> 

      <para>Chaque programme démarré par le <command>shell</command> nécessite la création d'un nouveau processus, on a ainsi une arborescence de processus, puisqu'une nouvelle instance ne possède qu'un seul parent. L'utilitaire <command>ps</command> permet d'obtenir un instantané des processus en cours</para>

<programlisting width="132">
$ > ps 
  PID<co id="com.pid" linkends="pid" />  TTY<co id="com.tt" linkends="tt" />  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIME<co id="com.time" linkends="time" /> CMD<co id="com.command" linkends="command" />
<![CDATA[
  544 pts/0    00:00:00 bash                                                    
 1473 pts/0    00:00:00 emacs
 1479 pts/0    00:00:00 ssh
 1481 pts/0    00:00:00 ps
]]>
</programlisting>

<calloutlist>
<callout arearefs="com.pid" id="pid">
	  <para><foreignphrase>Process IDentifier</foreignphrase>, identifiant (unique) du processus.</para>
</callout>

<callout arearefs="com.tt" id="tt">
	  <para><foreignphrase>TTY device</foreignphrase>, terminal d'exécution.</para>
</callout>

<!-- <callout arearefs="com.stat" id="stat">
	  <para><foreignphrase>STATus</foreignphrase>, état du processus</para>
</callout> -->

<callout arearefs="com.time" id="time">
	  <para><foreignphrase>TIME consumed</foreignphrase>, temps <foreignphrase>CPU</foreignphrase> consommé.</para>
</callout>

<callout arearefs="com.command" id="command">
	  <para>La commande exécutée.</para>
</callout>
</calloutlist>

      <para>Le système identifie chaque processus au moyen d'un entier appelé <foreignphrase>pid</foreignphrase>. Dans l'exemple précédent, la première ligne identifie le processus numéro 544, qui un <command>shell</command> (&fshell;) sur le terminal <command>/dev/pts/0</command>.</para>

	<para> La commande <command>ps l</command> (&cf; exemple suivant) permet d'obtenir plus de détails sur les processus. On y trouve les paramètres suivants : 
<itemizedlist>
	    <listitem><para>l'<foreignphrase>uid</foreignphrase> : propriétaire du processus,</para></listitem>
	    <listitem><para>le <foreignphrase>pid</foreignphrase> : identifiant du processus,</para></listitem> 
	    <listitem><para>le <foreignphrase>ppid</foreignphrase> : identifiant du père du processus,</para></listitem> 
	    <listitem><para>le <foreignphrase>pri</foreignphrase> : &ie; priorité d'ordonnancement,</para></listitem> 
	    <listitem><para>le <foreignphrase>nice</foreignphrase> : priorité assignée par <command>nice</command> ; la modification de cette valeur permet d'influer sur l'algorithme d'ordonnancement [<foreignphrase>scheduling</foreignphrase>],</para></listitem> 
	    <listitem><para>le <foreignphrase>vsz</foreignphrase> : donne la taille de la mémoire virtuelle utilisée (exprimée en kilo-octet),</para></listitem> 
	    <listitem><para>le <foreignphrase>rss</foreignphrase> : taille de la mémoire réelle utilisée (exprimée en kilo-octet).</para></listitem>
	    <listitem><para>le <foreignphrase>wchan</foreignphrase> : le canal d'attente, &ie; une adresse sur une structure de données identifiant la ressource ou l'évènement pour lequel le processus est en attente,</para></listitem> 
	    <listitem><para>le <foreignphrase>state</foreignphrase> : état du processus parmi (R, S, T, Z ...), </para></listitem>
	    <listitem><para>le <foreignphrase>tty</foreignphrase> : le terminal associé au processus, </para></listitem>
	    <listitem><para>le <foreignphrase>time</foreignphrase> : temps <foreignphrase>cpu</foreignphrase> accumulé (utilisateur et système),</para></listitem> 
	    <listitem><para>enfin la commande elle-même.</para></listitem>
	  </itemizedlist>
</para>

<programlisting width="110">
<![CDATA[
$ ps l
F   UID   PID  PPID PRI  NI   VSZ  RSS WCHAN  STAT TTY        TIME COMMAND
0  1000   544   543  11   0  2400 1516 wait4  S    pts/0      0:00 -bash
0  1000  1473   544   9   0  6152 2276 signal T    pts/0      0:00 emacs toto
0  1000  1479   544   9   0  2652 1396 signal T    pts/0      0:00 ssh -v -p 22 pascal@godel                  
0  1000  1489   544  17   0  3280 1412 -      R    pts/0      0:00 ps l
]]>
</programlisting>

	<para> L'invocation d'un programme déclenche un nouveau processus chargé de son exécution et pendant ce temps, le  &shell; (père du processu) est suspendu jusqu'à la terminaison de ce processus. On parle alors d'éxecution interactive (ou en avant-plan [<foreignphrase>foreground</foreignphrase>]). Il est évidement possible d'exécuter un processus de manière asynchrone [<foreignphrase>background</foreignphrase>], &ie; de permettre au &shell; d'exécuter de nouvelles commandes immédiatement. Il suffit pour se faire de postfixer la commande à exécuter de manière asynchrone par le caractère "ampersand" : &amp;. Voici un exemple (noter le numéro du processus : 20713) : 

<programlisting width="80">
<![CDATA[
$ fetchmail &                                                                   
[2] 20713
]]>
</programlisting>
</para>

      <para><command>&fshell;</command> reprend le mécanisme de suspension d'un processus interactif (introduit par <command>csh</command> par la commande <command>^Z</command> (lire <command>&lt;CTRL&gt;-Z</command>). La reprise peut se faire de manière asynchrone (arrière plan) par la commande <command>bg</command> ou de manière interactive (avant plan) avec la commande symétrique <command>fg</command>. </para>

	<para>Pour finir, signalons la commande <command>top</command> qui permet d'avoir des informations en temps réel sur les processus (rafraîchissement toutes les 3 secondes, par défaut sous Debian). En voici un exemple tronqué :
<programlisting width="80">
<![CDATA[
top - 08:35:24 up 1 day, 45 min,  1 user,  load average: 0.05, 0.05, 0.00       
Tasks:  41 total,   2 running,  37 sleeping,   2 stopped,   0 zombie
Cpu(s):   3.6% user,   1.7% system,   0.0% nice,  94.7% idle
Mem:    513024k total,   110736k used,   402288k free,    23804k buffers
Swap:   498004k total,        0k used,   498004k free,    43080k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  Command            
  302 root      18   0  1980 1980 1520 R  3.0  0.4   0:27.77 wdmLogin 
  293 root      12 -10 56732 7088 1700 S  1.3  1.4   0:49.73 XFree86  
 1490 pascal    11   0   932  932  748 R  0.7  0.2   0:00.33 top           
    2 root       9   0     0    0    0 S  0.3  0.0   0:00.65 keventd   
    1 root       8   0   464  464  408 S  0.0  0.1   0:04.90 init  
    3 root      19  19     0    0    0 S  0.0  0.0   0:00.06 ksoftirqd_CPU0  
    4 root       9   0     0    0    0 S  0.0  0.0   0:00.00 kswapd 
    5 root       9   0     0    0    0 S  0.0  0.0   0:00.00 bdflush 
    6 root       9   0     0    0    0 S  0.0  0.0   0:00.09 kupdated 
    7 root       9   0     0    0    0 S  0.0  0.0   0:00.00 i2oevtd
    9 root       9   0     0    0    0 S  0.0  0.0   0:00.62 kjournald
   40 root       9   0     0    0    0 S  0.0  0.0   0:00.00 khubd
   75 root       9   0     0    0    0 S  0.0  0.0   0:00.01 kjournald
   76 root       9   0     0    0    0 S  0.0  0.0   0:01.12 kjournald
   77 root       9   0     0    0    0 S  0.0  0.0   0:00.56 kjournald
   78 root       9   0     0    0    0 S  0.0  0.0   0:00.58 kjournald
   79 root       9   0     0    0    0 S  0.0  0.0   0:00.03 kjournald
   80 root       9   0     0    0    0 S  0.0  0.0   0:00.04 kjournald
   98 root       9   0     0    0    0 S  0.0  0.0   0:00.00 eth0
  164 root       9   0   756  756  644 S  0.0  0.1   0:00.20 syslogd
  167 root       9   0  1240 1240  416 S  0.0  0.2   0:00.52 klogd
  185 root       9   0  1348 1348 1236 S  0.0  0.3   0:00.02 sshd 
  194 root       9   0  2964 2964  684 S  0.0  0.6   0:00.22 xfs 
  253 root       8   0  1380 1376 1008 S  0.0  0.3   0:00.01 bash
  256 root       9   0   372  372  316 S  0.0  0.1   0:00.02 tee
  257 root       9   0   352  352  300 S  0.0  0.1   0:00.01 logger=
  267 daemon     9   0   552  552  480 S  0.0  0.1   0:00.00 atd
  270 root       8   0   660  660  552 S  0.0  0.1   0:00.00 cron
  283 root       9   0  1236 1236 1172 S  0.0  0.2   0:00.21 wdm
  287 root       9   0   444  444  388 S  0.0  0.1   0:00.00 getty
  288 root       9   0   444  444  388 S  0.0  0.1   0:00.01 getty
  289 root       9   0   444  444  388 S  0.0  0.1   0:00.00 getty
  290 root       9   0   444  444  388 S  0.0  0.1   0:00.00 getty
  291 root       9   0   444  444  388 S  0.0  0.1   0:00.00 getty
  292 root       9   0   444  444  388 S  0.0  0.1   0:00.01 getty
  294 root       9   0  1328 1328 1256 S  0.0  0.3   0:00.02 wdm
  541 root       9   0  1924 1924 1776 S  0.0  0.4   0:00.08 sshd
  543 pascal     9   0  2000 2000 1828 S  0.0  0.4   0:01.08 sshd
  544 pascal     9   0  1516 1516 1212 S  0.0  0.3   0:00.25 bash
 1473 pascal     9   0  2276 2276 1504 T  0.0  0.4   0:00.21 emacs
 1479 pascal     9   0  1396 1396 1136 T  0.0  0.3   0:00.14 ssh
]]>
</programlisting>
 </para>

      </sect3>
      
      <sect3>
	<title>Les signaux</title>
	<para>Les signaux sont une forme limitée de communication inter-processus. Ils permettent de prévenir les processus de l'occurence de certains évènements. Il est possible d'envoyer des signaux à des processus interactifs à partir du clavier. La commande suivante permet de connaître les associations clés/signaux :

<programlisting width="80">
<![CDATA[
$ stty -a
speed 38400 baud; rows 53; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
]]>
</programlisting>

Ainsi, la séquence &lt;CTRL&gt;-C (<command>^C</command>)  permet d'envoyer le signal de terminaison (<foreignphrase>SIGINT signal</foreignphrase>), la séquence &lt;CTRL&gt;-\ (<command>^\</command>) permet d'envoyer un autre signal de terminaison (<foreignphrase>SIGQUIT</foreignphrase>), la séquence &lt;CTRL&gt;-Z (<command>^Z</command>) permet d'envoyer le signal de suspension (<foreignphrase>SIGTSTP</foreignphrase>). Par défaut, les deux premiers signaux (SIGINT et SIGQUIT) termine le processus, tandis que le troisième ne fait que suspendre l'éxecution, &ie; elle peut donc être reprise. Ce comportement par défaut peut cependant être redéfini au sein d'un processus. 
</para>
 
	<para>Sur une architecture &glinux; on trouve 62 signaux. La commande, improprement nommée <command>kill</command> (&cf; <command>man 1 kill</command>) permet d'envoyer des signaux à un processus. Sa syntaxe est la suivante : <command>kill &lt;signal&gt; &lt;pus&gt;</command>, où &lt;signal&gt; est le signal envoyé au processus de numéro &lt;pus&gt;</para>

	<para>La liste des signaux délivrables par la commande <command>kill</command> peut être obtenue de la manière suivante : 
<programlisting width="80">
<![CDATA[
$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS      32) SIGRTMIN    33) SIGRTMIN+1
34) SIGRTMIN+2  35) SIGRTMIN+3  36) SIGRTMIN+4  37) SIGRTMIN+5
38) SIGRTMIN+6  39) SIGRTMIN+7  40) SIGRTMIN+8  41) SIGRTMIN+9
42) SIGRTMIN+10 43) SIGRTMIN+11 44) SIGRTMIN+12 45) SIGRTMIN+13                 
46) SIGRTMIN+14 47) SIGRTMIN+15 48) SIGRTMAX-15 49) SIGRTMAX-14
50) SIGRTMAX-13 51) SIGRTMAX-12 52) SIGRTMAX-11 53) SIGRTMAX-10
54) SIGRTMAX-9  55) SIGRTMAX-8  56) SIGRTMAX-7  57) SIGRTMAX-6
58) SIGRTMAX-5  59) SIGRTMAX-4  60) SIGRTMAX-3  61) SIGRTMAX-2
62) SIGRTMAX-1  63) SIGRTMAX 
]]>
</programlisting>

Parmi ces signaux, deux ne peuvent être ni ignorés, ni détournés. Il s'agit du <command>SIGKILL</command> (terminaison) et du <command>SIGSTOP</command> (suspension ou stop)  (à ne pas confondre avec le <command>SIGTSTP</command> vu précédemment).  
</para>

<!-- <para>La commande <command>stop</command> appliquée à un processus asynchrone permet d'en suspendre son exécution.</para> -->


      </sect3>

      <sect3>
	<title>Jobs</title>
	<para>Cette notion inventée par la branche <emphasis>BSD</emphasis> d'&unix; et introduite par <command>csh</command> est désormais disponible sur toutes les distributions &unix; <emphasis>libres</emphasis>.</para>

	<para>Un <foreignphrase>job</foreignphrase> est soit un processus, soit un groupe de processus lancé par le &shell;. Un <foreignphrase>job</foreignphrase> peut être suspendu, redémarré, terminé, executé interactivement ou de manière asynchrone. Le &shell; sait gérer plusieurs <foreignphrase>jobs</foreignphrase> simultanément, toutefois à un instant donné seul un <foreignphrase>job</foreignphrase> peut avoir accès au terminal. Les <foreignphrase>jobs</foreignphrase> sont intéressants dès que les processus qu'ils contrôlent ont une durée de vie de quelques secondes. Analysons la séquence suivante : 


<programlisting width="80">
$ su toor <co id="com.su" linkends="su" /> 
Password:
# id
uid=0(root) gid=0(wheel) groups=0(wheel)
# suspend <co id="com.susp" linkends="susp" /> 

Suspended
$ jobs <co id="com.job1" linkends="job1" />
[1]  - Running                xemacs C-csh_n_tcsh.xml
[2]  + Suspended              su toor
$ du -s -h /usr &amp; <co id="com.async" linkends="async" />
[3] 21136
$ ls3.7G    /usr <co id="com.rep" linkends="rep" />
[3]    Exit 1                 du -s -h /usr <co id="com.exit" linkends="exit" />
$ ls    /usr 
C-csh_n_tcsh.xml Makefile         _mystyle.xsl     images           my_style.xsl
CVS              _mystyle.css     html             my_print.dsl

<!-- $ stty tostop <co id="com.async2" linkends="async2" /> -->
$ du -s -h /usr &amp;

...

$ jobs
[1]    Running                       xemacs C-csh_n_tcsh.xml
[2]  - Suspended                     su toor
[3]  + Suspended (tty output)        du -s -h /usr <co id="com.notif" linkends="notif" />

$ %3 <co id="com.rep2" linkends="rep2" />
du -s -h /usr
3.7G    /usr

$ jobs
[1]  - Running                       xemacs C-csh_n_tcsh.xml
[2]  + Suspended                     su toor

$ %2
# exit <co id="com.rep3" linkends="rep3" />
$ jobs
[1]  + Running                       xemacs C-csh_n_tcsh.xml
</programlisting>
<calloutlist>
	    <callout arearefs="com.su" id="su">
	      <para>Changement d'identité utilisateur.</para>
	    </callout>

	    <callout arearefs="com.susp" id="susp">
	      <para>Suspension du processus et restauration de l'identité précédente.</para>
	    </callout>

	    <callout arearefs="com.job1" id="job1">
	      <para>Liste des <foreignphrase>jobs</foreignphrase> en cours;</para>
	    </callout>

	    <callout arearefs="com.async" id="async">
	      <para>Lancement d'une nouvelle commande, &ie; un processus de manière asynchrone, celui ci écrira son éventuel résultat sur la sortie standard, sans se préoccuper de ce qu'il peut se passer !</para>
	    </callout>

	    <callout arearefs="com.rep" id="rep">
	      <para>Le résultat de la commande <command>du</command> survient au moment où l'utilisateur tape sa commande <command>ls</command> et pertube donc son affichage. </para>
	    </callout>
	    
	    <callout arearefs="com.exit" id="exit">
	      <para> Terminaison du processus. La commande <command>ls</command> s'affiche alors.</para>
	    </callout>


	    <callout arearefs="com.rep2" id="rep2">
	      <para>Le comportement du processus change, l'utilisateur est informé 
que le <foreignphrase>job</foreignphrase> 3 est prêt à imprimer son résultat (il est suspendu jusqu'à ce qu'il soit autorisé à la faire).</para>
	    </callout>

	    <callout arearefs="com.notif" id="notif">
	      <para>On rappelle le <foreignphrase>job</foreignphrase> 3, ce qui lui permet d'afficher son résultat.</para>
	      <para>Un <foreignphrase>job</foreignphrase> asynchrone qui veut lire sur l'entrée standard alors que ce canal n'a pas été redirigé est toujours suspendu. Il faut le relancer de manière interactive pour qu'il puisse collecter ses données sur l'entrée standard.</para>
	    </callout>

	    <callout arearefs="com.rep3" id="rep3">
	      <para>On rappelle le <foreignphrase>job</foreignphrase> 2 et on le termine explicitement par un <command>exit</command>. Il reste alors un seul <foreignphrase>job</foreignphrase> en exécution asynchrone.</para>
	    </callout>
</calloutlist>
</para>

	<para>La liste des <foreignphrase>jobs</foreignphrase> en cours est donnée par la commande <command>jobs</command>. </para>
	<para>Le caractère % en première position dénote un <foreignphrase>job</foreignphrase>. </para>
	<para>Le tableau suivant (&cf; <quote><xref linkend="tab05"/></quote>) récapitule les différentes manières de référencer un <foreignphrase>job</foreignphrase>. 
<table id="tab05">
	    <title> référencement des <foreignphrase>jobs</foreignphrase></title>
	    <!-- one of (graphic mediaobject tgroup) -->
	    <tgroup cols="2" align='left'>
               <colspec colnum="1" colname="c1" colwidth="1*+1"/>
               <colspec colnum="2" colname="c2" colwidth="3*+1"/>
	      <thead>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry> Expression </entry>
		  <entry> Sémantique </entry>
		</row>
	      </thead>
	      <tbody>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry>%n</entry>
		  <entry><foreignphrase>job</foreignphrase> numéro <emphasis>n</emphasis>.</entry>
		</row>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry>%str</entry>
		  <entry><foreignphrase>job</foreignphrase> commençant par la chaine <emphasis>str</emphasis>.</entry>
		</row>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry>%?str</entry>
		  <entry><foreignphrase>job</foreignphrase> contenant la chaine <emphasis>str</emphasis>.</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </table>
</para>
	
	<para>Le tableau suivant (&cf; <quote><xref linkend="tab05"/></quote>) donne les commandes de contrôle d'un <foreignphrase>job</foreignphrase>. 

<table id="tab06">
	    <title> Commandes contrôlant les <foreignphrase>jobs</foreignphrase></title>
	    <!-- one of (graphic mediaobject tgroup) -->
	    <tgroup cols="2" align='left'>
               <colspec colnum="1" colname="c1" colwidth="1*+1"/>
               <colspec colnum="2" colname="c2" colwidth="3*+1"/>
	      <thead>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry> Expression </entry>
		  <entry> Sémantique </entry>
		</row>
	      </thead>
	      <tbody>
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry><command>bg [name]</command></entry>
		  <entry><para>Place le job <emphasis>name</emphasis> en exécution asynchrone. </para>
                         <para>Si l'argument <emphasis>name</emphasis> n'est pas précisé, la commande s'applique au <foreignphrase>job</foreignphrase> courant.</para></entry>
		</row>
		
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry><command>name &amp;</command></entry>
		  <entry>Place le job <emphasis>name</emphasis> en exécution asynchrone.</entry>
		</row>
		
		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry><command>fg [name]</command></entry>
		  <entry> <para>Place le job <emphasis>name</emphasis> en exécution interactive.</para>
                          <para>Si l'argument <emphasis>name</emphasis> n'est pas précisé, la commande s'applique au <foreignphrase>job</foreignphrase> courant.</para>
                  </entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry><command>name</command></entry>
		  <entry>Place le job <emphasis>name</emphasis> en exécution interactive.</entry>
		</row>

		<row>
		  <!-- one of (entrytbl entry) -->
		  <entry><command>stop name</command></entry>
		  <entry>Suspend le job <emphasis>name</emphasis>.</entry>
		</row>

	      </tbody>
	    </tgroup>
	  </table>
</para>

	<para>Enfin, la commande <command>kill</command> permet aussi d'envoyer des signaux aux <foreignphrase>jobs</foreignphrase>, en utilisant le même référencement des jobs qu'en <quote><xref linkend="tab05"/></quote>. Ainsi, la commande suivante met fin au <foreignphrase>job</foreignphrase> 1 : 
<programlisting width="80">
<![CDATA[
$ kill -SIGTERM %1                                                              
]]>
</programlisting>
</para>

	<formalpara>
	  <title>Commande <command>nohup</command></title>
	  <para>En <command>&fshell;</command>, tous les processus (y compris les processus asynchrones) sont terminés lors d'un <command>logout</command>, l'exécution de cette commande déclenchant l'envoi du signal <foreignphrase>SIGHUP</foreignphrase> à tous les processus fils. Si un processus doit poursuivre son exécution au-delà du &shell; qui lui a donné naissance, il faut utiliser la commande <command>nohup</command> (&cf; <emphasis>man 1 nohup</emphasis>).
</para>

	</formalpara>
      </sect3>

      
    <sect3>
      <title><command>ulimit</command></title>
      <para>Cette commande a pour objet de définir des limites à la consommation des ressources du système par les processus. Il s'agit d'un intervalle définit par une borne haute (<emphasis>H</emphasis> : qui ne peut être modifiée qu'à la baisse, sauf par le <emphasis>super</emphasis>-utilisateur) et une borne basse (<emphasis>S</emphasis> : qui peut être accrue jusqu'aux valeurs de la borne haute).</para>

 <para>
<programlisting width="80">
<![CDATA[
$ ulimit -a        # affichage de toutes les limites (= min(S, H))              
core file size        (blocks, -c) 0
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) unlimited
max memory size       (kbytes, -m) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 4096
virtual memory        (kbytes, -v) unlimited

$ ulimit -Ss 16384 # augmenter la limite S de la pile (=s) à 16Ko
$ ulimit -aS       # affichage des limites S (basses)
core file size        (blocks, -c) 0
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) unlimited
max memory size       (kbytes, -m) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) 16384
cpu time             (seconds, -t) unlimited
max user processes            (-u) 4096
virtual memory        (kbytes, -v) unlimited

$ ulimit -Sn 2048  # augmenter la limite S du nb max. de fichiers ouverts
-bash: ulimit: open files: cannot modify limit: Operation not permitted
]]>
</programlisting>
</para>
    </sect3>


    </sect2>



<sect2 id="sect_redirection_comm">      
      <title>Redirection de commandes</title>
      <para> Rapellons que, sous &unix; en général et sous &glinux; en particulier, il existe trois canaux d'E/S standard : 
      <itemizedlist>
	<listitem><para>L'entrée standard [<foreignphrase>stdin</foreignphrase>] associée au fd [<foreignphrase>file descriptor</foreignphrase>] <emphasis role="bold">0</emphasis> liée traditionnellement au clavier.</para></listitem>
	<listitem><para>La sortie standard [<foreignphrase>stdout</foreignphrase>] associée au fd <emphasis role="bold">1</emphasis>, liée traditionnellement à l'écran du terminal.</para></listitem>
	<listitem><para>La sortie standard d'erreur  [<foreignphrase>stderr</foreignphrase>] associée au fd <emphasis role="bold">2</emphasis>, liée traditionnellement à l'écran du terminal.</para></listitem>
      </itemizedlist>

Formellement, un descripteur de fichier est un entier non signé utilisé par les processus pour référencer les canaux d'E/S.
      </para>
      
      <para>La puissance et la flexibilité du concept des canaux standards  d'E/S tient essentiellement au fait que le &shell; peut rediriger ces canaux aussi bien sur des fichiers, que l'écran ou le clavier.</para> 

<para> 
<table id="redirec">
	  <title>Redirections</title>
	  <tgroup cols="2">
	    <colspec colnum="1" colname="c1" colwidth="1*+1" align="left"/>
	    <colspec colnum="2" colname="c2" colwidth="3*+1" align="left"/>
	    
	    <thead valign="middle">
	      <row>
		<entry align="center">Symbole</entry>
		<entry align="center">Sémantique</entry>
	      </row>
	    </thead>
	    
	    <tbody>	      	     	    		
	      <row>
		<entry><command>&gt;</command> &lt;fnom&gt;</entry>
		<entry>La sortie standard est redirigée dans le fichier &lt;fnom&gt;. S'il existait, son contenu est perdu et sinon il est créé.</entry>
	      </row>

	      <row>
		<entry><command>&gt;&gt;</command> &lt;fnom&gt;</entry>
		<entry>La sortie standard est redirigée dans le fichier &lt;fnom&gt;, ouvert en mode ajout s'il existait, sinon il est créé.</entry>
	      </row>

	      <row>
		<entry><command>2&gt;</command> &lt;fnom&gt;</entry>
		<entry>La sortie d'erreur est redirigée dans le fichier &lt;fnom&gt;. S'il existait, son contenu est perdu et sinon il est créé.</entry>
	      </row>

	      <row>
		<entry><command>2&gt;&gt;</command> &lt;fnom&gt;</entry>
		<entry>La sortie d'erreur est redirigée dans le fichier &lt;fnom&gt;, ouvert en mode ajout s'il existait, sinon il est créé.</entry>
	      </row>

	      <row>
		<entry><command>&lt;</command> &lt;fnom&gt;</entry>
		<entry>L'entrée standard est le fichier &lt;fnom&gt;.</entry>
	      </row>
	      
	      <row>
		<entry><command>&lt;&lt;</command> &lt;mot&gt;</entry>
		<entry>Lit les entrées du &shell; jusqu'à une ligne commençant (et contenant uniquement) le mot &lt;mot&gt; qui agit comme un marqueur de fin.</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</table>
</para>


<para>Le positionnement de la variable interne <varname>NO_CLOBBER</varname>, permet d'éviter l'écrasement des fichiers existants dans le cas de l'utilisation des commandes de redirection <command>&gt;</command> et <command>&gt;&amp;</command>. De plus les commandes  <command>&gt;&gt;</command> et <command>&gt;&gt;&amp;</command> ne peuvent être exécutées que sur des fichiers existants.</para>

      <para>Enfin, la sémantique initiale des commandes de redirection (après activation de <varname>noclobber</varname>) peut être explicitement restituée en utilisant le symbole <command>!</command>. Ainsi, les commandes <command>&gt;!</command>, <command>&gt;&gt;!</command>, <command>&gt;&amp;!</command> et <command>&gt;&gt;&amp;!</command> ont un comportement identique à leurs homologues du tableau précédent (&ie; sans le <command>!</command>, &cf; <quote><xref linkend="redirec"/></quote>).


<programlisting width="80">
<emphasis>EXEMPLES :</emphasis>
<![CDATA[
$ cat > file.txt << fin_de_saisie                                               
>> première ligne
>> puis une 2e
>> Encore une autre !
>> C'est pas fini ...
>> fin_de_saisie

$  ll file.txt
-rw-------  1 pascal  gnu  - 65 Aug 1 15:58 file.txt

$ cat < file.txt  # équivalent à cat file.txt
première ligne
puis une 2e
Encore une autre !
C'est pas fini ...


$ ( find /home -name "*~" -print 1> fres ) 2> ferr
                  # séparer les sorties standard (> fres) et d'erreur (2> ferr) 
$ cat fres        # les résultats
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/CS2-csh/toto.sh~
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/Progr-V2L/Progr-V2L.xml~
/home/miji/work/these/annexes/annexes.sxw~
/home/miji/work/these/partie1/part_legende/legendes.sxw~
/home/hosts/corto-home/turing/postfix/main.cf~
/home/hosts/corto-home/euler/ulocal-etc/flexbackup/flexbackup.conf~
/home/hosts/corto-home/euler/ulocal-etc/tripwire/twpol.txt~
/home/hosts/corto-home/euler/etc/ssh/sshd_config~
/home/hosts/corto-home/tux/etc/apache/httpd.conf~
/home/hosts/corto-home/tux/etc/apache-ssl/httpd.conf~

$ cat ferr        # les erreurs
find: /home/miji/.ssh: Permission denied
find: /home/miji/work/lit_reu/Dayot: Permission denied
find: /home/miji/Choices: Permission denied
find: /home/miji/pdf: Permission denied
find: /home/miji/tmp: Permission denied
find: /home/miji/.Eterm: Permission denied
find: /home/miji/.mozilla: Permission denied
find: /home/miji/.mutt: Permission denied
find: /home/miji/.netscape: Permission denied
find: /home/miji/.prefs: Permission denied
find: /home/miji/.vnc: Permission denied
find: /home/miji/.Gabber: Permission denied
find: /home/miji/.wmakerconf: Permission denied
]]>
</programlisting>
</para>

    </sect2>


<sect2>      
      <title> Tubes [<foreignphrase>Pipelines</foreignphrase>] </title>
      <para>
Le mécanisme de <foreignphrase>pipeline</foreignphrase> consiste à  rediriger la sortie d'une commande vers l'entrée d'une autre. D'un point de vue syntaxique nous avons la structure suivante :
<programlisting width="80">
<![CDATA[
<commandA> | <commandB>                                                         
]]>
</programlisting>
      
      <example id="ex_pipe">
	<title> Utilisation du mécanisme de <foreignphrase>pipeline</foreignphrase> </title>
	<para>
<programlisting width="80">
<![CDATA[
ls -l | sort -k 5n                                                              
]]>
</programlisting>

La sortie de la commande <command>ls -l</command> est redirigée vers l'entrée de la commande <command>sort -k 5n</command>.
</para>
      </example>
    </para>

      <qandaset defaultlabel='qanda'>
	<qandaentry>
	  <question>
	    <para>
            Que permet de réaliser la commande précédente ?
            </para>
	  </question>
	  <answer>
	    <para/> 
            <!-- tri numérique (ordre croissant) du répertoire (listing au format long) sur le 5e champ, i.e. la taille en octet --> 
	  </answer>
	</qandaentry>
      </qandaset>

    </sect2>

</sect1>







<!-- 3e partie -->
  <sect1>
    <title>Structures de Contrôle &amp; autres éléments algorithmiques</title>
    
    <para>Ces structures algorithmiques sont utilisées dans les scripts &shell;s. Pour rédiger un script &shell; (ici, en &fshell;), il faut :
<orderedlist>
	<listitem><para>Créer le fichier avec un éditeur de texte (<filename>sample.sh</filename>). La première ligne doit commencer avec le prologue [<foreignphrase>shebang</foreignphrase>] :  <command>#!/bin/bash</command>. </para></listitem>
	<listitem><para>Attribuer la permission d'exécution sur le fichier créé (<computeroutput>chmod +x sample.sh</computeroutput>).</para></listitem>
	<listitem><para>Enfin, pour l'exécuter il suffit de taper le nom du fichier, puisque c'est désormais une nouvelle commande (si on est dans le répertoire courant de cette commande, il suffit de taper <computeroutput>./sample.sh</computeroutput>).</para></listitem>
      </orderedlist>
Nous donnons dans ce qui suit, quelques exemples de scripts &shell;s (&fshell;). 
    </para>
    
    <sect2>      
      <title>Alternatives</title>
<!-- IF -->
      <sect3>
	<title> La structure alternative <command>if</command></title>
	<para> Cette structure permet l'exécution conditionnelle d'une instruction. Voici sa syntaxe (les deux formes sont équivalentes) :</para> 
	<para>
<programlisting width="80">
<![CDATA[
if [ <condition> ]; then                   if test <condition>; then            
  <liste instructions>                       <liste instructions>
elif [ <condition> ]; then                 elif test <condition>; then
  <liste instructions>                       <liste instructions>
elif [ <condition> ]; then                 elif test <condition>; then
  <liste instructions>                       <liste instructions>
else                                       else
  <liste instructions>                       <liste instructions>
fi                                         fi
]]>
</programlisting>
</para>

<para>
<example id="ex_if">
	    <title>Utilisation du if</title>
<programlisting width="80">
&_fcomp;
</programlisting>
	  </example>
<example>
	    <title> Résultat du code de <xref linkend="ex_if"/> </title>
<programlisting width="80">
<![CDATA[
$ ~/bin/fcomp.sh
usage : /home/pascal/bin/fcomp.sh file1 file2
compare deux fichiers file1 et file2 et dit s'il sont identiques ou differents. 

$ ~/bin/fcomp.sh ~/bin/fcomp.sh ~/bin/fdate.sh 
Les fichiers /home/pascal/bin/fcomp.sh et /home/pascal/bin/fdate.sh sont differe
nts.
]]>
</programlisting>
	</example>
</para>
      </sect3>
<!-- END IF -->

<!-- CASE -->
<sect3>
	<title>La structure alternative <command>case</command></title>
	<para>Cette structure permet l'exécution conditionnelle d'une instruction. </para> 
	<para>
<programlisting width="80">
<![CDATA[
case <variable> in                                                              
  motif11|motif12|... )
         <liste instructions>
         ;;

  motif21|motif22|... )
         <liste instructions>
         ;;

  motif3)
         <liste instructions>
         ;;

  motif4)
         <liste instructions>
         ;;

  *)
         <liste instructions>
         ;;
esac
]]>
</programlisting>
</para>

<para>
<example id="ex_switch">
	    <title>Utilisation du switch</title>
<para>
<programlisting width="80">
&_fdate;
</programlisting>
</para>
	  </example>

<example>
	    <title> Résultat du code de <xref linkend="ex_switch"/> </title>
<programlisting width="80">
$ fdate.sh                                                                      
Sam 12 Avr 2003, 21:20:45 [RET]
</programlisting>
	</example>

</para>

      </sect3>
<!-- END SWITCH -->
    </sect2>




    <sect2>      
      <title>Boucles</title>
<!-- WHILE -->
      <sect3>
	<title> Boucle <command>while</command></title>
	<para>Il s'agit de l'instruction standard qui permet d'exécuter le corps de la boucle tant que la condition d'entrée est vérifiée (valeur évaluée à vrai). </para>
	<para>
<programlisting width="80">
<![CDATA[
while [ <condition> ]; do                                                       
  <corps_de_boucle>
done
]]>
</programlisting>
</para>

<para>
<example id="ex_while">
	    <title>Utilisation du while</title>
<programlisting width="80">
<![CDATA[
#!/bin/bash                                                                     
# ~/bin/test.sh                                                                 

ind=1

while [ $ind -lt  11 ]; do
  indcar=`expr $ind \* $ind` 
  echo $ind "  " $indcar
  ind=` expr $ind + 1` 
done
]]>
</programlisting>
	  </example>
<example>
	    <title> Résultat du code de <xref linkend="ex_while"/> </title>
<programlisting width="80">
<![CDATA[
$ ~/bin/test.sh                                                                 
1     1                                                                         
2     4
3     9
4     16
5     25
6     36
7     49
8     64
9     81
10     100
]]>
</programlisting>
	</example>
</para>

      </sect3>
<!-- END WHILE -->

<!-- UNTIL -->      
      <sect3>
	<title>Boucle <command>until</command> </title>
	<para>Il s'agit de l'instruction standard qui permet d'exécuter le corps de la boucle jusquà ce que la condition d'entrée soit vérifiée (valeur évaluée à vrai).</para>
	<para>
<programlisting width="80">
<![CDATA[
until [ <condition> ]; do                                                       
  <corps_de_boucle>
done
]]>
</programlisting>
</para>

<para>
<example id="ex_until">
	    <title> Utilisation du <command>until</command> </title>
<programlisting width="80">
<![CDATA[
#!/bin/bash                                                                     
# ~/bin/test.sh                                                                 

ind=1

until [ $ind -ge  11 ]; do
  indcar=`expr $ind \* $ind` 
  echo $ind "  " $indcar
  ind=` expr $ind + 1` 
done
]]>
</programlisting>
	  </example>
<example>
	    <title> Résultat du code de <xref linkend="ex_until"/> </title>
<programlisting width="80">
<![CDATA[
$ ~/bin/test.sh                                                                 
1     1                                                                         
2     4
3     9
4     16
5     25
6     36
7     49
8     64
9     81
10     100
]]>
</programlisting>
	</example>
</para>

      </sect3>
<!-- END UNTIL -->

<!-- FOR -->
    <sect3>
	<title> Boucle <command>for</command></title>
	<para> Cette instruction permet de traiter en séquence tous les éléments d'une liste.</para>
	<para>

<programlisting width="80">
<![CDATA[
for <variable> in <liste_de_valeur>; do                                         
  <corps_de_boucle>
done
]]>
</programlisting>
</para>

<para>
<example id="ex_for">
	    <title> Utilisation du <command>for</command> </title>
<programlisting width="80">
<![CDATA[
#!/bin/bash 
# ~/bin/test.sh                                                                 

for i in 1 2 3 4 5 6 7 8 9; do                                                  
  m=`expr $i \* 2`
  echo -n " $m"
done
echo
]]>
</programlisting>
	  </example>

<example>
	    <title> Résultat du code de <xref linkend="ex_for"/> </title>
<programlisting width="80">
<![CDATA[
$ ~/bin/test.sh                                                                 
2 4 6 8 10 12 14 16 18                                                          
$
]]>
</programlisting>
	</example>
</para>

      </sect3>
<!-- END FOR -->


<!-- A U T R E S  B O U C L E S -->
    </sect2>

    
     <sect2>
      <title>Variables utilisateurs</title>

      <para>Ce sont les variables que les utilisateurs peuvent définir. Le &shell; étant un langage interprété non typé, aucune déclarartion n'est nécessaire et la même variable peut contenir tour à tour une chaîne de caractères, un entier ou un vecteur (tableau d'éléments de type chaîne de caractères ou entier, indexé par des entiers, commençant à 0).</para>
      
      <formalpara>
	<title>Affectation</title>
	<para>Cette opération permet d'associer un contenu à une variable (le contenant). En &fshell; l'affectation se fait en utilisant de la manière suivante (noter bien l'absence d'espace autour du symbole <emphasis role="bold">=</emphasis>) :
<programlisting width="80">
<emphasis>EXEMPLE :</emphasis>
<![CDATA[
$ myvar1=10                                                                     
$ myvar2="chaine de caractère"
]]>
</programlisting>
</para>
      </formalpara>

      <formalpara>
	<title>Accès au contenu</title>
	<para>L'accès au contenu de la variable se fait en préfixant le nom de la variable par le symbole <emphasis role="bold">$</emphasis>.
<programlisting width="80">
<emphasis>EXEMPLE (SUITE) :</emphasis>
<![CDATA[
$ echo $myvar1                                                                  
10
$ echo myvar2
chaine de caractère

$ echo myvar1     # omission du méta-caractère $
myvar1            # echo affiche le mot myvar1
]]>
</programlisting>

On peut aussi encadrer la variable par les symboles <emphasis role="bold">{</emphasis> et <emphasis role="bold">}</emphasis> avant de la préfixer par le symbole <emphasis role="bold">$</emphasis> :
<programlisting width="80">
<emphasis>EXEMPLE (SUITE) :</emphasis>
<![CDATA[
$ si="pas "                                                                     
$ echo "c'est vraiment $sidrole"  # la variable $sidrole n'est pas définie      
c'est vraiment
$ echo "c'est vraiment ${si}drôle"
c'est vraiment pas drôle
]]>
</programlisting>

<note><para>L'accès à une variable non définie ne produit pas d'erreur en &fshell;.</para></note>
</para>
      </formalpara>

 <formalpara>
	<title>Effacer une variable</title>
	<para>Cette opération permet de libérer la case mémoire occupée par la variable. Cela se fait en &fshell; en utilisant la commande interne <command>unset</command> de la manière suivante :
<programlisting width="80">
<emphasis>EXEMPLE (SUITE) :</emphasis>
<![CDATA[
$ echo $myvar1                                                                  
10
$ unset myvar1
$ echo $myvar1

$
]]>
</programlisting>
</para>
      </formalpara>

      <formalpara>
	<title>Variable de type vecteur</title>
	<para>Voici un exemple :
<programlisting width="80">
<emphasis>CODE :</emphasis>

&_ftestv;

<emphasis>EXEMPLE :</emphasis>
<![CDATA[
$ ./testvect.sh                                                                 
 -  Affichage element par       element
${vect[ 0 ]} =  2
${vect[ 1 ]} =  -2
${vect[ 2 ]} =  4
${vect[ 3 ]} =  -4
${vect[ 4 ]} =  6
${vect[ 5 ]} =  -6
${vect[ 6 ]} =  8
${vect[ 7 ]} =  -8
${vect[ 8 ]} =  10
${vect[ 9 ]} =  -10
 - Somme des elements =  0
Voici le vecteur vect (10 elements)         :  2 -2 4 -4 6 -6 8 -8 10 -10
$
]]>
</programlisting>
</para>
      </formalpara>


      <formalpara>
	<title>Mécanismes de substitution</title>
	<para>

        <table>
	    <title>Clé de substitution</title>
	    <tgroup cols="2">
	      <colspec colnum="1" colname="c1" colwidth="1*+1" align="left"/>
	      <colspec colnum="2" colname="c2" colwidth="3*+1" align="left"/>

	      <thead valign="middle">
		<row>
		  <entry align="center">Clé</entry>
		  <entry align="center">Sémantique</entry>
		</row>
	      </thead>

	      <tbody>	      	     	    		
		<row>
		  <entry><varname>${#&lt;name&gt;}</varname></entry>
		  <entry>Donne le nombre de caractères du contenu de la variable</entry>
		</row>

		<row>
		  <entry><varname>${&lt;name&gt;:-&lt;value&gt;}</varname></entry>
		  <entry>Renvoit la valeur de la variable &lt;name&gt; si elle existe et sinon &lt;value&gt; (il n'y a pas affectation).</entry>
		</row>
		
		<row>
		  <entry><varname>${&lt;name&gt;:=&lt;value&gt;}</varname></entry>
		  <entry>Renvoit la valeur de la variable &lt;name&gt; si elle existe et sinon affecte &lt;value&gt; à &lt;name&gt; et renvoit la valeur.</entry>
		</row>
		
		<row>
		  <entry><varname>${&lt;name&gt;:?&lt;value&gt;}</varname></entry>
		  <entry>Affiche &lt;value&gt; sur la sortie d'erreur standard si &lt;name&gt; n'est pas définie et réalise un exit s'il ne s'agit pas d'un shell interactif</entry>
		</row>
		
		<row>
		  <entry><varname>${&lt;name&gt;:+&lt;value&gt;}</varname></entry>
		  <entry>Affiche &lt;value&gt; si &lt;name&gt; est définie et rien sinon</entry>
		</row>


		<row>
		  <entry><varname>${&lt;name&gt;#&lt;motif&gt;}</varname></entry>
		  <entry>Supprime de &lt;name&gt; le motif &lt;motif&gt; le plus petit correspondant à gauche.</entry>
		</row>

		<row>
		  <entry><varname>${&lt;name&gt;##&lt;motif&gt;}</varname></entry>
		  <entry>Supprime de &lt;name&gt; le motif &lt;motif&gt; le plus grand correspondant à gauche.</entry>
		</row>

		<row>
		  <entry><varname>${&lt;name&gt;%&lt;motif&gt;}</varname></entry>
		  <entry>Supprime de &lt;name&gt; le motif &lt;motif&gt; le plus petit correspondant à droite.</entry>
		</row>

		<row>
		  <entry><varname>${&lt;name&gt;%%&lt;motif&gt;}</varname></entry>
		  <entry>Supprime de &lt;name&gt; le motif &lt;motif&gt; le plus grand correspondant à droite.</entry>
		</row>


		 </tbody>
	    </tgroup>
	  </table>
		

<programlisting width="80">
<emphasis>EXEMPLE :</emphasis>

<![CDATA[
$ var=/usr/local/bin/example.tar.gz

$ echo ${var#*.}   # supprime ce qui précède le 1er . [+ petit motif à gauche]  
tar.gz                
            
$ echo ${var##*.}  # supprime ce qui précède le 2e . [+ long motif à gauche]
.gz

$ echo ${var%.*}   # supprime ce qui suit le dernier . [+ petit motif à droite]
/usr/local/bin/example.tar

$ echo ${var%%.*}  # supprime ce qui suit l'av-dernier . [+ gand motif à droite]
/usr/local/bin/example
]]>
</programlisting>
</para>
      </formalpara>


<qandaset defaultlabel='qanda'>
	<qandaentry>
	  <question>
	    <para>D'après l'exemple qui précède, comment n'obtenir que le nom du fichier, sans le chemin complet et sans le suffixe (en deux temps) ?</para>
	  </question>
	  <answer>
	    <para>

<!--
<computeroutput>$ svar=${var##*/} &amp;&amp; ${svar%%.*} </computeroutput> 
-->

</para>
	  </answer>
	</qandaentry>
      </qandaset>

    </sect2>




    <sect2>
      <title>Paramètres du shell</title>
      <para>Le &shell; définit pour chaque commande un certain nombre de paramètres <quote>automatiques</quote>.

<table>
	  <title>Opérateurs de comparaison</title>
	  <tgroup cols="2">
	    <colspec colnum="1" colname="c1" colwidth="1*+1" align="left"/>
	    <colspec colnum="2" colname="c2" colwidth="3*+1" align="left"/>

	    <thead valign="middle">
	      <row>
		<entry align="center">Paramètre(s)</entry>
		<entry align="center">Utilisation</entry>
	      </row>
	    </thead>

	    <tbody>	      	     	    
	      <row>
		<entry><varname>$0</varname></entry>
		<entry>nom de la commande ou du script invoqué.</entry>
	      </row>

	      <row>
		<entry><varname>$1</varname>, <varname>$2</varname> .. <varname>$9</varname></entry>
		<entry>valeurs des paramètres positionnels passés à la commande ou au script.</entry>
	      </row>

	      <row>
		<entry align="left"><varname>$*</varname></entry>
		<entry align="left">ensemble des paramètres, sauf $0. "$#" vaut "$1 $2 ..."</entry>		
	      </row>

	      <row>
		<entry align="left"><varname>$@</varname></entry>
		<entry align="left">ensemble des paramètres, sauf $0. "$@" vaut "$1" "$2" ...</entry>		
	      </row>

	      <row>
		<entry><varname>$#</varname></entry>
		<entry colname="c2" align="left">nombre de paramètres effectifs, $0 non compris.</entry>
	      </row>	      	      

	      <row>
		<entry><varname>$-</varname></entry>
		<entry colname="c2" align="left">les options courantes du shell</entry>
	      </row>	      	      
	      
	      <row>
		<entry><varname>$?</varname></entry>
		<entry colname="c2" align="left">le code de retour de la dernière commande</entry>
	      </row>	      	      

	      <row>
		<entry><varname>$$</varname></entry>
		<entry colname="c2" align="left">le <emphasis>pid</emphasis> du shell parent</entry>
	      </row>	      	      

	      <row>
		<entry><varname>$!</varname></entry>
		<entry colname="c2" align="left">le <emphasis>pid</emphasis> du dernier processus asynchrone lancé par le shell parent</entry>
	      </row>	

	      <row>
		<entry><varname>$_</varname></entry>
		<entry colname="c2" align="left">le dernier argument de la commande précédente</entry>
	      </row>	
	      
	    </tbody>
	  </tgroup>
	</table>

<programlisting width="80">
<emphasis>CODE :</emphasis>

&_ftestp;

<emphasis>EXEMPLE :</emphasis>
<![CDATA[
$ ./testparam.sh toto titi tutu 147                                             
je suis le script, $0 =  ./ftestparm.sh
 evoque avec  4  arguments sur la ligne de commande
Voici les parametres : $*  toto titi tutu 147
parametre (0) :  toto
parametre (1) :  titi
parametre (2) :  tutu
parametre (3) :  147

$ ./testparam.sh
je suis le script, $0 =  ./testparam.sh
 pas d arguments, nb arg $# =  0
$
]]>
</programlisting>

</para>
    </sect2>




    <sect2>
      <title>Expressions conditionnelles</title>
<para>Voici une liste non exhaustive des principaux opérateurs de comparaison :

<table>
	  <title>Opérateurs de comparaison</title>
	  <!-- one of (graphic mediaobject tgroup) -->
	  <tgroup cols="2">
	    <colspec colnum="1" colname="c1" colwidth="1*+1" align="left"/>
	    <colspec colnum="2" colname="c2" colwidth="3*+1" align="left"/>
	    <thead valign="middle">
	      <row>
		<!-- one of (entrytbl entry) -->
		<entry align="center">Opérateur</entry>
		<entry align="center">Sémantique</entry>
	      </row>
	    </thead>

	    <tbody>

              <!-- FILE --> 
	      <row>
		<entry namest="c1" nameend="c2"><emphasis role="bold">O P E R A T E U R S &nbsp;&nbsp; D E &nbsp;&nbsp; F I C H I E R S</emphasis></entry>
	      </row>
	      
	      <row>
		<entry><command><option>-b</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier spécial en mode bloc.</entry>
	      </row>

	      <row>
		<entry><command><option>-c</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier spécial en mode caractères.</entry>
	      </row>

	      <row>
		<entry><command><option>-d</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un répertoire.</entry>
	      </row>

	      <row>
		<entry><command><option>-e</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> existe.</entry>
	      </row>

	      <row>
		<entry><command><option>-f</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier régulier.</entry>
	      </row>

	      <row>
		<entry><command><option>-g</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> a le <emphasis>setgid bit</emphasis> activé.</entry>
	      </row>

	      <row>
		<entry><command><option>-k</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> a le <emphasis>sticky bit</emphasis> activé.</entry>
	      </row>

	      <row>
		<entry><command><option>-u</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> a le <emphasis>setuid bit</emphasis> activé.</entry>
	      </row>
	      
	       <row>
		<entry><command><option>-G</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> appartient au groupe (<emphasis>egid</emphasis>).</entry>
	      </row>

	       <row>
		<entry><command><option>-O</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis>  appartient à l'utilisateur effectif du processus (<emphasis>euid</emphasis>).</entry>
	      </row>

	      <row>
		<entry><command><option>-L</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un lien symbolique.</entry>
	      </row>

	      <row>
		<entry><command><option>-p</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier spécial FIFO (tube nommé).</entry>
	      </row>

	      <row>
		<entry><command><option>-r</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier accessible en lecture.</entry>
	      </row>

	      <row>
		<entry><command><option>-w</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier accessible en écriture.</entry>
	      </row>

	      <row>
		<entry><command><option>-x</option> &lt;filename&gt;</command></entry>
		<entry>est vraie si le fichier désigné par <emphasis>&lt;filename&gt;</emphasis> est un fichier exécutable.</entry>
	      </row>

	      <row>
		<entry><command>&lt;filename1&gt; <option>-nt</option> &lt;filename2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;filename1&gt;</emphasis> est plus récent que <emphasis>&lt;filename2&gt;</emphasis>.</entry>
	      </row>

	      <row>
		<entry><command>&lt;filename1&gt; <option>-ot</option> &lt;filename2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;filename1&gt;</emphasis> est plus vieux que <emphasis>&lt;filename2&gt;</emphasis>.</entry>
	      </row>
              
              <!-- STRING --> 
	      <row>
		<entry namest="c1" nameend="c2"><emphasis role="bold">C O M P A R A I S O N &nbsp;&nbsp; D E &nbsp;&nbsp; C H A I N E S</emphasis></entry>
	      </row>
	
	      <row>
		<entry><command><option>-n</option> &lt;str&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;str&gt;</emphasis> a une longueur non nulle.</entry>
	      </row>

	       <row>
		<entry><command><option>-z</option> &lt;str&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;str&gt;</emphasis> a une longueur nulle.</entry>
	      </row>

	      <row>
		<entry><command>&lt;str1&gt; <option>=</option> &lt;str2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;str1&gt;</emphasis> est égale à <emphasis>&lt;str2&gt;</emphasis>.</entry>
	      </row>
              
	      <row>
		<entry><command>&lt;str1&gt; <option>!=</option> &lt;str2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;str1&gt;</emphasis> est différente de <emphasis>&lt;str2&gt;</emphasis>.</entry>
	      </row>

	      <!-- ENTIER --> 
	      <row>
		<entry namest="c1" nameend="c2"><emphasis role="bold">C O M P A R A I S O N &nbsp;&nbsp; D ' E N T I E R S</emphasis></entry>
	      </row>
	      
	      <row>
		<entry><command>&lt;int1&gt; <option>-eq</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est égal à <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>

	       <row>
		<entry><command>&lt;int1&gt; <option>-ne</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est différent <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>

	      <row>
		<entry><command>&lt;int1&gt; <option>-ge</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est supérieur ou égal à <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>
	      
	       <row>
		<entry><command>&lt;int1&gt; <option>-gt</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est strictement supérieur à <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>

	       <row>
		<entry><command>&lt;int1&gt; <option>-le</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est inférieur ou égal à <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>

	      <row>
		<entry><command>&lt;int1&gt; <option>-lt</option> &lt;int2&gt;</command></entry>
		<entry>est vraie si <emphasis>&lt;int1&gt;</emphasis> est strictement inférieur à <emphasis>&lt;int2&gt;</emphasis>.</entry>
	      </row>


	      <!-- COMBINAISON D'EXPR --> 
	      <row>
		<entry namest="c1" nameend="c2"><emphasis role="bold">C O M B I N A I S O N &nbsp;&nbsp; D ' E X P R E S S I O N S</emphasis></entry>
	      </row>
	      
	      <row>
		<entry><command> ( &lt;expr&gt; ) </command></entry>
		<entry>est vraie si <emphasis>&lt;expr&gt;</emphasis> est vraie.</entry>
	      </row>

	      <row>
		<entry><command> <option>!</option> &lt;expr&gt; </command></entry>
		<entry>est vraie si <emphasis>&lt;expr&gt;</emphasis> est fausse.</entry>
	      </row>

	      <row>
		<entry><command> &lt;expr1&gt; <option>-a</option> &lt;expr2&gt; </command></entry>
		<entry>est vraie si <emphasis>&lt;expr1&gt;</emphasis> et <emphasis>&lt;expr2&gt;</emphasis> sont simultanément vraies.</entry>
	      </row>
	      
	      <row>
		<entry><command> &lt;expr1&gt; <option>-o</option> &lt;expr2&gt; </command></entry>
		<entry>est vraie si <emphasis>&lt;expr1&gt;</emphasis> ou <emphasis>&lt;expr2&gt;</emphasis> est/sont vraie(s).</entry>
	      </row>
	      

	    </tbody>
	  </tgroup>
	</table>
</para>


      <para> <emphasis role="bold">Règles</emphasis> :
<itemizedlist>
	  <listitem><para>Les instructions arithmétiques apparaissent dans l'instruction <command>let</command> et dans l'expansion arithmétique.</para></listitem>
	  <listitem><para>Les constantes commençant par 0  (resp. 0x) sont interprétées comme des valeurs en base octale (resp. héxadécimale).</para></listitem>
	  <listitem><para>Une constante entière peut être exprimée dans une base de l'intervalle [2, 64], en la préfixant par l'expression <emphasis>base#</emphasis>. La base par défaut est 10.</para></listitem>
	  <listitem><para>Les variables du shell sont autorisées comme opérandes dans les expressions arithmétiques, l'expansion (substitution de la variable par sa valeur) ayant lieu, logiquement, avant l'évaluation de l'expression arithmétique.</para></listitem>
	</itemizedlist>
</para>


</sect2>

</sect1>






<!-- VERSION ASR DEBUT --> 

<!-- 4e PARTIE : EXOS -->

  <sect1>

    <title>Exercices</title>

    <simplesect>
      <title>Exercice - Mécanisme d'évaluation (1) </title>
      <para> Soit les affectations suivantes :

<programlisting width="80">
<![CDATA[
$ x=date                                                                        
$ y=foobar 
]]>
</programlisting>
</para>

      
      <para>Tester les commandes suivantes et expliquer dans chaque le résultat obtenu.
<programlisting width="80">
<![CDATA[
$ echo $x ; echo $y ; echo $z                                                   

$ echo "$x" ; echo "$y" ; echo "$z"

$ echo '$x' ; echo '$y' ; echo '$z'

$ echo `$x` ; echo `$y` ; echo `$z` 

$ $x ; $y ; $z

$ "$x" ; "$y" ; "$z"

$ '$x' ; '$y' ; '$z'

$ `$x` ;  `$y` ; `$z` 

$ $y=`$x` 

$ echo $foobar
]]>
</programlisting>
</para>
    </simplesect>

    <simplesect>
      <title>Exercice - Mécanisme d'évaluation (2)</title>
            
      <para>Tester les commandes suivantes et expliquer dans chaque le résultat obtenu.
<programlisting width="80">
<![CDATA[
$ echo pwd                                                                      

$ `echo pwd`

$ 'echo pwd'

$ "echo pwd"

$ echo echo pwd

$ echo `echo pwd`

$ echo 'echo pwd'

$ echo "echo pwd"

$ echo '`echo pwd`'

$ echo '`echo pwd`'
]]>
</programlisting>
</para>
    </simplesect>


        <simplesect>
      <title>Exercice - Modification de l'environnement d'un processus, incidence sur le/les fils</title>
            
      <para>Dans un terminal, sous le &shell; courant définir deux variables (<varname>var1</varname> et <varname>var2</varname>) et modifier quelques variables d'environnement. Afficher l'environnement ainsi modifié.</para>

      <para>Dans ce même terminal, empiler un nouveau shell (<command>/bin/bash</command>). Quelle sont les valeurs de <varname>var1</varname> et <varname>var2</varname>, des variables d'environnement ?
Définir une variable <varname>var3</varname>.</para>

<para>Quitter ce &shell; et revenir à l'environnement initial (<command>exit</command>). Examiner son environnement, que vaut <varname>var3</varname> ? Conclure.</para>
      <para>Exporter maintenant la variable  <varname>var1</varname>, empiler un nouveau &shell;. Examiner son environnment. Modifier ensuite 
<varname>var1</varname>. Définir la variable <varname>var2</varname>. Quitter ce &shell;, pour revenir à celui de départ. Quelles sont les valeurs de  <varname>var1</varname> et <varname>var2</varname> ?</para>

      <para>Et si avant de quitter ce &shell; empilé, vous aviez exporté la variable <varname>var2</varname>, qu'auriez-vous obtenu ? </para>
    </simplesect>

    <simplesect>
      <title>Exercice - Exécution asynchrone concurrente de processus</title>
      <para>Exécuter la commande suivante dans un premier terminal, et dans un second ouvert pour l'occasion, lister les processus en cours d'exécution (se limiter aux seuls processus du terminal <quote>générateur</quote>), observer leur filiation, le nombre de processus : 
<programlisting width="80">
<![CDATA[
$ ( ls -la /usr/bin/ ; sleep 5 ; echo "5 - OK" ; last ) & \                     
( cat /etc/passwd ; sleep 7 ; echo "7 - OK" ; cat /etc/group ) & ps aux
]]>
</programlisting>
Observer l'entrelacement des résulats de ces commandes.
</para>
      <para>La séquence <foreignphrase>backslash</foreignphrase> (&ie; \), suivit de la touche &lt;Entrée&gt; indique au &shell; une continuation de la commande sur la ligne suivante. Que fait la commande <command>sleep</command> ?</para>
    </simplesect>
    

    <simplesect>
      <title>Exercice - Manipulation de jobs (1)</title>
      <para>Lancer la commande suivante : <computeroutput>find / -type d -print</computeroutput>, laquelle recherche tous les objets de type répertoire dans toute l'arborescence. La recherche se fait de manière récursive et comme l'arborescence est grande, l'exécution est <emphasis>un peu longue</emphasis>. On est bloqué tant que le processus exécutant le <command>find</command> n'est pas terminé. Il vous est demandé de :

<orderedlist numeration="lowerroman" spacing="compact">
	  <listitem>
	    <para>suspendre (ou stopper) le processus.</para>
	  </listitem>

	  <listitem>
	    <para>de le relancer en arrière-plan</para>
	  </listitem>

	  <listitem>
	    <para>de le ramener au premier plan</para>
	  </listitem>

	  <listitem>
	    <para>de le terminer.</para>
	  </listitem>
	</orderedlist>
Est-il possible de <quote>tuer</quote> des processus ne vous appartenant pas ? Tester-le.
</para>

<para>Si vous n'êtes pas assez rapide ou bien si la commande s'exécute trop rapidement, ouvrir un nouveau terminal et refaire le travail demandé. </para>

    </simplesect>


    <simplesect>
      <title>Exercice - Manipulation de jobs (2) </title>
      <para>Reprendre l'exemple de la commande <command>find</command>, de la section <quote><xref linkend="sect_redirection_comm"/></quote>, mais limiter la recherche au répertoire <filename>/etc</filename>.
<orderedlist numeration="lowerroman" spacing="compact">
	  <listitem>
	    <para>Rediriger uniquement les erreurs dans un fichier (<filename>ferr</filename>) ; </para>
	  </listitem>

	  <listitem>
	    <para>Rediriger uniquement les sorties dans un fichier (<filename>frep</filename>) ; </para>
	  </listitem>

	  <listitem>
	    <para>Rediriger les sorties et les erreurs dans un même fichier (<filename>freperr</filename>) ; </para>
	  </listitem>

	  <listitem>
	    <para>Rediriger les sorties et les erreurs dans leurs fichiers respectifs (<filename>frep</filename> et <filename>ferr</filename>).</para>
	  </listitem>

	</orderedlist>
</para>
    </simplesect>

  </sect1>

<!-- VERSION ASR FIN --> 






<!-- =================================================================== -->




  <bibliography> 
     <title>Références</title> 

     <bibliodiv> 
      
      <biblioentry>
	<abbrev>0</abbrev>
	<authorgroup>
	  <author>
	    <personname>
	      <surname>GNU/Bash</surname>
	    </personname>
	  </author>
	</authorgroup>
	<title>Bash reference manual (version 2.05a)</title> 
 	<edition> 
 	 <ulink url="http://www.gnu.org/manual/bash-2.05a/html_mono/bashref.html"></ulink>
	</edition> 
 	<date>dernière maj : 13.11.2001</date>
      </biblioentry>


      <biblioentry> 
        <abbrev>1</abbrev> 
        <authorgroup>
          <author>         
            <personname>
            <!-- one of (othername lineage surname firstname honorific) -->
	      <surname>GNU/Bash home page</surname>
          </personname>   
        </author>
        </authorgroup>
        <title>Bash - GNU project - FSF</title> 
        <edition> 
          <ulink url="http://www.gnu.org/software/bash/bash.html"></ulink> 
         </edition> 
      </biblioentry> 

      <biblioentry> 
        <abbrev>2</abbrev> 
        <authorgroup>
          <author>         
            <personname>
            <!-- one of (othername lineage surname firstname honorific) -->
            <firstname>Robbins</firstname>
            <surname>Daniel</surname>
          </personname>   
          <email>drobbins@gentoo.org</email>
        </author>
        </authorgroup>
        <title>Bash by example, Part 1</title> 
        <edition> 
          <ulink url="http://www-106.ibm.com/developerworks/linux/library/l-bash.html"></ulink> 
         </edition> 
      </biblioentry> 


      <biblioentry> 
        <abbrev>3</abbrev> 
        <authorgroup>
          <author>         
            <personname>
            <!-- one of (othername lineage surname firstname honorific) -->
            <firstname>Robbins</firstname>
            <surname>Daniel</surname>
          </personname>   
          <email>drobbins@gentoo.org</email>
        </author>
        </authorgroup>
        <title>Bash by example, Part 2</title> 
        <edition> 
          <ulink url="http://www-106.ibm.com/developerworks/linux/library/l-bash2.html"></ulink> 
         </edition> 
      </biblioentry> 


      <biblioentry> 
        <abbrev>4</abbrev> 
        <authorgroup>
          <author>         
            <personname>
            <!-- one of (othername lineage surname firstname honorific) -->
            <firstname>Robbins</firstname>
            <surname>Daniel</surname>
          </personname>   
          <email>drobbins@gentoo.org</email>
        </author>
        </authorgroup>
        <title>Bash by example, Part 3</title> 
        <edition> 
          <ulink url="http://www-106.ibm.com/developerworks/linux/library/l-bash3.html"></ulink> 
         </edition> 
      </biblioentry> 

     </bibliodiv> 
   </bibliography> 
</article>

