Support N°4 : Le shell et les commandes Gnu (suite)
Transcription
Support N°4 : Le shell et les commandes Gnu (suite)
Le système d'exploitation Debian/Gnu Linux C. HEMDANI Support N°4 : Le shell et les commandes Gnu (suite) Table des matières 1 Les processus 1 1.1 Dénition et environnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 États d'un processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Lancement en tâche de fond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.4 Backgroung, foreground, jobs 2 1.5 Liste des processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.6 Les signaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.7 nohup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.8 nice et renice 1.9 time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2 Alias, groupement et liaison de commandes 5 2.1 Alias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Groupement de commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3 Liaison et exécution conditionnelle 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Les variables 5 6 3.1 Nomenclature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.2 Déclaration et aectation 6 3.3 Accès et achage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.4 Suppression et protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.5 Export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.6 Accolades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3.7 Variables système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3.8 Variables spéciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.9 Longueur d'une chaîne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.10 Tableaux et champs 3.11 Variables typées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 4 Conguration de bash 4.1 10 Fichiers de conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Shell de connexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.1.2 Shell simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.1.3 Mode non interactif 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Structure et exécution d'un script 5.1 10 11 Arguments d'un script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5.1.1 Paramètres de position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5.1.2 Redénition des paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.1.3 Réorganisation des paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.1.4 Sortie d'un script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.2 Environnement du processus 5.3 Substitution de commande 5.4 Tests de conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Tests sur une chaîne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 Tests sur les valeurs numériques 5.4.3 Tests sur les chiers 14 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.4.4 Tests combinés par des critères ET, OU et NON 5.4.5 Syntaxe allégée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5 if ... then ... else ... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.6 Choix multiples : case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.7 Saisie de l'utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.8 Les boucles 5.9 . . . . . . . . . . . . . . . . . . . . . . 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.8.1 Boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.8.2 Boucle while 19 5.8.3 Boucle until . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.8.4 true et false . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.8.5 break et continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.10 Calculs et expressions 19 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 5.10.1 expr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 5.10.2 Calculs avec bash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.11 Une variable dans une autre variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.12 Traitement des signaux 22 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le système d'exploitation Debian/Gnu Linux C. HEMDANI Support N°4 : Le shell et les commandes Gnu (suite) 1 Les processus 1.1 Dénition et environnement Un processus représente à la fois un programme en cours d'exécution et tout son environnement d'exécution (mémoire, état, identication, propriétaire, père...). Voici une liste des données d'identication d'un processus : Un numéro de processus unique PID (Process ID ) : chaque processus Unix est numéroté an de pouvoir être diérencié des autres. Le premier processus lancé par le système a le processus appelé systemd (init dans les anciennes versions). On utilise le un processus. Lancer 10 fois le même programme produit 10 PID PID PID 1 et il s'agit d'un quand on travaille avec diérents. Un numéro de processus parent PPID (Parent Process ID ) : chaque processus peut lui-même lancer d'autres processus, des processus enfants (child le PID process ). Chaque enfant reçoit parmi les informations, du processus père qui l'a lancé. Tous les processus ont un PPID sauf le processus 0 qui est un pseudo-processus représentant le démarrage du système et qui sera l'ancêtre de tous les processus. Un numéro d'utilisateur et un numéro de groupe : ils correspondent à l'UID et au GID de l'utilisateur qui a lancé le processus. C'est nécessaire pour que le système sache si le processus a le droit d'accéder à certaines ressources ou non. Les processus enfants héritent de ces informations. Durée de traitement et priorité : la durée de traitement correspond au temps d'exécution écoulé depuis le dernier réveil du processus. Dans un environnement multitâche, le temps d'exécution est partagé entre les divers processus, et tous ne possèdent pas la même priorité. Les processus de plus haute priorité sont traités en premier. Lorsqu'un processus est inactif, sa priorité augmente an d'avoir une chance d'être exécuté. Lorsqu'il est actif, sa priorité baisse an de laisser sa place à un autre. C'est l'ordonnanceur de tâches du système qui gère les priorités et les temps d'exécution. Répertoire de travail actif : à son lancement, le répertoire courant (celui depuis lequel le processus a été lancé) est transmis au processus. C'est ce répertoire qui servira de base pour les chemins relatifs. Fichiers ouverts : table des descripteurs des chiers ouverts. Par défaut, au début, seuls trois sont présents : 0, 1 et 2 (les canaux standards). À chaque ouverture de chier ou de nouveau canal, la table se remplit. À la fermeture du processus, les descripteurs sont fermés. Autres informations : comme la taille de la mémoire allouée, la date de lancement du processus, le terminal d'attachement, l'état du processus, ... 1.2 États d'un processus Durant sa vie (temps entre le lancement et la sortie), un processus peut passer par divers états : exécution en mode utilisateur (user exécution en mode noyau (kernel en attente d'E/S (waiting ), mode ), mode ), endormi (sleeping ), prêt à l'exécution (runnable ), endormi dans le swap (mémoire virtuelle ), nouveau processus, n de processus (zombie ). 1.3 Lancement en tâche de fond Le shell peut autoriser la saisie d'une nouvelle commande sans attendre la n de l'exécution de la commande précédente. Pour cela il sut de saisir, après avoir tapé la commande, le caractère la commande lancée fonctionneront en parallèle. $ ls -R / > ls . txt & [1] 2835 $ [1] Done 1 &. Dans ce cas, le shell et Juste après la saisie, un nombre apparaît (2835 dans l'exemple), il est à retenir car il s'agit du nouveau processus lancé. Après une autre saisie, une ligne valeur [1] Done PID du indique que le traitement est terminé. La est propre au shell particulier (bash). Remarque 1 Le processus lancé en tâche de fond ne devrait pas attendre de saisie au risque de confusion entre cette commande et le shell lui-même, et ne devrait pas acher de résultats sur l'écran au risque d'avoir des achages en conit avec celui du shell (par exemple, l'apparition d'une ligne en milieu de saisie). Quand on quitte le shell, on quitte aussi tous ses ls : c'est pour cela qu'il ne faut pas quitter le shell pendant un traitement important. 1.4 Backgroung, foreground, jobs On peut récupérer la main sous le shell si on a lancé un processus au premier plan. On peut le stopper temporairement (le suspendre) en tapant $ sleep 100 ^Z [1]+ Stopped [Ctrl] Z : sleep 100 Le processus est stoppé : son exécution est suspendue jusqu'à ce qu'on le replace au premier plan avec la commande fg (foreground ) : $ fg sleep 100 sleep 100 Quand on lance une commande, le premier nombre entre crochets est le numéro de job. On peut obtenir la liste des jobs avec la commande jobs. $ sleep 40& [1] 2968 $ sleep 60& [2] 2969 $ jobs [1] - Running [2]+ Running $ fg 2 sleep 60 ^Z [2]+ Stopped $ bg 2 [2]+ sleep 60 & Les commandes commande bg sleep 40 & sleep 60 & sleep 60 bg et fg permettent d'agir sur ces jobs en prenant comme paramètre leur numéros. La est exécutée sur un job stoppé pour le relancer en arrière-plan (background ). 1.5 Liste des processus La commande ps (process status ) permet d'avoir des informations sur les processus en cours. Lancée seule, elle n'ache que les processus en cours lancés par l'utilisateur et depuis la console actuelle. $ ps PID TTY 2916 pts /2 3120 pts /2 TIME CMD 00:00:00 bash 00:00:00 ps Pour avoir plus d'informations, on utilise le paramètre $ ps -f UID etudiant etudiant PID PPID C STIME TTY 2916 2527 0 14:19 pts /2 3132 2916 0 14:34 pts /2 Le paramètre -e -f. TIME CMD 00:00:00 bash 00:00:00 ps -f donne des informations sur tous les processus en cours. 2 $ ps -e PID TTY 1 ? 2 ? 3 ? ... TIME 00:00:00 00:00:00 00:00:00 Le paramètre paramètre -g -u permet de préciser une liste d'un ou plusieurs utilisateurs séparés par une virgule. Le eectue la même chose mais pour les groupes, $ ps -u root PID TTY 1 ? 2 ? 3 ? ... TIME 00:00:00 00:00:00 00:00:00 -l Enn le paramètre $ F 0 0 ps -l S UID S 1000 R 1000 CMD systemd kthreadd ksoftirqd /0 PID 2916 3179 -t pour les terminaux et -p pour des PID précis. CMD systemd kthreadd ksoftirqd /0 propose plus d'informations techniques. PPID 2527 2916 C PRI 0 80 0 80 NI ADDR SZ WCHAN 0 - 1728 0 953 - TTY pts /2 pts /2 TIME CMD 00:00:00 bash 00:00:00 ps Le tableau suivant dénit quelque colonnes. Colonne Dénition UID PID PPID C STIME TTY TIME CMD S PRI NI User ID, numéro de l'utilisateur. Process ID, numéro du processus. Parent Process ID, numéro du processus père. Facteur de priorité, plus la valeur est grande plus la priorité est élevée. Heure de lancement du processus. Nom du terminal depuis lequel le processus a été lancé. Durée de traitement du processus. Commande exécutée. État du processus : S (sleeping), R (running), Z (zombie). Priorité du processus. Nice, incrément pour l'ordonnanceur. 1.6 Les signaux Lorsqu'un processus tourne en tâche de fond, il ne peut pas être arrêté par une quelconque combinaison de touches. Il peut être nécessaire de lui envoyer des signaux auxquels il pourra éventuellement réagir. Pour cela, il faut employer la commande kill. Contrairement à ce que son nom semble indiquer, le rôle de cette commande n'est pas forcément de détruire ou de terminer un processus, mais d'envoyer des signaux aux processus. kill [ - l ] - signal PID1 [ PID2 ...] Le signal est l'un des moyens de communication entre les processus. Lorsqu'on envoie un signal à un processus, celui-ci doit l'intercepter et réagir en conséquence. Certains signaux peuvent être ignorés, d'autres non. Ils sont numérotés et nommés. L'option $ kill -l 1) SIGHUP 6) SIGABRT ... 63) SIGRTMAX -1 2) SIGINT 7) SIGBUS -l permet d'obtenir la liste des signaux. 3) SIGQUIT 8) SIGFPE 4) SIGILL 9) SIGKILL 5) SIGTRAP 10) SIGUSR1 64) SIGRTMAX Les rôles des signaux les plus utilisés sont donnés dans le tableau suivant. Signal 1) 2) 3) 9) 15) SIGHUP SIGINT SIGQUIT SIGKILL SIGTERM Rôle Hang Up, est envoyé par le père à tous ses enfants lorsqu'il se termine. Intérruption du processus ([CTRL] C). Intérruption du processus avec génération d'un Core Dump (chier de débogage). Signal ne pouvant être ignoré et qui force le processus à nir 'brutalement'. Demande au processus de se terminer normalement. 3 Par défaut, la commande kill envoie le signal $ sleep 100& [1] 3379 $ kill 3379 $ [1]+ Complété $ sleep 100& [1] 3388 $ kill -9 3388 $ [1]+ Processus arrêté SIGTERM. sleep 100 sleep 100 1.7 nohup Quand le shell est quitté (exit, [Ctrl] D, ...), le signal 1 (SIGHUP) est envoyé aux enfants pour qu'ils se terminent aussi. Lorsqu'un traitement long est lancé en tâche de fond et que l'utilisateur veut quitter le shell, ce traitement sera alors arrêté et il faudra tout recommencer. Le moyen d'éviter cela est de lancer le processus avec la commande nohup. Dans ce cas, le processus lancé ne réagira plus au signal SIGHUP, pourra être quitté, la commande continuera son exécution. Par défaut les canaux de sortie et d'erreur standards sont redirigés vers un chier redirection est explicitement précisée. et donc le shell nohup.out, sauf si la $ nohup ls -R / & [1] 3430 $ nohup : les entrées sont ignorées et la sortie est ajoutée à nohup . out SIGCHLD à son père. Sauf cas prévu (le père se détache du ls), SIGHUP. Si le père se termine avant ses ls, ceux-ci deviennent des zombis : le signal SIGCHLD n'est pas reçu... Le processus ls est bien terminé, il est Quand un ls se termine, il envoie le signal le père doit obtenir autant de SIGCHLD qu'il a eu de ls ou émis de mort, il ne consomme aucune ressource. Il ne peut donc être tué (puisqu'il est mort) mais continue à occuper une entrée dans la table des processus. 1.8 nice et renice La commande nice permet de lancer une commande avec une priorité plus faible, an de permettre éven- tuellement à d'autres processus de tourner plus rapidement. nice [ - valeur ] commande [ arguments ] Une valeur positive causera une baisse de priorité et une valeur négative l'augmentera (si autorisé). La valeur doit être comprise entre $ nice -10 [1] 3488 $ ps -l F S UID 0 S 1000 0 R 1000 0 R 1000 PID, et 19. Plus la valeur est élevée, plus le traitement est ralenti. ls -R / > liste 2 >/ dev / null & PID 2916 3488 3489 La commande d'un -20 PPID C PRI 2527 0 80 2916 83 90 2916 0 80 renice NI 0 10 0 ADDR SZ - 1767 - 1548 953 fonctionne un peu comme nice WCHAN - TTY pts /2 pts /2 pts /2 TIME 00:00:00 00:00:02 00:00:00 CMD bash ls ps mais elle permet de modier la priorité en fonction d'un utilisateur ou d'un groupe de processus. renice [ - n ] priorité [[ - p ] PID ...] [[ - g ] PGID ...] [[ - u ] utilisateur ...] 0 La priorité doit être comprise entre et 19 -20 et 19. L'utilisateur standard ne peut utiliser que les valeurs entre permettant de baisser la priorité. Les paramètres sont interprétés comme des identiants de processus (PID), des identiants d'un groupe de processus (PGID) ou des noms d'utilisateurs. A titre d'exemple, la commande # renice +5 3495 -u etudiant root -p 437 changera la priorité des processus d'identiants utilisateurs etudiant et root. 3495 et 4 437, et celles de tous les processus appartenant aux 1.9 time La commande time mesure les durées d'exécution d'une commande, idéale pour connaître les temps de traitement. Elle retourne trois valeurs : real : durée totale d'exécution de la commande, user : durée du temps CPU nécessaire pour exécuter le programme, sys : durée du temps CPU nécessaire pour exécuter les appels système eectués au sein du programme. $ time ls -R ~ > liste real 0 m0 .031 s user 0 m0 .020 s sys 0 m0 .012 s 2 Alias, groupement et liaison de commandes 2.1 Alias Un alias est un raccourci d'une commande avec d'éventuels paramètres. Il se dénit avec la commande alias. Utilisée seule, elle liste les alias disponibles. $ alias alias ..= ' cd .. ' alias cd ..= ' cd .. ' alias l = ' ls -alF ' alias la = ' ls -la ' alias ll = ' ls -l ' alias rm = ' rm -i ' On peut créer ses propres alias comme par la commande suivante : $ alias deltree = ' rm -rf ' 2.2 Groupement de commandes On peut chaîner des commandes avec le caractère point-virgule ';' pour les faire exécuter en séquentiel. $ uname -a ; pwd ; ls -l uname -a est d'abord exécutée, puis pwd et en n ls -l. Dans l'exemple suivant : $ uname -a ; pwd ; ls -l > resultat . txt & seule la dernière commande est exécutée en tâche de fond et seul son résultat est redirigé dans le chier resultat.txt. Comment faire alors pour que chacune d'elle redirige sa sortie vers resultat.txt et s'exécute en tâche de fond ? Une solution serait : $ uname -a > resultat . txt & pwd >> resultat . txt & ls -l >> resultat . txt & [1] 3097 [2] 3098 [3] 3099 Cependant, trois processus sont lancés en tâches de fond et non pas un seul. De plus, si les commandes sont lancées séquentiellement, elles tournent toutes en parallèle et c'est la première nie qui écrira en premier dans le chier. La solution consiste en l'utilisation des parenthèses. $ ( uname -a ; pwd ; ls -l ) > resultat . txt & [1] 3112 Un seul processus est lancé en tache de fond. Toutes les commandes placées entre les parenthèses sont lancées par un sous-shell unique, qui va exécuter séquentiellement les commandes indiquées. Ainsi, la redirection concerne l'ensemble des commandes et rien n'empêche de lancer ce sous-shell en arrière-plan. Une seconde possibilité est l'utilisation des accolades { ... }. Dans ce cas, aucun sous-shell n'est exécuté, et si une commande interne (cd ou autre) est exécutée, elle concerne le shell actif. 5 $ { uname -a ; pwd ; ls -l ; } > resultat . txt Notons qu'il faut laisser un espace entre l'accolade ouvrante et la première commande, et qu'il faut placer un ';' entre la dernière commande et l'accolade fermante. 2.3 Liaison et exécution conditionnelle En plus du chaînage classique, les commandes peuvent être liées et exécutées de façon conditionnelle. La condition d'exécution d'une commande est la réussite ou non de la précédente. Une fois exécutée, chaque commande renvoie un code de retour, généralement peut récupérer cette valeur par la variable Les opérateurs && et || $?. 0 si tout s'est bien passé, 1 ou 2 en cas d'erreur. Le shell permettent d'eectuer une exécution conditionnelle. commande1 && commande2 commande1 || commande2 La commande située après La commande située après || && sera exécutée uniquement si la commande précédente a retourné 0 (réussite). ne sera exécutée que si la commande précédente a retourné autre chose que 0. $ cat document Ce document présente le système d ' exploitation Debian Gnu / Linux . $ grep " Debian " document > / dev / null && echo " Trouvé " || echo " Introuvable " Trouvé $ grep " RedHat " document > / dev / null && echo " Trouvé " || echo " Introuvable " Introuvable 3 Les variables On distingue trois types de variables : utilisateur, système et spéciales. Le principe est de pouvoir aecter un contenu à un nom de variable, généralement une chaîne de caractères ou des valeurs numériques. 3.1 Nomenclature Un nom de variable a le même modèle que les identicateurs du langage C. On convient, généralement, que les variables utilisateur soient en minuscules pour les diérencier des variables système (en majuscules). 3.2 Déclaration et aectation Une variable est déclarée dès qu'une valeur lui est aectée. L'aectation est réalisée avec le symbole =, sans espace avant ou après le signe. var=Bonjour 3.3 Accès et achage $ devant le nom de la variable. Quand le shell $, il tente d'interpréter le mot suivant comme étant une variable. Si elle existe, alors $nom_variable On accède au contenu d'une variable en plaçant le caractère rencontre le est remplacé par son contenu, ou par un texte vide dans le cas contraire. On parle aussi de référencement de variable. $ chemin =/ usr / include $ ls $chemin ... $ cd $chemin $ pwd / usr / include $ cd $chemin / linux $ pwd / usr / include / linux Pour acher la liste des variables, on utilise la commande variables système, nom et contenu. 6 env. Elle ache les variables utilisateur et les $ env XDG_VTNR =7 MATE_DESKTOP_SESSION_ID = this - is - deprecated XDG_SESSION_ID =1 SSH_AGENT_PID =1631 GPG_AGENT_INFO =/ run / user /1000/ keyring / gpg :0:1 TERM = xterm ... Une variable peut contenir des caractères spéciaux, le principal étant l'espace. L'exemple suivant ne fonctionne pas : $ s = Salut tout le monde bash : tout : commande introuvable Pour cela il faut soit verrouiller les caractères spéciaux par un \, soit les mettre entre guillemets ou apostrophes. $ s = Salut \ tout \ le monde $ s =" Salut tout le monde " $ s = ' Salut tout le monde ' # Solution lourde # Solution correcte # Solution correcte La principale diérence entre les guillemets et les apostrophes est l'interprétation des variables et des substitutions. Précisons aussi que " et ' se verrouillent mutuellement. $ d = debian $ u = ubuntu $ echo " La distribution $u est basée sur $d ." La distribution ubuntu est basée sur debian . $ echo ' La distribution $u est basée sur $d . ' La distribution $u est basée sur $d . $ echo ' La distribution " $u est basée sur $d ". ' La distribution " $u est basée sur $d ". 3.4 Suppression et protection unset. On protège une variable en écriture et contre sa readonly. Une variable en lecture seule, même vide, est gée. Il n'existe aucun On supprime une variable avec la commande suppression avec la commande moyen de la replacer en écriture ou de la supprimer, sauf en quittant le shell. $ d = debian $ u = ubuntu $ echo " La distribution $u est basée La distribution ubuntu est basée sur $ unset d $ echo " La distribution $u est basée La distribution ubuntu est basée sur $ readonly u $ u = Ubuntu bash : u : variable en lecture seule sur $d ." debian . sur $d ." . 3.5 Export Par défaut, une variable n'est accessible que depuis le shell où elle a été dénie. Dans l'exemple suivant, la variable d est déclarée sous l'invite du shell courant puis est achée par un script lancé depuis ce même shell. Ce dernier ne connaît pas la variable d : rien ne s'ache. $ $ $ $ d = debian echo ' echo " $d est une distribution Gnu / Linux ." ' > deb . sh chmod u + x deb . sh ./ deb . sh est une distribution Gnu / Linux . 7 La commande export permet d'exporter une variable de manière à ce que son contenu soit visible par les scripts et autres sous-shells. Les variables exportées peuvent être modiées dans le script, mais ces modications ne s'appliquent qu'au script ou au sous-shell. Dans l'exemple suivant, le script d deb.sh peut accéder à la variable exportée mais les modications restent locales au script. Une fois celui-ci terminé, la modication disparaît. $ d = debian $ export d $ echo 'd = gentoo ; echo " $d est une distribution Gnu / Linux ." ' >> deb . sh $ ./ deb . sh debian est une distribution Gnu / Linux . gentoo est une distribution Gnu / Linux . $ echo " $d est une distribution Gnu / Linux ." debian est une distribution Gnu / Linux . 3.6 Accolades Les accolades de base {} permettent d'identier liste. On peut vouloir contenant le nom de chier le nom d'une variable. Imaginons la variable copier le chier liste1 en liste2. fichier $ fichier = liste $ cp $fichier1 $fichier2 cp : opérande de fichier manquant Saisissez cp -- help pour plus d ' informations . Cela ne fonctionne pas car ce n'est pas $fichier qui est interprété mais $fichier1 et $fichier2 qui n'existent pas. $ cp $ { fichier }1 $ { fichier }2 Dans ce cas, cette ligne équivaut à : $ cp liste1 liste2 3.7 Variables système En plus des variables que l'utilisateur peut dénir lui-même, le shell est lancé avec un certain nombre de variables prédénies utiles pour certaines commandes et accessibles par l'utilisateur. Le contenu de ces variables système peut être modié mais il faut alors faire attention car certaines ont une incidence directe sur le comportement du système. Le tableau suivant en décrit quelques unes. 8 Variable Contenu Chemin d'accès du répertoire utilisateur. Répertoire par défaut HOME de la commande PATH cd. Liste de répertoires, séparés par des ':' où le shell recherche les commandes externes et autres scripts et exécutables. La recherche se fait dans l'ordre des répertoires saisis. PS1 Prompt String1, PS2 Prompt String2, chaîne représentant le prompt standard aché à l'écran par le shell en attente de saisie de commandes. chaîne représentant un prompt secondaire au cas où la saisie doit être complétée. SHELL Chemin complet du shell de connexion de l'utilisateur. LANG Dénition de la langue à utiliser ainsi que du jeu de caractères. USER Nom de l'utilisateur en cours. LOGNAME Nom du login utilisé lors de la connexion. HISTSIZE Taille en nombre de lignes de l'historique des commandes. OLDPWD Chemin d'accès du répertoire accédé précédemment. PWD Chemin d'accès au répertoire courant. 3.8 Variables spéciales Il s'agit de variables accessibles uniquement en lecture et dont le contenu est généralement contextuel. En voici quelques unes : Variable $? $$ $! $- Contenu Code de retour de la dernière commande exécutée. PID du shell actif. PID du dernier processus lancé en arrière-plan. Les options du shell. 3.9 Longueur d'une chaîne Il est possible d'obtenir la longueur d'une chaîne avec le caractère #. $ sys = Linux $ echo " Longueur du mot $sys = $ {# sys }" Longueur du mot Linux = 5 3.10 Tableaux et champs Deux moyens sont disponibles pour déclarer un tableau, l'un avec l'utilisation des crochets la création globale. Le premier élément est à la position 0 et le dernier à la position contenu du tableau, il faut mettre la variable et l'élément entre accolades. $ Distribution [0]=" Debian " $ Distribution [1]=" Gentoo " $ Distribution [2]=" Slackware " $ echo $ { Distribution [1]} Gentoo 9 1023. [], l'autre avec Pour accéder au ou : $ Distribution =( Debian Gentoo Slackware ) $ echo $ { Distribution [2]} Slackware Pour lister tous les éléments : $ echo $ { Distribution [*]} Debian Gentoo Slackware Pour connaître le nombre d'éléments : $ echo $ {# Distribution [*]} 3 Si l'index est une variable, il est inutile de la faire précéder par $ : $ i =0 $ echo $ { Distribution [ i ]} Debian 3.11 Variables typées typeset -i. L'avantage est qu'il deexpr (décrite plus loin). La commande Les variables peuvent être typées en entier (integer ) avec la commande vient possible d'eectuer des calculs et des comparaisons sans passer par let ou ((...)) permet des calculs sur des variables entières. Opérateur + % < == && & - * Rôle / Opérations simples. Modulo. > <= != || | ^ >= Comparaisons, 1 si vraie, 0 si faux. Égal ou diérent. Comparaisons liées par un opérateur logique. Logique binaire AND, OR et XOR. $ typeset -i x $ x =6*7 $ echo $x 42 $ x = x *3 $ echo $x 126 $ typeset -i y $ y =5 $ let x = y +5 x = x * y $ echo $x 50 4 Conguration de bash 4.1 Fichiers de conguration Le shell bash peut être lancé dans plusieurs modes : le shell interactif de connexion (login shell ), le shell interactif simple, le shell non interactif. Selon son mode de démarrage, le shell va chercher et exécuter divers scripts et chiers de conguration. Un chier de conguration est un script shell : une séquence de commandes individuelles ayant pour but de congurer l'environnement de l'utilisateur. 10 4.1.1 Shell de connexion Le shell de connexion est lancé après la saisie du login et du mot de passe sur la console. C'est celui précisé à la n de chaque ligne de /etc/passwd. Dans ce mode, le shell cherche à exécuter, dans l'ordre indiqué et s'ils sont présents, les chiers de conguration suivants : 1. /etc/profile 2. le premier chier trouvé de la liste ordonnée suivante : (a) (b) (c) ~/.bash_profile ~/.bash_login ~/.profile Remarque 2 Le chier /etc/profile exécute automatiquement un autre chier de conguration de nom /etc/bash.bashrc ~/.profile exécute automatiquement le chier ~/.bashrc s'il existe. si ce dernier existe. De même, À la déconnexion, il tente d'exécuter ~/.bash_logout 4.1.2 Shell simple Le shell interactif simple correspond à l'exécution de bash dans une fenêtre (xterm, une console ou à la main (taper ~/.bashrc seront exécutés 1. /etc/bash.bashrc 2. ~/.bashrc bash dans une console). Dans ce cas, seuls les chiers gnome-terminal, ...), /etc/bash.bashrc et s'ils existent, et dans l'ordre suivant : 4.1.3 Mode non interactif Le shell peut être lancé en mode non interactif. C'est généralement le cas lorsqu'on exécute un script. Dans ce cas, il n'y a aucun chiers de conguration exécuté par défaut au démarrage, sauf si on précise une variable appelée BASH_ENV qui contient le chemin d'un script. Dans ce cas, bash charge et exécute ce chier avant le début de l'exécution du script ou de la commande. 5 Structure et exécution d'un script Le shell n'est pas qu'un simple interpréteur de commandes, mais dispose d'un véritable langage de programmation avec notamment une gestion des variables, des tests, des boucles, des opérations sur les variables, des fonctions ... Toutes les instructions et commandes sont regroupées au sein d'un script. Lors de son exécution, chaque ligne sera lue et exécutée. Une ligne peut être composée de commandes internes ou externes, de commentaires, ou être vide. Plusieurs commandes par lignes sont possibles, séparées par ';' ou liées conditionnellement par && ou ||. Par convention, les noms des scripts shell se terminent (pas obligatoirement) par .sh pour le Bourne Shell et le Bourne Again Shell, par .ksh pour le Korn Shell et par .csh pour le C Shell. Pour rendre un script directement exécutable : $ chmod u + x monscript Pour l'exécuter : $ ./ monscript Pour éviter le ./ : $ PATH = $PATH :. $ monscript Quand un script est lancé, un nouveau shell ls est créé pour exécuter chacune de ses commandes. Une commande interne du script est directement exécutée par le nouveau shell. Pour une commande externe, un nouveau shell ls est créé et chargé de l'exécuter. Enn, dans le cas d'un script shell, un nouveau shell ls est lancé pour le lire ligne par ligne. Une ligne de commentaire commence toujours par le caractère d'une ligne comportant déjà des commandes. 11 #. Un commentaire peut être placé en n # La ligne suivante effectue un ls ls # La ligne en question La première ligne a une importance particulière car elle permet de préciser quel shell va exécuter le script : #!/ bin / bash La première ligne ci-dessus d'un script indique que ce dernier doit être exécuté par le shell bash. 5.1 Arguments d'un script 5.1.1 Paramètres de position Les paramètres de position sont des variables spéciales utilisées lors d'un passage de paramètres à un script. Variable $0 $n $# $* $@ Contenu Nom de la commande (du script). $1, $2, $3, ... les paramètres passés au script. Nombre total de paramètres passés au script. Liste de tous les paramètres au format "$1 $2 $3 ...". Liste des paramètres sous forme d'éléments distincts. $ cat param . sh #!/ bin / bash echo " Nom : $0 " echo " Nombre de parametres : $ #" echo " Parametres : 1= $1 2= $2 3= $3 " echo " Liste : $ *" echo " Elements : $@ " $ ./ param . sh debian gentoo slackware Nom : ./ param . sh Nombre de parametres : 3 Parametres : 1= debian 2= gentoo 3= slackware Liste : debian gentoo slackware Elements : debian gentoo slackware La diérence entre $@ et $* ne semble pas évidente. Reprenons l'exemple précédent avec une petite modi- cation : $ ./ param . sh debian " gentoo slackware " Nom : ./ param . sh Nombre de parametres : 2 Parametres : 1= debian 2= gentoo slackware 3= Liste : debian gentoo slackware Elements : debian gentoo slackware Cette fois, il n'y a que deux paramètres qui sont passés. Pourtant les listes semblent visuellement identiques. En fait si la première contient bien : " debian gentoo slackware " la deuxième contient : " debian " " gentoo slackware " Soit bien deux éléments. Dans le premier exemple on avait : " debian " " gentoo " " slackware " 12 5.1.2 Redénition des paramètres Outre le fait de lister les variables, la commande set permet de redénir le contenu des variables de position. Avec : set valeur1 valeur2 valeur3 ... $1 prendra comme contenu valeur1, $2 valeur2 et ainsi de suite. $ cat param2 . sh #!/ bin / bash echo " Avant set :" echo " Nombre de paramètres : $ #" echo " Paramètres : 1= $1 2= $2 3= $3 " echo " Liste : $ *" set redhat suse gentoo echo " Après set :" echo " Nombre de paramètres : $ #" echo " Paramètres : 1= $1 2= $2 3= $3 " echo " Liste : $ *" $ ./ param2 . sh debian ubuntu mint gnewsence Avant set : Nombre de paramètres : 4 Paramètres : 1= debian 2= ubuntu 3= mint Liste : debian ubuntu mint gnewsence Après set : Nombre de paramètres : 3 Paramètres : 1= redhat 2= suse 3= gentoo Liste : redhat suse gentoo 5.1.3 Réorganisation des paramètres La commande shift est une autre commande permettant de modier la structure des paramètres de $2 devient $2 et ainsi de suite. Le $1 originel disparaît. $# , $* et $@ sont redénis en conséquence. La commande shift suivie d'une valeur n eectue un décalage de n éléments. Ainsi avec shift 4, $5 devient $1, $6 devient $2, ... position. Un simple appel décale tous les paramètres d'une position en supprimant le premier : $1, $3 devient $ cat ./ param3 . sh #!/ bin / bash shift 2 echo " Nombre de paramètres : $ #" echo " Liste : $ *" $ ./ param3 . sh debian ubuntu mint Nombre de paramètres : 1 Liste : mint 5.1.4 Sortie d'un script La commande exit 0 (pas d'erreur) 0 à 255 peut être précisée. On récupère la valeur de sortie par la variable permet de mettre n à un script. Par défaut la valeur retournée est mais n'importe quelle autre valeur de $?. 5.2 Environnement du processus En principe seules les variables exportées sont accessibles par un processus ls. Si on souhaite visualiser l'environnement lié à un ls (dans un script par exemple), on utilise la commande La commande env env. permet de redénir aussi l'environnement du processus à lancer. Cela peut être utile lorsque le script doit accéder à une variable qui n'est pas présente dans l'environnement du père, ou qu'on ne souhaite pas exporter. La syntaxe est : env var1 = valeur var2 = valeur ... commande Dans le cas de bash, env n'est pas indispensable, on peut donc utiliser la syntaxe suivante : 13 var1 = valeur var2 = valeur ... commande Si la première option est le signe - alors c'est tout l'environnement existant qui est supprimé pour être remplacé par les nouvelles variables et valeurs. $ cat d . sh #!/ bin / bash echo " d = $d " $ unset d $ ./ d . sh d= $ env d = debian ./ d . sh d = debian $ d = debian ./ d . sh d = debian $ export d = DEBIAN $ ./ d . sh d = DEBIAN $ env - ./ d . sh d= 5.3 Substitution de commande Le mécanisme de substitution permet de placer le résultat de commandes simples ou complexes dans une variable. On place les commandes à exécuter entre des accents graves ` ([Alt Gr] 7 sur les claviers français). $ mon_unix = ` uname -a | cut -d ' ' -f10 ` $ echo $mon_unix GNU / Linux Notons que seul le canal de sortie standard est aecté à la variable. Le canal d'erreur standard est toujours l'écran. 5.4 Tests de conditions $?. La commande test permet d'eectuer des tests de 0 alors la condition est réalisée. conditions. Le résultat est récupérable par la variable Si ce résultat est 5.4.1 Tests sur une chaîne $ $ 0 $ 1 $ $ 0 test test test test -z "variable" : zero, retourne OK si la variable est vide (exemple, test -z "$a"). -n "variable" : non zero, retourne OK si la variable n'est pas vide (texte quelconque). "variable" = chaîne : OK si les deux chaînes sont identiques. "variable" != chaîne : OK si les deux chaînes sont diérentes. d= test -z " $d " ; echo $ ? test -n " $d " ; echo $ ? d = debian test " $d " = debian ; echo $ ? Attention à bien placer les variables contenant du texte entre guillemets. Dans le cas contraire, un bug se produira si la variable est vide : $ s1 = $ s2 = azerty $ [ $s1 = $s2 ] && echo " ok " bash : [: = : opérateur unaire attendu alors que : [ " $s1 " = " $s2 " ] && echo " ok " ne produit pas d'erreur. 14 5.4.2 Tests sur les valeurs numériques Les chaînes à comparer sont converties en valeurs numériques. Bash ne gère que des valeurs entières. La syntaxe est : test valeur1 opérateur valeur2 Les opérateurs sont : $ a =10 $ b =20 $ test 0 $ test 1 $ test 10 est -eq (=), -ne (<>), -lt (<), -gt (>), -le (<=) et -ge (>=). " $a " - ne " $b " ; echo $ ? " $a " - ge " $b " ; echo $ ? " $a " - lt " $b " && echo " $a est inférieur à $b " inférieur à 20 5.4.3 Tests sur les chiers La syntaxe est : test critère fichier -f (chier normal), -d (répertoire), -c (chier en mode caractère), -b (chier en mode -p (tube nommé), -r (autorisation en lecture), -w (autorisation en écriture), -x (autorisation en exécu-s (chier non vide), -e (chier existe), -L (chier est un lien symbolique). Les critères sont : bloc), tion), $ ls param . sh - rwxr - -r - - 1 etudiant etudiant 252 janv . $ test -f param . sh ; echo $ ? 0 $ test -x param . sh ; echo $ ? 0 $ test -d param . sh ; echo $ ? 1 5 20:13 param2 . sh 5.4.4 Tests combinés par des critères ET, OU et NON On peut eectuer plusieurs tests avec une seule commande. Les options de combinaison sont les mêmes que pour la commande find : -a (AND), -o (OR), ! (NOT). Les parenthèses peuvent être utilisées pour le groupement des combinaisons mais elles doivent être verrouillées \(...\). $ test \( ! -d param . sh \) -a -x " param . sh " && \ > echo " param . sh n ' est pas un répertoire et il est exécutable ." param . sh n ' est pas un répertoire et il est exécutable . 5.4.5 Syntaxe allégée Le mot test peut être remplacé par les crochets ouverts et fermés [ ... ]. Il faut laisser un espace après le crochet ouvert et avant le crochet fermé. $ [ " $a " - lt " $b " ] && echo " $a est inférieur à $b " 10 est inférieur à 20 bash intègre une commande interne de test qui se substitue au programme test (/usr/bin/test). Dans la pratique, la commande interne est entièrement compatible avec la commande externe mais bien plus rapide car il n'y a pas de création de nouveau processus. Pour forcer l'utilisation de la commande interne, on utilise les doubles crochets [[ ... ]]. $ [[ " $a " - lt " $b " ]] && echo " $a est inférieur à $b " 10 est inférieur à 20 15 5.5 if ... then ... else ... La structure if then else fi est une structure de contrôle conditionnelle. if < commandes_condition > then < commandes exécutées si la condition est réalisée > else < commandes exécutées si la condition n ' est pas réalisée > fi On peut aussi préciser elif, en fait un else if. Si la dernière condition n'est pas réalisée, on teste une nouvelle. $ cat param4 . sh #!/ bin / bash if [[ $ # - ne 0 ]] then echo " $ # paramètres en ligne de commande ." else echo " Aucun paramètre " fi 5.6 Choix multiples : case La commande case ... esac permet de vérier le contenu d'une variable ou d'un résultat de manière multiple. case valeur modele1 ) modele2 ) ... *) esac in commandes ;; commandes ;; commandes_par_défaut ;; Le modèle est soit un simple texte, soit composé des caractères spéciaux décrits par le tableau suivant. Chaque bloc de commandes lié au modèle doit se terminer par deux points-virgules. Dès que le modèle est vérié, le bloc de commandes correspondant est exécuté. L'étoile en dernière position permet d'exécuter l'action par défaut si aucun critère n'est vérié. Elle est facultative. Caractère * ? [...] [!...] | Rôle N'importe quelle chaîne (même vide). Un (seul) caractère quelconque. Une plage de caractères. Négation de la plage de caractères. OU logique. #!/ bin / bash if [ $ # - ne 1 ] then echo " Erreur : Un et un seul paramètre attendu ." exit 1 fi case $1 in [a - zA - Z ]*) echo " Le paramètre commence par une lettre .";; [0 -9]*) echo " Le paramètre commence par un chiffre .";; *) echo " Le paramètre commence par un autre caractère .";; esac exit 0 16 5.7 Saisie de l'utilisateur La commande read permet à l'utilisateur de saisir une chaîne et de la placer dans une ou plusieurs variables. [Entrée]. La saisie doit être validée par la touche read var1 [ var2 ...] Si plusieurs variables sont précisées, le premier mot ira dans var1, le second dans var2, et ainsi de suite. S'il y a moins de variables que de mots, tous les derniers mots vont dans la dernière variable. $ cat read . sh #!/ bin / bash echo -e " Continuer ( O / o / N / n )? \ c " read reponse case $reponse in [ Oo ]) echo " Oui , on continue ";; [ Nn ]) echo " Non , on s ' arrête "; exit 0;; *) echo " Erreur de saisie "; exit 1;; esac echo -e " Tapez deux mots ou plus : \ c " read mot1 mot2 echo -e " mot1 = $mot1 \ nmot2 = $mot2 " exit 0 $ ./ read . sh Continuer ( O / o / N / n )? o Oui , on continue Tapez deux mots ou plus : Salut tout le monde ! mot1 = Salut mot2 = tout le monde ! 5.8 Les boucles Elles permettent la répétition d'un bloc de commandes soit un nombre limité de fois, soit conditionnellement. Toutes les commandes à exécuter dans une boucle se placent entre les commandes do et done. 5.8.1 Boucle for La boucle for ne se base pas sur une quelconque incrémentation de valeur mais sur une liste de valeurs, de chiers ... for var in < liste > do < commandes à exécuter > done La liste représente un certain nombre d'éléments qui seront successivement attribués à Avec une variable $ cat for1 . sh #!/ bin / bash for param in $@ do echo " $param " done $ ./ for1 . sh ab cde ab cde 17 var. Liste implicite Si on ne précise aucune liste à for, alors c'est la liste des paramètres qui est implicite. Ainsi, la boucle du script précédent aurait pu être : for param do echo " $param " done Avec une liste d'éléments explicite Chaque élément situé après le in sera utilisé pour chaque itération de la boucle, l'un après l'autre. $ cat for2 . sh #!/ usr / bin / sh for element in elt1 elt2 do echo " $element " done $ ./ for2 . sh elt1 elt2 Avec des critères de recherche sur des noms de chiers Si un ou plusieurs éléments de la liste correspond à un chier ou à un motif de chiers présents dans le répertoire courant, la boucle for considère l'élément comme un nom de chier. $ cat for3 . sh #!/ bin / bash echo " Liste des fichier du répertoire courant :" for fichier in * do echo -e " $fichier " done $ ./ for3 . sh Liste des fichier du répertoire courant : Bureau case . sh Documents Downloads spim -8.0 ... Avec une substitution de commande Toute commande produisant une liste de valeurs peut être placée à la suite du in à l'aide d'une substitution de commande. La boucle for prendra le résultat de cette commande comme la liste d'éléments sur laquelle boucler. $ cat for4 . sh #!/ bin / bash echo -e " Liste des utilisateurs dans / etc / passwd : \ c " for user in ` cat / etc / passwd | cut -d : -f1 ` do echo -e " $user \ c " done $ ./ for4 . sh Liste des utilisateurs dans / etc / passwd : root daemon bin sys sync games ... 18 5.8.2 Boucle while while condition do commandes done Tant que la condition est réalisée, le bloc de commande est exécuté. On sort si la condition n'est plus valable. $ cat while1 . sh #!/ bin / bash while echo -e " Chaine ? \ c "; read nom ; [ -z " $nom " ] do echo " ERREUR : pas de saisie " done echo " Vous avez saisi : $nom " Lecture d'un chier ligne par ligne Elle peut se faire, soit en utilisant un tube (pipe) : #!/ bin / bash cat fichier . txt | while read ligne do echo " $ligne " done ou bien par redirection de l'entrée : #!/ bin / bash while read ligne do echo " $ligne " done < fichier . txt 5.8.3 Boucle until until condition do < commandes > done La boucle until est analogue à la boucle while. La seule diérence est que, contrairement à lorsque la condition est réalisée qu'on sort de la boucle until. while, c'est 5.8.4 true et false La commande true ne fait rien d'autre que de renvoyer 0. La commande false renvoie toujours 1. De cette manière il est possible de réaliser des boucles innies. La seule manière de sortir de ces boucles est un exit ou un break. Par convention, tout programme qui ne retourne pas d'erreur, retourne 0, retournant une erreur, ou un résultat à interpréter, retourne autre chose que tandis que tout programme 0. C'est l'inverse en logique booléenne. 5.8.5 break et continue La commande done. break permet d'interrompre une boucle. Dans ce cas le script continue après le mot clé Elle peut prendre un argument numérique indiquant le nombre de boucles à sauter dans le cas de boucles imbriquées. while true do echo -e " Chaine ? \ c " read a 19 if [ -z " $a " ] then break fi done continue permet de relancer une boucle et d'eectuer un nouveau passage. Elle peut prendre n boucles). Le script commande do. La commande un argument numérique indiquant le nombre de boucles à relancer (on remonte de redémarre à la 5.9 Les fonctions Les fonctions sont des bouts de scripts nommés, directement appelés par leur nom, pouvant accepter des paramètres et retourner des valeurs. Les noms de fonctions suivent les mêmes règles que les variables sauf qu'elles ne peuvent pas être exportées. nom_fonction () { commandes return } Les fonctions peuvent être soit tapées dans le script courant, soit dans un autre chier pouvant être inclus dans l'environnement. Pour cela il faut saisir : . fichier Le point suivi d'un nom de chier charge son contenu (fonctions et variables) dans l'environnement courant. return permet d'aecter une valeur de retour à une fonction. exit pour sortir d'une fonction car sinon on quitte le script. La commande commande Il ne faut surtout pas utiliser la $ cat fonctions ll () { ls -l $@ } li () { ls -i $@ } $ . fonctions $ li 269361 Bureau 269726 case . sh 269365 Documents ... 5.10 Calculs et expressions 5.10.1 expr La commande expr permet d'eectuer des calculs sur des valeurs numériques, des comparaisons, et de la recherche dans des chaînes de texte. 20 Opérateur + * / % != = < > <= >= : Rôle Addition. Soustraction. Multiplication. L'étoile étant reconnue par le shell comme un caractère spécial, il faut la verrouiller avec un antislash : \*. Division. Modulo. Diérent. Ache 1 si diérent, 0 sinon. Égal. Ache 1 si égal, 0 sinon. Inférieur. Ache 1 si inférieur, 0 sinon. Supérieur. Ache 1 si supérieur, 0 sinon. Inférieur ou égal. Ache 1 si inférieur ou égal, 0 sinon. Supérieur ou égal. Ache 1 si supérieur ou égal, 0 sinon. Recherche dans une chaîne. Exemple : commence par d. Syntaxe particulière : expr debian : "d*" retourne 1 car debian expr debian : ".*" retourne la longueur de la chaîne. Notons qu'il faut toujours laisser des espaces entre les opérateurs et leurs opérandes. $ expr 7 + 3 10 $ expr 7 \* 3 21 $ a = $ ( expr 13 - 10) $ echo $a 3 $ cat expr . sh #!/ bin / bash somme =0 compteur =1 N =10 echo " Calcul de la somme des $N premiers nombres entiers :" while [ " $compteur " - le " $N " ] do somme = $ ( expr $somme + $compteur ) echo " itération = $compteur , somme = $somme " compteur = $ ( expr $compteur + 1) done $ ./ expr . sh Calcul de la somme des 10 premiers nombres entiers : itération =1 , somme =1 itération =2 , somme =3 itération =3 , somme =6 ... itération =10 , somme =55 5.10.2 Calculs avec bash bash propose une forme simple de calculs sur les entiers, en plaçant l'opération entre $ a =1; $ echo 2 $ b =6; $ echo 12 $((...)) a = $ (( a +1)) $a a = $ (( a * b )) $a On n'a pas besoin de spécier les $ des noms des variables entre les doubles parenthèses. 21 : 5.11 Une variable dans une autre variable Considérons l'exemple suivant : $ x = debian $ y=x $ echo $y x Comment acher le contenu de x et pas simplement On peut utiliser pour cela la commande précédée par deux $, eval x? qui essaie d'interpréter, si possible, la valeur d'une variable comme étant une autre variable. $ eval echo \ $$y debian $ cat eval . sh #!/ bin / bash cpt =1 for i in a b c do eval $i = $cpt cpt = $ (( cpt +1)) done echo $a $b $c $ ./ eval . sh 1 2 3 5.12 Traitement des signaux La commande trap permet de modier le comportement du script à la réception d'un signal. Commande Réaction trap signaux trap 'commandes' signaux trap signaux Dans l'exemple suivant, trap Ignore les signaux. Exemple, ignore les signaux 2 et 3. Restaure les actions par défaut pour les signaux indiqués. empêche l'exécution du $ cat trap . sh #!/ bin / bash ignorer () { echo " Ctrl + C ignoré " } sortir () { echo " Signal 15 reçu "; exit 0 } trap ignorer 2 trap sortir 15 while true do true done $ ./ trap . sh ^ C Ctrl + C ignoré ^ C Ctrl + C ignoré Depuis un autre terminal ou console : $ kill -2 12456 $ kill -2 12456 $ kill -15 12456 trap 2 3 Pour chaque signal reçu, exécution des commandes indiquées. # aucun effet # aucun effet # SIGTERM Sur le premier terminal : Ctrl + C ignoré Ctrl + C ignoré Signal 15 reçu 22 [Ctrl] C (SIGINT) et intercepte le signal SIGTERM :