Unix Par La Pratique

Embed Size (px)

Citation preview

  • 8/8/2019 Unix Par La Pratique

    1/16

    C h r i s t o p h e B l a e s s

    Shells

    Linux et Unixpar la pratique

    Groupe Eyrolles, 2008, ISBN : 978-2-212-12273-2

  • 8/8/2019 Unix Par La Pratique

    2/16

    2

    Programmation Shell

    Avant dentamer la programmation sous shell, rappelons la syntaxe lmentaire qui estutilise pour lancer des processus depuis la ligne de commande sous Unix et Linux,puisque nous emploierons galement ces symboles dans les scripts.

    Nous tendrons ces possibilits ultrieurement, mais ces lments seront dj suffisantspour comprendre les premiers scripts tudis.

    Saisie Signification

    commande La commande est excute normalement ; le symbole dinvite sera affich lorsquelle

    se terminera.commande & La commande est excute en arrire-plan, ce qui signifie quelle na en principe

    pas accs au terminal. Le shell reprend donc la main immdiatement, et affiche

    son symbole dinvite alors que la commande continue sexcuter en tche de

    fond. Le shell affiche une ligne du type

    [1] 2496

    indiquant le numro du job larrire-plan, suivi du PID (lidentifiant de processus).

    Lorsque la commande se termine, le shell affichera une ligne

    [1]+ Done commande

    juste avant de proposer un nouveau symbole dinvite.commande > fichier La commande est excute, mais sa sortie standard est dirige vers le fichier

    indiqu. Seule la sortie derreur saffiche lcran.

    commande >> fichier La sortie standard est ajoute en fin de fichier sans en craser le contenu.

    commande < fichier La commande est excute, mais ses informations dentre seront lues depuis lefichier qui est indiqu plutt que depuis le terminal.

    cmmnd_1 | cmmnd_2 Les deux commandes sont excutes simultanment, lentre standard de laseconde tant connecte par un tube (pipe) la sortie standard de la premire.

  • 8/8/2019 Unix Par La Pratique

    3/16

    Shells Linux et Unix par la pratique14

    Premier aperu

    Avant dentrer dans le dtail de la syntaxe et des commandes pour le shell, nous allonstout dabord survoler un script complet, afin de nous familiariser avec la structure desprogrammes shell. Ce script, dj assez important pour un premier exemple, est unevariation sur un article que javais crit en mai 1996 pour le journal la ligne LinuxGazette, [Blaess 1996].

    Premier script, rm_secure

    Lide est de remplacer la commande rm normale (suppression de fichiers et de rper-toires) par un script qui permette de rcuprer les fichiers effacs malencontreusement.Il en existe des implmentations plus performantes, mais lavantage de ce script estdtre assez simple, facile installer et tudier. Nous allons lanalyser en dtail, dansson intgralit. Des numros ont t ajouts en dbut de ligne pour rfrence, mais ils nefont videmment pas partie du script.

    rm_secure.sh :

    1 sauvegarde_rm=~/.rm_saved/23 function rm4 {5 local opt_force=06 local opt_interactive=07 local opt_recursive=08 local opt_verbose=09 local opt_empty=0

    10 local opt_list=011 local opt_restore=012 local opt1314 OPTERR=015 # Analyse des arguments de la ligne de commande16 while getopts ":dfirRvels-:" opt ; do17 case $opt in18 d ) ;; # ignore19 f ) opt_force=1 ;;20 i ) opt_interactive=1 ;;21 r | R ) opt_recursive=1 ;;22 e ) opt_empty=1 ;;23 l ) opt_list=1 ;;24 s ) opt_restore=1 ;;25 v ) opt_verbose=1 ;;26 - ) case $OPTARG in27 directory ) ;;28 force) opt_force=1 ;;29 interactive ) opt_interactive=1 ;;30 recursive ) opt_recursive=1 ;;31 verbose ) opt_verbose=1 ;;

  • 8/8/2019 Unix Par La Pratique

    4/16

    Programmation Shell

    CHAPITRE215

    32 help ) /bin/rm --help33 echo "rm_secure:"34 echo " -e --empty vider la corbeille"35 echo " -l --list voir les fichiers sauvs"36 echo " -s, --restore rcuprer des fichiers"37 return 0 ;;38 version ) /bin/rm --version39 echo "(rm_secure 1.2)"40 return 0 ;;41 empty ) opt_empty=1 ;;42 list ) opt_list=1 ;;

    43 restore ) opt_restore=1 ;;44 * ) echo "option illgale --$OPTARG"45 return 1;;46 esac ;;47 ? ) echo "option illgale -$OPTARG"48 return 1;;49 esac50 done51 shift $(($OPTIND - 1))

    5253 # Crer ventuellement le rpertoire54 if [ ! -d "$sauvegarde_rm" ] ; then55 mkdir "$sauvegarde_rm"56 fi5758 # Vider la poubelle59 if [ $opt_empty -ne 0 ] ; then60 /bin/rm -rf "$sauvegarde_rm"

    61 return 062 fi6364 # Liste des fichiers sauvs65 if [ $opt_list -ne 0 ] ; then66 ( cd "$sauvegarde_rm"67 ls -lRa * )68 fi6970 # Rcupration de fichiers71 if [ $opt_restore -ne 0 ] ; then72 while [ -n "$1" ] ; do73 mv "${sauvegarde_rm}/$1" .74 shift75 done76 return77 fi7879 # Suppression de fichiers

    80 while [ -n "$1" ] ; do81 # Suppression interactive : interroger l'utilisateur82 if [ $opt_force -ne 1 ] && [ $opt_interactive -ne 0 ]

    then

  • 8/8/2019 Unix Par La Pratique

    5/16

    Shells Linux et Unix par la pratique16

    83 local reponse84 echo -n "Dtruire $1 ? "

    85 read reponse86 if [ "$reponse" != "y" ] && [ "$reponse" != "Y" ] &&87 [ "$reponse" != "o" ] && [ "$reponse" != "O" ] ; then88 shift89 continue90 fi91 fi92 if [ -d "$1" ] && [ $opt_recursive -eq 0 ] ; then93 # Les rpertoires ncessitent l'option rcursive

    94 shift95 continue96 fi97 if [ $opt_verbose -ne 0 ] ; then98 echo "Suppression $1"99 fi

    100 mv -f "$1" "${sauvegarde_rm}/"101 shift102 done

    103 }104105 trap "/bin/rm -rf $sauvegarde_rm" EXIT

    Lanalyse dtaille du script est un peu laborieuse, mais il est nettement prfrabledtudier un programme rel, complet et utilisable, quun exemple simpliste, construituniquement pour illustrer les possibilits du shell. Si certaines parties semblent obscures,il ny a pas lieu de sinquiter : nous y reviendrons dans la prsentation des commandeset de la syntaxe.

    Analyse dtaille

    Exceptionnellement, ce script ne dbute pas par une ligne shebang introduite par #!. Eneffet, il nest pas conu pour tre excut dans un processus indpendant avec unecommande comme ./rm_secure.sh, mais pour tre lu par une commande source ou .depuis un fichier dinitialisation du shell (comme ~/.profile ou ~/.bashrc).

    Lorsquun script est appel ainsi . script , il est interprt directement par le shell encours dexcution, sans lancer de nouvelle instance. Aussi les variables et fonctions dfi-nies par ce script seront-elles disponibles mme aprs sa terminaison. Il ne faut pasconfondre le point utilis ici pour sourcer un script, et le point reprsentant le rper-toire courant dans lappel ./script.

    Ce script dfinit une fonction nomme rm, stendant des lignes 3 103. Le programmetant lu et interprt directement par le shell, et non par un processus fils, cette fonctionsera disponible dans lenvironnement du shell qui vient de sinitialiser.

    Lorsquon appelle, depuis la ligne de saisie, un nom de commande comme rm, le shell vadabord contrler sil existe dans son environnement une fonction qui a ce nom. Sil nen

  • 8/8/2019 Unix Par La Pratique

    6/16

    Programmation Shell

    CHAPITRE217

    trouve pas, il vrifiera sil sagit de lune de ses commandes internes (comme cd). Endernier ressort, il parcourra lensemble des rpertoires mentionns dans la variabledenvironnement PATH la recherche dun fichier excutable qui ait le nom indiqu. Natu-rellement, si la commande contient un chemin daccs (par exemple /bin/rm), il vite toutce mcanisme et lance directement le fichier dsir.

    Dans notre cas, nous dfinissons une fonction ayant pour nom rm, qui sera donc invoque la place du fichier /bin/rm habituel.

    La premire ligne du script dfinit une variable qui contient le nom dun rpertoire vers

    lequel les fichiers seront dplacs plutt que vritablement effacs. Des options la lignede commande nous permettront dexaminer le contenu du rpertoire et de rcuprer desfichiers. Il est vident que lutilisateur doit avoir un droit dcriture sur ce rpertoire. Laconfiguration la plus intuitive consiste utiliser un rpertoire qui figure dj dans lerpertoire personnel de lutilisateur et de lui donner un nom qui commence par un pointafin dviter de le retrouver chaque invocation de ls.

    Nous voyons que laffectation dune variable se fait, avec le shell, simplement laide

    dune commande nom=valeur. Il est important de noter quil ne doit pas y avoir despaceautour du signe gal.

    Vient ensuite la dclaration de la fonction. On emploie le mot-cl function suivi du nomde la routine, puis de son corps encadr par des accolades. Les lignes 5 12 dclarent desvariables locales de la fonction. Ces variables serviront noter, lors de lanalyse de laligne de commande, les diffrentes options indiques par lutilisateur. Les dclarationssont ici prcdes du mot-cl local, qui permet de ne les rendre visibles que dans notrefonction. Quand une fonction est, comme ici, destine rester durablement dans lammoire du shell, il est important de ne pas polluer lenvironnement en laissant inuti-lement des variables apparatre en dehors de la routine o elles sont employes.

    Notre fonction rm accepte les mmes options la ligne de commande que la commande /bin/rm, et en ajoute trois nouvelles :

    Option Signification Provenance

    -d ou --directory Ignore /bin/rm

    -f ou --force Ne pas interroger lutilisateur /bin/rm

    -i ou --interactive Interroger lutilisateur avant de supprimer un fichier /bin/rm

    -r, -R, ou --recursive Supprimer dune faon rcursive les rpertoires /bin/rm

    -v ou --verbose Afficher les noms des fichiers avant de les supprimer /bin/rm

    --help Afficher une page daide /bin/rm

    --version Afficher le numro de version du programme /bin/rm

    -e ou --empty Vider la corbeille de sauvegarde rm_secure

    -l ou --list Voir le contenu de la corbeille rm_secure

    -s ou --restore Rcuprer un fichier dans la corbeille rm_secure

  • 8/8/2019 Unix Par La Pratique

    7/16

    Shells Linux et Unix par la pratique18

    Avant de lire les arguments de la ligne de commande, nous devons initialiser une variablesystme nomme OPTIND, ce qui a lieu la ligne 14. Le rle de cette variable sera dtaillplus bas.

    La ligne 16 introduit une boucle while. Voici la syntaxe de ce type de boucle :

    while conditiondo

    corps de la boucle...done

    Les instructions contenues dans le corps de la boucle sont rptes tant que la conditionindique est vraie. Afin de rendre lcriture un peu plus compacte, il est frquent deremplacer le saut de ligne qui se trouve aprs la condition par un caractre point-virgule,qui, en programmation shell, signifie fin dinstruction . La boucle est donc gnralementcrite ainsi :

    while condition ; do

    corps de la boucledone

    Une erreur frquente chez les dbutants est de tenter de placer le point-virgule l o ilparat visuellement le plus naturel pour un programmeur C ou Pascal : en fin de ligne.Sa position correcte est pourtant bien avant le do !

    Ici, la condition est exprime par une commande interne du shell :

    getopts ":dfirRvels-:" opt

    La commande getopts permet danalyser les arguments qui se trouvent sur la ligne de

    commande. Nous lui fournissons une chane de caractres qui contient les lettres attri-bues aux options (comme dans le tableau de la page prcdente), et le nom dune variablequelle devra remplir. Cette fonction renvoie une valeur vraie tant quelle trouve uneoption qui est contenue dans la liste, et place le caractre dans la variable opt. Nousdtaillerons ultrieurement le fonctionnement de cette routine, et la signification desdeux-points prsents dans cette chane. Retenons simplement quarrivs la ligne 17,nous savons que lun des caractres inscrits dans la chane est prsent dans la variable opt.

    Sur cette ligne 17, nous trouvons une structure de slection case qui va nous permettre dedistribuer le contrle du programme en fonction du contenu dune variable. Sa syntaxeest la suivante :

    case expression invaleur_1 )

    action_1 ;;valeur_2 )

    action_2 ;;esac

    La valeur renvoye par lexpression, ici le contenu de la variable opt, est comparesuccessivement aux valeurs proposes jusqu ce quil en soit trouv une qui lui corres-ponde, et laction associe est alors excute. Les diffrents cas sont spars par deux

  • 8/8/2019 Unix Par La Pratique

    8/16

    Programmation Shell

    CHAPITRE219

    points-virgules. Pour le dernier cas, toutefois, ce signe de ponctuation est facultatif, maisil est recommand de lemployer quand mme, afin dviter des problmes ultrieurs siun nouveau cas doit tre ajout. Le mot-cl esac (case lenvers), que lon trouve laligne 49, sert marquer la fin de cette structure de slection.

    Nous remarquons au passage que, ligne 17, nous lisons pour la premire fois le contenudune variable. Cela seffectue en prfixant son nom par un caractre $. Ainsi, nous nousrfrons au contenu de la variable opt en crivant $opt. Il faut bien comprendre ds prsent que le nom rel de la variable est bien opt ; le $ est un oprateur demandantdaccder son contenu. Nous verrons plus avant des formes plus gnrales de cet oprateur.

    Les valeurs auxquelles lexpression est compare dans les diffrentes branches de lastructure case ne sont pas limites de simples valeurs entires, comme peuvent y trehabitus les utilisateurs du langage C, mais peuvent reprsenter des chanes de caractrescompltes, incorporant des caractres gnriques comme lastrisque *. Ici, nous nouslimiterons employer le caractre | qui reprsente un OUlogique, la ligne 21. Ainsilaction

    opt_recursive=1

    est excute si le caractre contenu dans opt est un r ou un R.

    Nous observons que les lignes 19 25 servent remplir les variables qui reprsentent lesoptions en fonction des caractres rencontrs par getopts.

    Un cas intressant se prsente la ligne 26, puisque nous avons rencontr un caractredoption constitu par un tiret. Cela signifie que loption commence par -- . Dans lachane de caractres que nous avons transmise getopts la ligne 16, nous avons fait

    suivre le tiret dun deux-points. Cela indique la commande getopts que nous attendonsun argument loption - . Il sagit dune astuce pour traiter les options longuescomme --help. Lorsque getopts rencontre loption - , il place largument qui la suit(par exemple help) dans la variable OPTARG. Nous pouvons donc reprendre une structurede slection case pour examiner le contenu de cette variable, ce qui est fait de la ligne 26 la ligne 46 o se trouve le esac correspondant.

    Les options longues, directory, force, interactive, verbose, recursive, empty, list,

    restore, sont traites comme leurs homologues courtes, dcrites dans le tableau prc-dent. Aussi les options help et version commencent par invoquer la vritable commanderm afin quelle affiche ses propres informations, avant dcrire leurs messages laide de lacommande echo. On remarquera que ces deux cas se terminent par une commandereturn 0, ce qui provoque la fin de la fonction rm, et renvoie un code de retour nulindiquant que tout sest bien pass.

    Le motif mis en comparaison sur la ligne 44, un simple astrisque, peut correspondre nimporte quelle chane de caractres selon les critres du shell. Ce motif sert donc absor-

    ber toutes les saisies non valides dans les options longues. Nous affichons dans ce cas unmessage derreur au moyen de la commande :

    echo "option illgale --$OPTARG"

  • 8/8/2019 Unix Par La Pratique

    9/16

    Shells Linux et Unix par la pratique20

    Nous remarquons quau sein de la chane de caractres encadre par des guillemets,loprateur $ agit toujours, et remplace OPTARG par son contenu, cest--dire le texte deloption longue errone. En ce cas, nous invoquons la commande return avec unargument 1, ce qui signifie conventionnellement quune erreur sest produite.

    la ligne 47, nous revenons la premire structure de distribution case-esac. Nousavions mis la ligne 16 un deux-points en premire position de la chane doptions trans-mise getopts. Cela permet de configurer le comportement de cette commandelorsquelle rencontre une lettre doption non valide. Dans ce cas, elle met le caractre ?dans la variable indique, opt en loccurrence, stocke la lettre non valide dans la variable

    OPTARG, et naffiche aucun message derreur. Notre dernier cas, sur la ligne 47, sert donc afficher un message derreur, et arrter la fonction avec un code dchec.

    Aprs clture avec esac et done de la lecture des options, il nous reste traiter les autresarguments qui se trouvent sur la ligne de commande, ceux qui ne sont pas des options,cest--dire les noms de fichiers ou de rpertoires quil faut supprimer ou rcuprer.

    Lorsquun script (ou une fonction) est invoqu, les arguments lui sont transmis dans desvariables spciales. Ces variables, accessibles uniquement en lecture, sont reprsentes

    par le numro de largument sur la ligne de commande. Ainsi, $1 renvoie la valeur dupremier argument, $2 celle du deuxime, et ainsi de suite. Nous verrons ultrieurementquil existe aussi des variables spciales, accessibles avec $0, $#, $* et $@, qui aident manipuler ces arguments.

    La boucle while autour de getopts a parcouru toutes les options qui se trouvent en dbut deligne de commande, puis elle se termine ds que getopts rencontre un argument qui necommence pas par un tiret. Avant danalyser un argument, getopts stocke son indice dansla variable OPTIND, que nous avions initialise zro la ligne 14. Si les n premiers argu-ments de la ligne de commande sont des options valides, en sortie de la boucle while, la varia-ble OPTIND vaut n+1. Il est donc prsent ncessaire de sauter les OPTIND-1 premiers argumentspour passer aux noms de fichiers ou de rpertoires. Cest ce qui est ralis sur la ligne 51 :

    shift $(($OPTIND - 1))

    La construction $(( )) encadre une expression arithmtique que le shell doit interprter.Ici, il sagit donc simplement du nombre darguments liminer, soit $OPTIND-1. Lacommande shift n dcale les arguments en supprimant les n premiers.

    Nous allons entrer prsent dans le vif du sujet, avec les fonctionnalits vritables duscript. Toutefois, nous allons auparavant crer le rpertoire de sauvegarde, sil nexistepas encore. Cela nous vitera de devoir vrifier sa prsence plusieurs reprises dans lereste du programme. Nous voyons donc apparatre sur les lignes 54 56 une nouvellestructure de contrle, le test if-then-else. Sa syntaxe est la suivante :

    if conditionthen

    actionelse

    autre actionfi

  • 8/8/2019 Unix Par La Pratique

    10/16

  • 8/8/2019 Unix Par La Pratique

    11/16

    Shells Linux et Unix par la pratique22

    Le test [ xxx -ne yyy ] est une comparaison arithmtique entre xxx et yyy. Il renvoie unevaleur vraie si les deux lments sont diffrents (not equal). En dautres termes, ceslignes signifient :

    si la variable reprsentant loption empty nest pas nulle, alors

    effacer le rpertoire de sauvegarde

    quitter la fonction en indiquant une russite

    fin

    La deuxime option que nous traitons est la demande daffichage du contenu de la

    corbeille. Pour ce faire, nous employons les lignes 66 et 67 :( cd "$sauvegarde_rm"ls -lRa * )

    Elles correspondent un dplacement vers le rpertoire de sauvegarde, et un affichagercursif de son contenu et de celui des sous-rpertoires. Nous avons encadr ces deuxlignes par des parenthses. On demande ainsi au shell de les excuter dans un sous-shellindpendant, ce qui prsente lavantage de ne pas modifier le rpertoire de travail du shell

    principal. Un nouveau processus est donc cr, et seul le rpertoire de travail de ceprocessus est modifi.

    Loption traite ensuite est la rcupration de fichiers ou de rpertoires effacs. Uneboucle stend des lignes 72 75 :

    while [ -n "$1" ] ; domv "${sauvegarde_rm}/$1" .shift

    done

    Le test [ -n "$1" ] vrifie si la longueur de la chane "$1" est non nulle. Ce test russitdonc tant quil reste au moins un argument traiter. Linstruction shift que lon trouvesur la ligne 74 sert liminer largument que lon vient de traiter. Cette boucle permetainsi de balayer tous les noms de fichiers ou de rpertoires un par un. La ligne 73 essaiede rcuprer dans le rpertoire sauvegarde_rm un ventuel fichier sauvegard, en le dpla-ant vers le rpertoire courant. Remarquons quil est tout fait possible, avec cette mmecommande, de rcuprer des arborescences compltes, y compris les sous-rpertoires.

    La portion du programme qui soccupe des suppressions se situe entre les lignes 80et 102. Elle est construite au sein dune boucle while-do qui balaie les noms des fichierset des rpertoires indiqus sur la ligne de commande.

    Une premire tape consiste interroger lutilisateur si loption interactive a t rcla-me, et si loption force ne la pas t. Nous voyons au passage comment deux condi-tions peuvent tre regroupes par unETlogique au sein dun test. Nous reviendrons surce mcanisme ultrieurement.

    Aprs dclaration dune variable locale, et affichage dun message dinterrogation (avecloption -n de echo pour viter daller la ligne), le script invoque la commande shellread. Cette dernire lit une ligne et la place dans la variable indique en argument.

  • 8/8/2019 Unix Par La Pratique

    12/16

    Programmation Shell

    CHAPITRE223

    Nous comparons alors cette rponse avec quatre chanes possibles : y, Y, o, et O. Lopra-teur de comparaison des chanes est =, et son inverse est !=. Si la rponse ne correspond aucune de ces possibilits, nous invoquons dabord shift, pour dcaler les arguments,puis la commande continue qui nous permet de revenir au dbut de la boucle while. Lesarguments pour lesquels lutilisateur na pas rpondu par laffirmative sont ainsi oublis .

    La deuxime vrification concerne les rpertoires. Ceux-ci, en effet, ne peuvent tre effa-cs quavec loption recursive. Si le test de la ligne 92 choue, largument est ignor eton passe au suivant.

    Si on a rclam un comportement volubile du programme (option -v ou --verbose), onaffiche le nom du fichier ou du rpertoire trait avant de poursuivre. Puis, les lignes 100et 101 dplacent effectivement le fichier, et passent largument suivant.

    La fonction qui remplace la commande rm est donc prsent crite. Lorsque le script estexcut laide de linstruction source ou de . , il place cette fonction dans lammoire du shell ; elle est prte tre invoque la place de rm. Il demeure toutefois unedernire ligne apparemment mystrieuse :

    trap "/bin/rm -rf $sauvegarde_rm" EXIT

    Cette ligne est excute directement par le shell lorsque nous appelons notre script. Lacommande trap permet dassurer une gestion minimale des signaux. Voici sa syntaxegnrale :

    trap commande signal

    Lorsque le shell recevra le signal indiqu, il droutera son excution pour raliser imm-

    diatement la commande passe en argument. Les signaux permettent une communicationentre processus, et surtout une prise en compte asynchrone des vnements quun logi-ciel peut tre amen rencontrer (interruption dune ligne de communication, fin dunetemporisation, dpassement dune limite doccupation du disque, etc.). Nous reviendronsplus en dtail sur la gestion des signaux ultrieurement. Ici, la commande trap nous sert intercepter un pseudo-signal simul par le shell. En effet, avant que le shell ne setermine, il simule lmission dun signal nomm EXIT. La commande passe en argumentest donc excute juste avant de refermer une session de travail. Elle sert effacer le

    rpertoire de sauvegarde.Cette ligne est bien entendu optionnelle, mais je conseille de la conserver, car elle vite lutilisateur de devoir vider explicitement sa corbeille (manuellement ou dune manireprogramme laide de la crontab).

    Performances

    Lutilitaire rm_secure na pas pour objet de fournir une rcupration des fichiers sur dulong terme. Ce rle est dvolu aux mcanismes de sauvegarde priodique du systme. Enfait, rm_secure est conu comme une sorte de commande Contrle-Zoudition/Annulerqui permet de corriger immdiatement une erreur de frappe ayant entran la destruction

  • 8/8/2019 Unix Par La Pratique

    13/16

    Shells Linux et Unix par la pratique24

    involontaire dun fichier. En tenant compte de ses spcificits, chacun est toujours librede modifier le script sa convenance pour ladapter un cas particulier.

    Il faut aussi tre conscient que, dans un environnement graphique X Window, oplusieurs fentres xterm sont utilises simultanment, ds que lon ferme lune dentreelles, la commande deffacement est invoque, dtruisant le rpertoire de sauvegardecommun toutes les fentres. Si ce point pose un problme, il est malgr tout possible decrer un rpertoire de sauvegarde pour chaque instance indpendante du shell. On obtientcela en ajoutant au nom du rpertoire un suffixe qui reprsente le PID du shell, enremplaant la premire ligne du script par :

    sauvegarde_rm=~/.rm_saved_$$/

    Un tel script a pour vocation de rester le plus discret possible vis--vis de lutilisateur.Idalement, on ne devrait se souvenir de sa prsence que le jour o un fichier vient dtreeffac maladroitement. Il faut donc viter de ralentir le fonctionnement de la commanderm originale. cet effet, nous avons fait le choix de dplacer les fichiers avec mv pluttque de les copier avec cp, ou des les archiver avec tar. Lorsque le fichier quil faut suppri-mer se trouve sur le mme systme de fichiers que le rpertoire de sauvegarde, la

    commande mv agit instantanment, car elle ne doit modifier que le nom du fichier danslarborescence, et pas son contenu. Il sagit du cas le plus courant pour les utilisateursnormaux, dont les rpertoires personnels et tous les descendants se trouvent gnrale-ment sur la mme partition. Pour root, en revanche, la situation est autre, car ce dernierdoit souvent intervenir sur des rpertoires qui se trouvent sur des partitions diffrentes.La commande mv ne peut plus simplement dplacer le fichier, mais est oblige de lecopier, puis de supprimer loriginal. Dans ce cas, notre script induit un ralentissementsensible, notamment lorsquon agit sur des hirarchies compltes (par exemple, en

    supprimant toute larborescence des sources dun programme) ou sur des fichiers volu-mineux (core, par exemple). On peut choisir de dsactiver lemploi de rm_secure pourroot, en partant du principe que toute action entreprise sous ce compte est potentiellementdangereuse, et ncessite une attention accrue tout moment.

    Idalement, la connexion rootsur un systme Unix ou Linux qui compte peu dutilisa-teurs devrait tre rserve linstallation ou la suppression de paquetages logiciels, lajout dutilisateur et ldition de fichiers de configuration (connexion distante, adres-sage rseau). Dans tous ces cas, on nintervient que sur des fichiers dont une copieexiste ailleurs (CD, bande de sauvegarde, Internet). Thoriquement, rootne devraitjamais se dplacer et encore moins toucher aux fichiers dans les rpertoires person-nels des utilisateurs o lon trouve des donnes nexistant quen un seul exemplaire(fichiers source, textes, e-mail). Thoriquement

    Exemple dexcution

    Voici, en conclusion de ce survol dun script pour shell, un exemple dutilisation. Noussupposons que les fichiers dinitialisation (~/.profile ou ~/.bashrc), excuts lors dudmarrage des sessions interactives du shell, contiennent une ligne qui permette dinvo-quer le script, la manire de . ~/bin/rm_secure.sh. Nous considrons donc que la

  • 8/8/2019 Unix Par La Pratique

    14/16

    Programmation Shell

    CHAPITRE225

    fonction rm dfinie prcdemment est prsente dans lenvironnement, et a prsance surle fichier excutable /bin/rm.

    Je souhaite ne supprimer que le fichier de sauvegarde, et jappelle donc rm *.bak pourviter de saisir son nom en entier. Hlas, jintroduis par erreur un caractre espace aprslastrisque.

    Ae ! Il ne me reste plus qu compter sur laide de notre script. Commenons par nousremmorer ses options :

    $ ls

    rm_secure.sh rm_secure.sh.bak

    $ rm * .bak

    mv:.bak.: Aucun fichier ou rpertoire de ce type

    $ ls

    $

    $ rm --help

    Usage: /bin/rm [OPTION]... FICHIER...

    Enlever (unlink) les FICHIER(s).

    -d, --directory enlever le rpertoire, mme si non vide

    (usager root seulement)

    -f, --force ignorer les fichiers inexistants,

    ne pas demander de confirmation

    -i, --interactive demander confirmation avant destruction

    -r, -R, --recursive enlever les rpertoires rcursivement

    -v, --verbose en mode bavard expliquer ce qui est fait

    --help afficher l'aide-mmoire

    --version afficher le nom et la version du logiciel

    Rapporter toutes anomalies .

    rm_secure:

    -e --empty vider la corbeille

    -l --list voir les fichiers sauvs

    -s, --restore rcuprer des fichiers

    $ rm -l

    -rwxr-xr-x cpb/cpb 2266 2007-09-01 19:39:14 rm_secure.sh

    -rwxr-xr-x cpb/cpb 2266 2007-09-01 19:39:14 rm_secure.sh.bak

    $ rm --restore rm_secure.sh$ ls

    rm_secure.sh

  • 8/8/2019 Unix Par La Pratique

    15/16

    Shells Linux et Unix par la pratique26

    Ouf ! Le fichier est rcupr. Vrifions maintenant que le rpertoire de sauvegarde estbien vid automatiquement lors de la dconnexion :

    Essayons de voir sil reste des fichiers aprs une nouvelle connexion :

    Ce dernier message nest peut-tre pas trs heureux. Nous laisserons au lecteur le soindencadrer lappel ls de la ligne 67 par un test if-then-fi qui affiche un message plus

    appropri si la commande ls signale une erreur (ne pas oublier de rediriger la sortiederreur standard de cette dernire commande vers /dev/null pour la dissimuler).

    Conclusion

    Avec ce chapitre dintroduction la programmation shell, nous avons pu observer lastructure des scripts, que nous pourrons tudier plus en dtail par la suite.

    On peut remarquer la concision de ce langage, qui permet de raliser une tche djrespectable en une centaine de lignes de programmation. Et ce, en raison du niveaudabstraction lev des commandes employes. Par exemple, la suppression rcursivedun rpertoire, comme nous lavons vu dans la dernire ligne du script, demanderait aumoins une vingtaine de lignes de programmation en C.

    Les chapitres venir vont nous permettre dtudier la programmation shell dunemanire plus formelle, et plus complte.

    Exercices

    2.1 Appel dun script par source (facile)

    Crez un script qui initialise une nouvelle variable avec une valeur arbitraire, puis affiche cettevariable.

    Lancez le script (aprs lavoir rendu excutable avec chmod) comme nous lavons fait dans le

    chapitre 1. Une fois lexcution termine, essayez dafficher le contenu de la variable :initialise_et_affiche.sh

    #! /bin/sh

    $ rm --list

    -rwxr-xr-x cpb/cpb 2266 2007-09-01 19:39:14 rm_secure.sh.bak

    $ exit

    $ rm --list

    ls: *: Aucun fichier ou rpertoire de ce type

    $

  • 8/8/2019 Unix Par La Pratique

    16/16