Version 1.9.fr.1.1
2007-04-23
Table des matières
Liste des illustrations
Liste des tableaux
La raison première de ce document est que beaucoup de gens trouvent le HOWTO trop court et incomplet, et le guide Bash Scripting trop poussé. Il n'y a rien entre ces deux extrêmes. J'ai aussi écrit ce guide selon le principe général que les guides de base devraient être gratuits, alors que peu le sont.
C'est un guide pratique qui, sans être toujours sérieux, essaye de donner des exemples d'usage plutôt que théoriques. Je l'ai en partie écrit parce que je ne suis pas emballée par les exemples dépouillés, hyper simplifiés écrits par des gens qui, sachant de quoi ils parlent, montrent de super possibilités du Bash, tellement hors contexte que vous ne pouvez vous imaginez leurs applications pratiques. Vous pouvez lire ce genre de documents après ce guide, lequel contient exercices et exemples qui aideront à survivre dans la vraie vie.
De par mon expérience en tant qu'utilisateur, administrateur et formateur sur système UNIX/Linux, je sais que des gens peuvent avoir des années d'interactions quotidiennes avec leur système sans avoir la moindre notion de l'automatisation de tâches. De sorte qu'ils pensent souvent que UNIX n'est pas convivial, et pire, ils ont l'impression que c'est lent et obsolète. Cette difficulté est de celles que peut palier ce guide.
Prérequis — Ce qui n'est pas dans ce guide. Vous devriez :
Voir Introduction to Linux (ou votre miroir TLDP TLDP mirror) si vous ignorez l'un de ces aspects. Des informations complémentaires peuvent être trouvées dans la documentation de votre système (man ; info pages), ou là : the Linux Documentation Project.
La dernière édition se trouve à http://tille.xalasys.com/training/bash/. Vous devriez aussi la trouver à http://tldp.org/LDP/Bash-Beginners-Guide/html/index.html.
Ce guide est disponible imprimé chez Fultus.com.
Traduction chinoise at http://xiaowang.net/bgb-cn/, par Wang Wei.
Traduction ukrainienne at http://docs.linux.org.ua/index.php/LDP:Bash_beginners_guide, par Yaroslav Fedevych et son équipe.
Une traduction française en cours, à relire.
| Historique des versions | ||
|---|---|---|
| Version 1.9.fr.1.1 | 2007-04-23 | Y, JPG |
| Relectures de Marc Blanc et Jerome Blondel. | ||
| Version 1.9.fr.1.0 | 2007-04-01 | Y, JPG |
| Première version française. | ||
| Version 1.9 | 2006-10-10 | MG |
| Remarques des lecteurs ajoutées, index ajouté en utilisant les tags DocBook. | ||
| Version 1.8 | 2006-03-15 | MG |
| Exemple clarifié au Chap 4, correction du document « ici » au Chap 9, corrections typographiques, ajout d'un lien vers les traductions chinoises et ukrainienne, note et chose à savoir au sujet de awk au Chap 6. | ||
| Version 1.7 | 2005-09-05 | MG |
| Correction de typographie au Chap 3, 6 et 7, remarques de lecteurs ajoutées, ajout d'une note au Chap 7. | ||
| Version 1.6 | 2005-03-01 | MG |
| Debuggage mineur, ajout de mots clés, note au sujet du nouveau Bash 3.0, retrait d'une image vierge. | ||
| Version 1.5 | 2004-12-06 | MG |
| Changements du fait du nouveau domaine, corrections mineures. | ||
| Version 1.4 | 2004-10-18 | MG |
| Debuggage, ajout de quelques notes au Chap 9, repositionnement de vues écran avec les sections écran. Correction de typographie. | ||
| Version 1.3 | 2004-07-09 | MG |
| Ajout d'une image de traceur 1X1 pixel http://tille.xalasys.com/images/blank-bash.png, ajout object texte pour toutes les images, réparation d'un lien mort dans l'index, amélioration de la liste des signaux. | ||
| Version 1.2 | 2004-06-15 | MG |
| Ajout index, plus de repère dans les sections écrans. | ||
| Version 1.1 | 2004-05-22 | MG |
| Dernière relecture avant la mise sous presse, ajout d'exemples, vérification du sommaire, exercices, introduction arrangée. | ||
| Version 1.0 | 2004-04-27 | TM |
| Livraison initiale pour LDP, d'autres exercices, d'autres repères, moins d'erreurs et abus, ajout du glossaire. | ||
| Version 1.0-beta | 2003-04-20 | MG |
| Pre-version | ||
Informations manquantes, liens invalides, erreurs de frappe, remarques ? Envoyer un mail à
La personne assurant le suivi du document.Copyright © 2003-2005 Machtelt Garrels.
Permission est donnée pour copier, distribuer et/ou modifier ce document selon les termes de la Licence GNU Free Documentation, Version 1.1 ou ultérieure publiée par la Free Software Foundation, avec les Sections Invariantes : « New versions of this document », « Contributions », « Feedback » et « Copyright information », sans textes de couverture de garde ni de textes de couverture de dos. Une copie de la licence est incluse dans Annexe B, GNU Free Documentation License intitulée « GNU Free Documentation License ».
L'auteur et l'éditeur ont fait leur possible pour s'assurer de la validité des informations de ce livre. Cependant, le contenu de ce guide est mis à disposition sans garantie, que ce soit explicite ou implicite. Ni l'auteur, ni l'éditeur, ni un distributeur ne peuvent être tenu responsable des éventuels dommages ou conséquences résultant de l'application du contenu de ce guide.
Les logos, marques déposées et les symboles utilisés dans ce guide sont la propriété de leur dépositaire respectif.
Bash, téléchargeable à http://www.gnu.org/directory/GNU/. Le Bash accompagne à peu près tous les systèmes Linux, et se trouve maintenant sur un large éventail de systèmes UNIX.
Se compile aisément si vous avez besoin de le personnaliser, testé sur un large éventail d'UNIX, Linux, MS Windows, et autres systèmes.
Les conventions typographiques et d'usage suivantes apparaissent dans le texte :
Tableau 1. Conventions typographiques et d'usage
| Type de texte | sens |
|---|---|
| « Texte entre guillemets » | Citation de gens, texte rendu par l'ordinateur entre guillemets |
reproduction de la vue du terminal |
Capture des données saisies ou affichées sur le terminal, généralement rendue avec un fond gris clair. |
| commande | Nom d'une commande qui peut être tapée sur la ligne de commande. |
VARIABLE |
Nom d'une variable ou pointeur vers le contenu d'une variable, comme
$VARNAME. |
option |
Option d'une commande, comme « l'option -a de la commande
ls ». |
argument |
Argument d'une commande, comme dans « read
man ls ». |
|
|
Synopsis de commande ou emploi habituel, sur une ligne séparée. |
NomDeFichier |
Nom d'un fichier ou d'un répertoire, par exemple « se positionner dans le répertoire
/usr/bin . » |
| Touche | Touches à frapper sur le clavier, exemple « taper Q pour quitter ». |
| Bouton graphique sur lequel cliquer comme le bouton . | |
| → | Options à choisir dans un menu graphique, par exemple : « Choisir → dans votre navigateur. » |
| Terminologie | Terme important ou concept : « Le noyau est le coeur du système. » |
\ |
La barre oblique inversée affichée dans un terminal ou dans un synopsis de commande indique que la ligne n'est pas finie. (NdT : nous appelerons ce symbole l'échappement). En d'autres mots, si vous voyez une longue commande qui est découpée en plusieurs lignes, \ signifie « Ne pressez pas encore la touche Entrée encore ! » |
| Voir Chapitre 1, Bash et scripts Bash | Lien vers sujets connexes dans ce guide. |
| L'auteur | Lien vers une ressource WEB externe. |
Les chapitres 4 à 6 abordent les outils de base qui sont utilisés régulièrement dans les scripts.
Les chapitres 8 à 12 abordent les constructions les plus courantes dans les scripts.
Chapitre 1, Bash et scripts Bash : Les bases de Bash : pourquoi Bash est si bon, construction de blocs, premières consignes d'écriture de bons scripts.
Chapitre 2, Ecrire et corriger des scripts : Les bases du script : écrire et débugger.
Chapitre 3, L'environnement du Bash : L'environnement Bash : les fichiers d'initialisation, les variables, les expressions littérales, l'ordre d'expansion, les alias, les options.
Chapitre 4, Expressions régulières : Expressions régulières : une introduction.
Chapitre 5, L'éditeur de flot GNU sed : Sed : une introduction à l'éditeur ligne à ligne.
Chapitre 6, Le langage de programmation GNU awk : Awk : introduction à awk le langage de progammation.
Chapitre 7, Les instructions de condition : Les instructions conditionnelles : constructions utilisées en Bash pour tester des conditions.
Chapitre 8, Ecrire des scripts interactifs : Les scripts interactifs : faire des scripts conviviaux, intégrer la saisie de l'utilisateur.
Chapitre 9, Tâches répétitives : Exécuter des commandes récursivement : constructions utilisées en Bash pour automatiser l'exécution de commandes.
Chapitre 10, Un peu plus sur les variables : Variables complexes : spécifier des types de variables, introduction aux tableaux de variables, opérations sur variables.
Chapitre 11, Fonctions : Fonctions : une introduction.
Chapitre 12, Trapper les signaux : Capturer des signaux : introduction aux signaux de processus, capturer les signaux envoyés par l'utilisateur.
Résumé
Dans ce module d'introduction nous
Décrivons quelques Shell courants
Mettons en avant les avantages et possibilités du Bash GNU
Décrivons les blocs de constructions du Shell
Abordons les fichiers d'initialisation du Bash
Voyons comment le Shell exécute les commandes
Examinons quelques exemples simples de scripts
Le Shell UNIX interprète les commandes de l'utilisateur, qui sont soit directement entrées par celui-ci, ou qui peuvent être lues depuis un fichier appelé un script shell ou programme. Ces scripts sont interprétés, donc non compilés. Le Shell lit les commandes de chaque ligne du script et cherche ces commandes dans le système (voir Section 2, « Avantages du Bourne Again SHell »), alors qu'un compilateur convertit un programme en une forme lisible par la machine, un fichier exécutable - lequel peut alors être employé dans un script.
A part de passer des commandes au noyau, la tâche principale du Shell est de mettre en place un environnement utilisateur qui peut être configuré individuellement par le biais de fichiers de configuration.
Tout comme les gens connaissent une variété de langages, votre système UNIX généralement offre une variété de types de Shell :
sh ou Bourne Shell : le Shell originel toujours en vigueur sur les systèmes UNIX et sur les environnements de type UNIX. C'est le Shell de base, un petit programme avec peu de possibilités. Bien que ce ne soit pas le Shell standard, il est toujours disponible sur les systèmes Linux par souci de compatibilité des programmes UNIX.
bash ou Bourne Again shell : le Shell standard GNU , intuitif et souple. Probablement celui à conseiller aux débutants tout en étant un outil puissant pour un usage poussé et professionnel. Sur Linux, bash est le Shell standard pour l'utilisateur courant. Ce Shell est réputé être un sur-ensemble du Bourne Shell, un ensemble d'ajouts et d'extensions. Ce qui veut dire que le Bourne Again Shell est compatible avec le Bourne Shell : les commandes reconnues par sh, le sont aussi par bash. Cependant, l'inverse n'est pas toujours vrai. Tous les exemples et exercices de ce livre utilisent bash.
csh ou C shell : la syntaxe de ce Shell ressemble à celle du langage de programmation C. Parfois demandée par les programmeurs.
tcsh ou TENEX C Shell : un surensemble du répandu Shell C, implémentant convivialité et rapidité. C'est pourquoi certains l'appellent aussi le Turbo Shell C.
ksh ou le Korn shell : quelques fois apprécié des gens venant du monde UNIX. Un sur-ensemble du Bourne Shell ; avec une configuration - le cauchemar des débutants - standard.
Le fichier /etc/shells donne un aperçu des Shells connus du système Linux :
mia:~>cat/etc/shells
/bin/bash
/bin/sh
/bin/tcsh
/bin/csh
Votre Shell par défaut est déclaré dans le fichier /etc/passwd , comme cette ligne pour l'utilisateur mia :
mia:L2NOfqdlPrHwE:504:504:Mia Maya:/home/mia:/bin/bash
Pour permuter d'un
Shell à un autre, simplement entrez le nom du nouveau Shell actif dans
le terminal. Le système trouve le répertoire où le nom apparaît au
moyen des paramètres de PATH, et
puisqu'un Shell est un fichier exécutable (programme), le Shell courant
l'active et il s'exécute. Une nouvelle invite est souvent affichée, du
fait que chaque Shell a une interface propre :
mia:~>tcsh
[mia@post21 ~]$
Bash est un Shell compatible avec sh qui incorpore des spécificités utiles du Korn Shell (ksh) et du C Shell (csh). Il est censé se conformer à la norme IEEE POSIX P1003.2/ISO 9945.2 Standards des Shell et Outils. Il offre des améliorations fonctionnelles par rapport à sh pour la programmation et l'utilisation interactive ; ce qui inclut l'édition de commande en ligne, historique illimité des commandes, contrôle des travaux, fonctions Shell et alias, tableau indexé de taille illimitée, et l'arithmétique d'entiers dans toutes les bases depuis la base 2 jusqu'à la base 64. Bash peut exécuter la plupart des scripts sh sans modification.
En plus de l'option permettant des commandes Shell à un caractère qui peut être configuré généralement avec la commande intégrée set, il y a plusieurs options multi-caractères que vous pouvez employer. Nous verrons quelques unes de ces options les plus usitées dans les chapitres suivants ; la liste complète peut être trouvée dans les pages info de Bash, → .
Les fichiers de démarrage sont des scripts qui sont lus et exécutés par Bash quand il démarre. Les sous-sections suivantes décrivent diverses façons de démarrer le Shell, et le fichier de démarrage lu en conséquence.
Interactif signifie que vous pouvez entrer des commandes. Le Shell n'est pas lancé parce qu'un script a été activé. Un Shell de connection vous donne accès au Shell après qu'il vous ait authentifié, généralement en contrôlant le nom d'utilisateur et le mot de passe.
Un Shell sans connexion signifie que l'accès ne nécessite pas d'authentification par le système. Par exemple, quand vous ouvrez un terminal par le biais d'une icone, ou d'un menu.
Ce fichier est habituellement référencé dans ~/.bash_profile :
Voir Chapitre 7, Les instructions de condition pour plus d'informations sur la construction if.
Tous les scripts utilisent un Shell non-interactif. Ils sont programmés pour faire certaines tâches et ne peuvent être utilisés pour faire autre chose que ce pour quoi ils ont été prévus.
PATH
n'est pas utilisé pour la recherche de ces fichiers, donc mettre le
chemin complet dans la variable si vous souhaitez en faire usage.
Bash essaye de se comporter comme le programme historique Bourne sh tout en se conformant à la norme POSIX.
Quand il est invoqué de façon interactive, la variable ENV peut pointer vers des informations de démarrage suplémentaires.
Cette option est activée soit en employant l'intégrée set :
ou en appelant le Bash avec l'option --posix option. Bash essayera alors de respecter autant que possible la norme POSIX des Shell. Déclarer la variable POSIXLY_CORRECT fait la même chose.
Fichiers lus quand le Shell est invoqué par rshd :
![]() |
Eviter l'usage d'outils à distance |
|---|---|
|
Ayez à l'esprit les dangers de ces outils tels que rlogin, telnet, rsh et rcp. Leur usage présente des risques pour la confidentialité et la sécurité de par leur mode d'accès parce que des données non cryptées parcourent le réseau. Si vous avez le besoin d'outils à distance, transfert de fichiers et autres, utilisez une version de Secure SHell, c'est à dire SSH, disponible gratuitement ici : http://www.openssh.org. Divers programmes client sont disponibles aussi pour les systèmes non-UNIX, consulter votre miroir de logiciels. |
Un Shell interactif généralement lit et écrit depuis et sur un terminal utilisateur : les flux d'entrée et de sortie sont dirigés vers le terminal. Le mode interactif de Bash est activé quand la commande bash est invoquée sans les options rendant inactif, et sauf avec l'option qui permet de prendre l'entrée depuis une chaîne de caractères ou quand le Shell est invoqué de façon à lire l'entrée standard, ce qui autorise les paramètres positionnels (voir Chapitre 3, L'environnement du Bash ).
Test en examinant la variable spéciale -, il contient un 'i' quand le Shell est interactif :
eddy:~>echo$-
himBH
Dans un Shell non interactif, l'invite PS1, n'est pas paramétrée.
Différences dans le mode interactif :
Les invites sont établies, PS2 est déclaré pour des commandes multi-lignes , il est souvent déclaré à « > ».
C'est aussi l'invite que l'on obtient quand le Shell trouve que la
commande entrée n'est pas finie, par exemple si vous oubliez des
guillemets, une structure de commande non finie, etc.
Les commandes sont par défaut lues depuis la ligne de commande en utilisant readline.
Bash interprète l'option Shell ignoreeof plutôt que de sortir immédiatement à la réception de EOF (Fin de Fichier).
L'historique des commandes avec
leur expansion est activé par défaut. L'historique est
enregistré dans le fichier désigné par HISTFILE quand le Shell est quitté. Par defaut, HISTFILE pointe vers ~/.bash_history.
Les commandes intégrées utilisées selon le mode POSIX et qui renvoient des erreurs n'ont pas pour effet de quitter le Shell. Les commandes intégrées sont listées à la Section 3.2, « Les commandes intégrées du Shell ».
Un échec de exec ne fait pas quitter le Shell.
Des erreurs produites par l'analyse de syntaxe ne font pas quitter le Shell.
Le contrôle simple de nom des arguments de la commande intégrée cd est activé par défaut.
La sortie automatique, après le laps de temps spécifié par la variable TMOUT, est activée.
Plus d'informations :
Voir Chapitre 12, Trapper les signaux au sujet des signaux.
Section 4, « Le processus d'expansion de Shell » aborde divers processus d'expansion sur une commande saisie.
Les expressions conditionnelles sont utilisées dans la commande composée [[ et par les intégrées test et [.
Les conditions sont discutées en détail au Chapitre 7, Les instructions de condition.
Plus d'informations au sujet des descripteurs de fichiers à la Section 2.3, « Redirection et descripteurs de fichiers ».
Le Shell permet aux expressions arithmétiques d'être évaluées, en tant que processus d'expansion ou par l'intégrée let.
L'évaluation utilise des entiers de longueur fixe sans vérification de possible débordement de capacité, mais avec un contrôle de la division par 0 qui renvoie une erreur. Les opérateurs, leur ordre et leur associativité, sont pareil que dans le langage C, voir Chapitre 3, L'environnement du Bash.
Les alias permettent à une chaîne d'être substituée par un mot quand il est utilisé comme le premier mot d'une commande simple. Le Shell maintient une liste d'alias qui peuvent être déclarés ou supprimés avec les commandes alias et unalias.
Nous aborderons les alias en détail à la Section 5, « Alias ».
Bash fournit les variables sous la forme d'un tableau à une dimension . Toute variable peut être utilisée comme un tableau ; l'intégrée declare déclarera explicitement un tableau. Il n'y a pas de limite supérieure à la taille d'un tableau, ni de besoin de trier ou d'assigner de façon contiguë les valeurs. Les tableaux sont basés sur le zéro. Voir Chapitre 10, Un peu plus sur les variables.
La pile de répertoires est une liste des répertoires récemment visités. L'intégrée pushd ajoute des répertoires à la pile tout en changeant le répertoire courant, et l'intégrée popd enlève les répertoires spécifiés de la pile en positionant le répertoire courant comme étant celui qui vient d'être enlevé.
Le contenu peut être affiché avec la commande dirs ou en visualisant la variable DIRSTACK.
Bash permet de jouer avec l'invite de façon amusante. Voir la section Controlling the Prompt dans les pages info de Bash.
Quand il est invoqué avec rbash ou avec --restricted ou l'option -r , il se produit ceci :
Déclarer ou invalider SHELL, PATH, ENV ou BASH_ENV n'est pas possible.
Un nom de fichier contenant un slash n'est pas permis avec l'intégrée . (source) .
La redirection des résultats avec >, >|, ><, >&, &> et >> est désactivée.
L'option -f et -d Les options sont désactivées pour l'intégrée enable .
Un chemin par défaut PATH ne peut pas être spécifié avec l'intégrée command.
Bash determine le type de programme qui doit être exécuté. Les programmes standards sont les commandes système qui existent sous forme compilée dans le système. Quand un tel programme est exécuté, un nouveau processus est créé parce que Bash lance une copie exacte de lui-même. Ce processus fils a le même environnement que son parent, seul l'identifiant est différent. Cette procédure est appellée forking.
Le mécanisme fork-and-exec cependant substitue une ancienne commande par une nouvelle, tandis que l'environnement dans lequel le nouveau programme est exécuté reste le même, y compris la configuration des entrées/sorties, des variables d'environnement et des priorités. Ce mécanisme est employé pour créer tous les processus UNIX, donc il s'applique aussi au système d'opération Linux. Même le premier processus, init, avec l'ID 1, fourche dans la procédure de démarrage appelée bootstrapping.
Les commandes intégrées sont parties intégrantes du Shell lui-même. Quand le nom d'une commande intégrée est employé comme le premier mot d'une commande simple, le Shell exécute la commande directement, sans créer un nouveau processus. Les commandes intégrées sont nécessaires pour implanter des fonctionnalités impossibles ou difficiles à mettre en oeuvre par des outils externes.
Bash possède 3 types de commandes intégrées :
:, ., break, cd, continue, eval, exec, exit, export, getopts, hash, pwd, readonly, return, set, shift, test, [, times, trap, umask et unset.
alias, bind, builtin, command, declare, echo, enable, help, let, local, logout, printf, read, shopt, type, typeset, ulimit et unalias.
Quand Bash est exécuté en mode POSIX, les commandes spéciales diffèrent des autres selon 3 aspects :
Si la saisie n'est pas commentée, le Shell la lit et la divise en mots et opérateurs, selon les règles d'analyse qui déterminent la signification de chaque caractère saisi. Alors ces mots et opérateurs sont transformés en commandes et autres constructions, lesquels retournent un statut d'exécution qui peut être exploité. Le schéma fork-and-exec ci-dessus est appliqué seulement après que le Shell ait analysé la saisie selon le processus suivant :
Le texte est découpé en mots et opérateurs, selon les règles de syntaxe, voir Chapitre 3, L'environnement du Bash. Ces éléments sont séparés par des métacaractères. Les alias sont remplacés par leur équivalent.
Le Shell parses (analyse et transforme) les éléments en commandes simples ou composées.
Bash procède à diverses expansions d'éléments, les décomposant en listes de fichiers et commandes avec arguments.
Au besoin il est procédé à des redirections, les opérateurs de redirection et leurs opérandes sont éliminés de la liste des arguments.
Les commandes sont exécutées.
Optionnellement le Shell attend que la commande s'achève pour récupérer son statut d'exécution.
Une simple commande Shell telle que touch file1 file2 file3 consiste en la commande elle-même suivie par des arguments, séparés par des espaces.
Les fonctions Shell sont un moyen de grouper des commandes pour une exécution ultérieure par l'appel d'un nom pour le groupe. Elles sont exécutées tout comme des commandes « régulières ». Quand le nom de la fonction Shell est employé comme le nom d'une commande simple, la liste des commandes associées à cette fonction est exécutée.
Un paramètre est une entité qui mémorise une valeur. Cela peut être un nom, un nombre ou une valeur spéciale. Pour les besoins du Shell, une variable est un paramètre qui mémorise un nom. Une variable a une valeur et zéro ou plus attributs. Les variables sont créées avec l'intégrée declare.
L'assignation de variables est traitée à la Section 2, « Variables », l'utilisation poussée de variables au Chapitre 10, Un peu plus sur les variables.
L'expansion par le Shell est effectuée après que chaque ligne de commande ait été découpée en jetons ou morceaux. Voici les opérations d'expansion :
Nous traiterons ces types d'expansion à la Section 4, « Le processus d'expansion de Shell ».
Avant qu'une commande soit exécutée, ses flux d'entrée et de sortie peuvent être redirigés en employant un symbole spécial interprété par le Shell. La redirection peut aussi être employée pour ouvrir et fermer des fichiers dans l'environnement d'exécution du Shell.
A l'exécution d'une commande, les mots que l'analyse syntaxique a marqué comme assignation de variables (précédant le nom de commande) et comme redirection sont conservés pour y faire référence ultérieurement. Les mots qui ne sont pas des assignations de variables ou des redirections sont analysés ; le premier mot restant après cette analyse est considéré comme étant le nom de la commande et le reste ses arguments. Alors les opérations de redirections sont effectuées, puis les valeurs assignées aux variables sont interprétées (expansion). Si le résultat ne donne aucun nom de commande, les variables sont affectées dans l'environnement en cours.
Une part importante du travail du Shell est de localiser les commandes. Bash le fait de cette façon :
Si la commande n'est pas une fonction, la chercher dans la liste des intégrées.
Si la commande n'est ni une fonction ni une intégrée, la chercher dans les répertoires listés dans PATH. Bash se sert d'une table de hachage
(zone de stockage en mémoire) pour récupérer le
chemin complet des exécutables de sorte qu'une recherche
extensive est évitée.
Quand un fichier contenant
des commandes Shell est utilisé comme le premier argument
n'étant pas une option à l'invocation de Bash (sans
l'option -c ou l'option -s)
un Shell non-interactif est lancé. Ce Shell cherche d'abord le fichier
de script dans le répertoire en cours, puis cherche dans ceux de PATH si le fichier ne peut pas y être trouvé.
Ce guide traite principalement du dernier bloc de construction Shell : les scripts. Quelques considerations générales avant de continuer :
La structure d'un script est très flexible. Même si Bash permet beaucoup de liberté, vous devez mettre en oeuvre une logique rigoureuse, un contrôle des données, une efficacité qui permet à l'utilisateur qui exécute le script de le faire facilement et correctement.
Au moment d'écrire un nouveau script, posez-vous les questions suivantes :
La table ci-dessous donne un aperçu des termes de programmation avec lesquels vous devez vous familiariser :
Tableau 1.1. Vue générale des termes de programmation
| Termes | Qu'est-ce que c'est ? |
|---|---|
| Contrôle de commande | Test du statut d'exécution (NdT : code retour) d'une commande pour déterminer si une portion du code doit être exécutée ou pas. |
| Branchement conditionnel | Une instruction logique du programme qui détermine quelle alternative du programme exécuter ensuite. |
| Enchaînement logique | La conception du programme dans ses grandes lignes. Détermine la séquence logique des opérations de sorte que cela aboutisse à un résultat contrôlé. |
| Boucle | Partie de code qui s'exécute zéro fois ou plus. |
| Saisie de l'utilisateur | Donnée fournie par une source externe(NdT périphérique de saisie) pendant que le programme tourne, qui peut être mémorisée et exploitée au besoin. |
Afin d'accélérer les phases de développement, l'ordre logique du programme devrait être pensé à l'avance. C'est votre première étape quand vous développez un script.
L'exemple ci-dessous montre un tel enchaînement logique. Il décrit la rotation des fichiers journaux. Cet exemple montre la possible réitération d'une boucle, en fonction du nombre de fichiers journaux sur lesquels vous voulez paramétrer une rotation.
tom:~>cat-nmysystem.sh
1 #!/bin/bash
2 clear
3 echo "This is information provided by mysystem.sh. Le programme démarre maintenant."
4
5 echo "Bonjour, $USER"
6 echo
7
8 echo "Nous sommes le `date`, semaine `date +"%V"`."
9 echo
10
11 echo "Ces utilisateurs sont actuellement connectés :"
12 w | cut -d " " -f 1 - | grep -v USER | sort -u
13 echo
14
15 echo "`uname -s` est le système, `uname -m` le processeur."
16 echo
17
18 echo "Le système fonctionne depuis :"
19 uptime
20 echo
21
22 echo "C'est pas plus compliqué !"
echo et printf sont des commandes intégrées de Bash. La première retourne toujours un statut à 0, et affiche simplement ses arguments terminés par un caractère de fin de ligne sur la sortie standard, tandis que la deuxième autorise des options de formatage de la chaîne et renvoie un statut différent de 0 en cas d'échec.
Voici le même script avec l'intégrée printf :
tom:~>catmysystem.sh
#!/bin/bash
clear
printf "This is information provided by mysystem.sh. Le programme démarre maintenant."
printf "Bonjour, $USER.\n\n"
printf "Nous sommes le `date`, semaine `date +"%V"`.\n\n"
printf "Ces utilisateurs sont actuellement connectés :\n"
w | cut -d " " -f 1 - | grep -v USER | sort -u
printf "\n"
printf "`uname -s` est le système, `uname -m` le processeur.\n\n"
printf "Le système fonctionne depuis :\n"
uptime
printf "\n"
printf "C'est pas plus compliqué\n"
L'écriture d'un script convivial en insérant des messages est traité au Chapitre 8, Ecrire des scripts interactifs.
![]() |
La localisation standard du Bourne Again Shell |
|---|---|
|
Ceci implique que le programme bash est installé dans |
![]() |
Si stdout n'est pas disponible |
|---|---|
|
Si vous exécutez un script par cron, fournir le chemin complet et rediriger les résultats et les erreurs. Du fait que le Shell tourne en mode non-interactif, toute erreur provoquera la fin du script prématurément si vous n'y songez pas. |
Les chapitres suivants traiteront en détail les scripts ci-dessus.
Un script init
démarre les services système sur des machines UNIX et Linux. Les démons
de journalisation du système, de gestion des ressources, de contrôle
d'accès et de mails en sont des exemples. Ces scripts, aussi appelés
scripts de démarrage, sont stockés dans un endroit particulier de votre
système, tel que /etc/rc.d/init.d ou /etc/init.d.
Init, le processus initial, lit ses fichiers de configuration et décide
quels services il démarre ou arrête en fonction du niveau d'exécution
système. Le niveau d'exécution est un état de configuration du système
(NdT qui correspond à une utilisation particulière du système) ; chaque
système a un niveau d'exécution qui autorise un unique utilisateur, par
exemple, pour exécuter des tâches administratives, pour lesquelles le
système doit être dans un état aussi stable que possible. Comme par
exemple récupérer un fichier système important depuis une sauvegarde.
Les niveaux d'exécution de démarrage et d'arrêt sont habituellement
aussi configurés.
Voici un exemple très simple qui joue un son au démarrage et à l'arrêt de la machine :
#!/bin/bash
# This script is for /etc/rc.d/init.d
# Link in rc3.d/S99audio-greeting and rc0.d/K01audio-greeting
case "$1" in
'start')
cat /usr/share/audio/at_your_service.au > /dev/audio
;;
'stop')
cat /usr/share/audio/oh_no_not_again.au > /dev/audio
;;
esac
exit 0
L'instruction case souvent utilisée dans ce genre de script est décrite à la Section 2.5, « Emploi de l'instruction exit et du if ».
Ces exercices vont vous entraîner pour le prochain chapitre :
Utilisez l'option --version pour déterminer quelle version tourne.
Les Shell suivants sont-ils interactifs ? Sont-ils des Shell d'authentification ?
Affichez les commandes mémorisées dans la table 'hash' de votre session de Shell en cours.
Comment afficher le nom du système ? Seulement le nom, rien de plus !
Résumé
A la fin de ce chapitre vous serez capable de :
Ecrire un script simple
Définir le type de Shell qui doit exécuter le script
Ajouter des commentaires
Changer les permissions du script
Exécuter et débugger un script
Pour créer un script Shell, ouvrez un nouveau fichier avec l'éditeur. N'importe quel éditeur fera l'affaire : vim, emacs, gedit, dtpad et cetera sont tous valides. Vous pouvez songer à utiliser un éditeur sophistiqué comme vim ou emacs, parce qu'ils peuvent être configurés pour reconnaître la syntaxe Shell et Bash et donc peuvent être d'une grande aide en évitant ces erreurs que les débutants font, tel que oublier un crochet ou un point-virgule.
![]() |
Le vidéo-inverse dans vim |
|---|---|
|
Pour activer le vidéo-inverse dans vim, passer la commande
Vous pouvez ajouter ce paramètre à votre fichier |
Entrez des commandes UNIX dans ce nouveau fichier, comme vous le feriez sur la ligne de commande. Ainsi que nous l'avons vu dans le chapitre précédent (voir Section 3, « L'exécution de commandes »), les commandes peuvent être des fonctions Shell, des commandes intégrées, des commandes UNIX et le nom d'un autre script.
Dans cet exemple nous employons l'intégrée echo pour informer l'utilisateur sur ce qui va se dérouler, avant que la tâche qui crééra le résultat s'exécute. Il est fortement recommandé d'informer les utilisateurs sur ce que fait le script, de façon à éviter qu'ils deviennent anxieux parce que le script ne fait rien. Nous reviendrons sur le sujet de la notification aux utilisateurs au Chapitre 8, Ecrire des scripts interactifs.
Ecrivez ce script. Ce peut être une bonne idée de créer un répertoire ~/scripts pour ranger vos scripts. Ajoutez le répertoire au contenu de la variable PATH variable :
![]() |
Des invites différentes |
|---|---|
|
L'invite varie au long de ce guide selon l'humeur de l'auteur. Ce qui ressemble plus à la vie réelle que l'invite classique $. La seule convention que nous avons gardé est que l'invite de root finit par #. |
Le script doit avoir les permissions d'exécution pour le propriétaire afin d'être exécutable. Quand vous définissez des permissions, contrôlez que vous avez obtenu les permissions voulues. Une fois fait, le script peut être lancé comme toute autre commande :
willy:~/scripts>chmodu+xscript1.shwilly:~/scripts>ls-lscript1.sh
-rwxrw-r-- 1 willy willy 456 Dec 24 17:11 script1.shwilly:~>script1.sh
Le script démarre.
Salut, willy !
Je vais afficher une liste des utilisateurs connectés :
3:38pm up 18 days, 5:37, 4 users, load average: 0.12, 0.22, 0.15
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty2 - Sat 2pm 4:25m 0.24s 0.05s -bash
willy :0 - Sat 2pm ? 0.00s ? -
willy pts/3 - Sat 2pm 3:33m 36.39s 36.39s BitchX willy ir
willy pts/2 - Sat 2pm 3:33m 0.13s 0.06s /usr/bin/screen
Je définis 2 variables, maintenant.
Ceci est une chaîne : noir
Et ceci est un nombre : 9
Je vous rends la main, maintenant.willy:~/scripts>echo$COLOURwilly:~/scripts>echo$VALUEwilly:~/scripts>
Si vous ne voulez pas démarrer un nouveau Shell mais exécuter le script dans le Shell courant, vous faites source :
![]() |
source = . |
|---|---|
|
L'intégrée Bash source est un synonyme de la commande Bourne shell . (dot). |
willy:~/scripts>sourcescript1.sh
--output ommitted--willy:~/scripts>echo$VALUE
9willy:~/scripts>
Quand un script s'exécute dans un sous-Shell, vous devriez définir quel Shell doit exécuter ce script. Le type de Shell pour lequel vous avez écrit le script peut ne pas être celui par défaut de votre système, alors les commandes peuvent ne pas être interprétées par un Shell inadéquat.
Dans ce guide, tous les scripts commenceront par la ligne
Comme indiqué auparavant, ceci implique que le programme Bash doit se trouver dans /bin.
Vous devriez vous rappeler que vous ne serez peut-être pas la seule personne à lire votre code. Beaucoup d'utilisateurs et d'administrateurs système lancent des scripts qui ont été écrits par d'autres. Si ils veulent voir comment vous avez fait, les commentaires sont utiles pour éclairer le lecteur.
Les commentaires vous rendent aussi la vie plus facile. Par exemple vous avez lu beaucoup de pages man pour obtenir de certaines commandes de votre script un résultat donné. Vous ne vous souviendrez plus de ce qu'il fait après quelques semaines, à moins d'avoir commenté ce que vous avez fait, comment et pourquoi.
#!/bin/bash
# Ce script efface le terminal, affiche un message d'accueil et donne des informations
# sur les utilisateurs connectés. Les 2 exemples de variables sont définis et affichés.
clear # efface le terminal
echo "Le script démarre."
echo "Salut, $USER !" # le signe dollar est employé pour obtenir le contenu d'une variable
echo
echo "Je vais maintenant vous afficher une liste des utilisateurs connectés :"
echo
w # montre qui est connecté
echo # et ce qu'ils font
echo "Je définis 2 variables maintenant."
COLOUR="noir" # définit une variable locale Shell
VALUE="9" # définit une variable locale Shell
echo "Ceci est une chaîne : $COLOUR" # affiche le contenu de la variable
echo "Et ceci est un nombre : $VALUE" # affiche le contenu de la variable
echo
echo "Je vous redonne la main maintenant."
echo
Quand les choses
ne vont pas comme attendues, vous devez déterminer qu'est-ce qui
provoque cette situation. Bash fournit divers moyens pour débugger. La plus commune est de lancer le sous-Shell avec l'option -x
ce qui fait s'exécuter le script en mode débug. Une trace de chaque
commande avec ses arguments est affichée sur la sortie standard après
que la commande ait été interprétée mais avant son exécution.
Ceci est le script commented-script1.sh exécuté en mode débug. Notez que les commentaires ne sont pas visibles dans la sortie du script.
willy:~/scripts>bash-xscript1.sh
+ clear
+ echo 'Le script démarre.'
Le script démarre.
+ echo 'Salut, willy !'
Salut, willy !
+ echo
+ echo 'Je vais maintenant vous afficher une liste des utilisateurs connectés :'
Je vais maintenant vous afficher une liste des utilisateurs connectés :
+ echo
+ w
4:50pm up 18 days, 6:49, 4 users, load average: 0.58, 0.62, 0.40
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty2 - Sat 2pm 5:36m 0.24s 0.05s -bash
willy :0 - Sat 2pm ? 0.00s ? -
willy pts/3 - Sat 2pm 43:13 36.82s 36.82s BitchX willy ir
willy pts/2 - Sat 2pm 43:13 0.13s 0.06s /usr/bin/screen
+ echo
+ echo 'Je définis 2 variables maintenant.'
Je définis 2 variables maintenant.
+ COLOUR=noir
+ VALUE=9
+ echo 'Ceci est une chaîne : '
Ceci est une chaîne :
+ echo 'Et ceci est un nombre : '
Et ceci est un nombre :
+ echo
+ echo 'Je vous redonne la main maintenant.'
Je vous redonne la main maintenant.
+ echo
![]() |
Fonctionnalités à venir du Bash |
|---|---|
|
Il y a maintenant un débugger complet pour Bash, disponible sur SourceForge. Cependant, cela nécessite une version modifiée de bash-2.05. Cette fonctionnalité devrait être disponible dans la version bash-3.0. |
Avec l'intégrée set vous pouvez exécuter en mode normal ces portions
de code où vous êtes sûr qu'il n'y a pas d'erreurs, et afficher les
informations de débuggage seulement pour les portions douteuses.
Admettons que nous ne soyons pas sûr de ce que fait la commande w dans l'exemple commented-script1.sh, alors nous pouvons l'entourer dans le script comme ceci :
set -x # active le mode débug
w
set +x # stoppe le mode débug
La sortie affiche alors ceci :
willy: ~/scripts>script1.sh
Le script démarre.
Salut, willy !
Je vais maintenant vous afficher une liste des utilisateurs connectés :
+ w
5:00pm up 18 days, 7:00, 4 users, load average: 0.79, 0.39, 0.33
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty2 - Sat 2pm 5:47m 0.24s 0.05s -bash
willy :0 - Sat 2pm ? 0.00s ? -
willy pts/3 - Sat 2pm 54:02 36.88s 36.88s BitchX willyke
willy pts/2 - Sat 2pm 54:02 0.13s 0.06s /usr/bin/screen
+ set +x
Je définis 2 variables maintenant.
Ceci est une chaîne :
Et ceci est un nombre :
Je vous redonne la main maintenant.willy: ~/scripts>
On peut basculer du mode activé à désactivé autant de fois que l'on veut dans le script.
La table ci-dessous donne un aperçu d'autres options Bash utiles :
Tableau 2.1. Aperçu des options de débug
| Syntaxe abrégée | Syntaxe longue | Effet |
|---|---|---|
| set -f | set -o noglob | Désactive la génération de noms de fichiers à partir des métacaractères (globbing). |
| set -v | set -o verbose | Affiche les lignes fournies au Shell telles qu'elles ont été lues. |
| set -x | set -o xtrace | Affiche la trace des commandes avant leur exécution. |
Dans l'exemple qui suit, nous montrons l'usage de ces options depuis la ligne de commande :
willy:~/scripts>set-vwilly:~/scripts>ls
ls
commented-scripts.sh script1.shwilly:~/scripts>set+v
set +vwilly:~/scripts>ls*
commented-scripts.sh script1.shwilly:~/scripts>set-fwilly:~/scripts>ls*
ls: *: No such file or directorywilly:~/scripts>touch*willy:~/scripts>ls
* commented-scripts.sh script1.shwilly:~/scripts>rm*willy:~/scripts>ls
commented-scripts.sh script1.sh
Une fois que vous avez localisé la partie douteuse, vous pouvez ajouter des instructions echo
devant chaque commande douteuse, de sorte que vous verrez exactement où
et pourquoi le résultat n'est pas satisfaisant. Dans le script commented-script1.sh,
ça pourrait être fait comme ça, toujours en
supposant que l'affichage des utilisateurs nous cause des soucis :
echo "debug message : avant exécution de la commande w"; w
echo "Variable VARNAME a la valeur $VARNAME."
Résumé
Dans ce chapitre nous traiterons des diverses façons de modifier l'environnement du Bash :
En modifiant les fichiers d'initialisation du Shell
En utilisant des variables
En utilisant divers modes d'échappement
En effectuant des calculs arithmétiques
En déclarant des alias
En employant l'expansion et la substitution
Quand il est invoqué interactivement avec l'option --login ou si il est invoqué en tant que sh, Bash lit les instructions de /etc/profile. Ceci habituellement définit les variables Shell PATH, USER, MAIL, HOSTNAME et HISTSIZE.
Tous les paramétrages de l'environnement des utilisateurs devraient être dans ce fichier. Cela peut ressembler à ça :
# /etc/profile
# Environnement général du système et programmes de démarrage pour le paramétrage du login
PATH=$PATH:/usr/X11R6/bin
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
USER="`id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
HOSTNAME=`/bin/hostname`
HISTSIZE=1000
# Clavier, sonnerie, style d'affichage : le fichier de configuration readline :
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then
INPUTRC=/etc/inputrc
fi
PS1="\u@\h \W"
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC PS1
# Source des fichiers d'init de programmes spécifiques (ls, vim, less, ...)
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
. $i
fi
done
# Paramètrage de programmes d'initialisation
source /etc/java.conf
export NPX_PLUGIN_PATH="$JRE_HOME/plugin/ns4plugin/:/usr/lib/netscape/plugins"
PAGER="/usr/bin/less"
unset i
Ce fichier de configuration définit quelques variables de base de l'environnement du Shell ainsi que quelques variables requises par les utilisateurs lançant Java et/ou des applications Java depuis leur navigateur. Voir Section 2, « Variables ».
Voir Chapitre 7, Les instructions de condition pour en savoir plus sur les structures if employées dans ce fichier ; Chapitre 9, Tâches répétitives traite des boucles tel que for.
Le source Bash contient des exemples de fichiers profile
pour un usage courant ou particulier. Ceux-ci et celui donné en exemple
ci-dessus nécessitent des adaptations propres à les faire fonctionner
dans votre environnement.
Sur
des systèmes qui offrent divers types de Shell, il peut être judicieux
de mettre la configuration spécifique à Bash dans ce fichier, parce que /etc/profile
est aussi lu par d'autres Shell, comme Bourne. Pour éviter que se
produisent des erreurs de syntaxe par des Shells qui ne comprennent pas
la syntaxe de Bash le fichier de configuration de chaque Shell est
différent. Dans un tel cas, le fichier de l'utilisateur ~/.bashrc devrait pointer sur /etc/bashrc afin de l'inclure dans le processus d'initialisation du Shell à la connexion.
Vous pouvez voir aussi que /etc/profile
sur votre système contient seulement l'environnement Shell et le
paramètrage du programme de démarrage, tandis que /etc/bashrc contient des définitions pour des fonctions Shell et des alias qui s'appliquent à tout le système . Le fichier /etc/bashrc peut être appelé dans /etc/profile ou dans les fichiers d'initialisation Shell de chaque utilisateur.
Le source contient des exemples de fichiers bashrc, ou vous pouvez en trouver une copie dans /usr/share/doc/bash-2.05b/startup-files. Ceci fait partie de bashrc et vient avec la documentation Bash :
alias ll='ls -l'
alias dir='ls -ba'
alias c='clear'
alias ls='ls --color'
alias mroe='more'
alias pdw='pwd'
alias sl='ls --color'
pskill()
{
local pid
pid=$(ps -ax | grep $1 | grep -v grep | gawk '{ print $1 }')
echo -n "killing $1 (process $pid)..."
kill -9 $pid
echo "slaughtered."
}
A part les alias généraux, il contient des alias pratiques qui rendent correctes des commandes même mal libellées. Nous traiterons des alias à la Section 5.2, « Créer et supprimer des alias ». Ce fichier contient une fonction pskill, qui sera étudiée en détail au Chapitre 11, Fonctions.
![]() |
Je n'ai pas ces fichiers ? ! |
|---|---|
|
Ces fichiers peuvent être absent de votre répertoire racine ; créer les au besoin. |
C'est le fichier de configuration principal pour définir l'environnement personnel. Dans ce fichier l'utilisateur peut ajouter des options de configuration supplémentaires ou changer le paramétrage par défaut :
franky~>cat.bash_profile
#################################################################
# #
# .bash_profile file #
# #
# Exécuté depuis le Shell Bash quand vous vous loggez. #
# #
#################################################################
source ~/.bashrc
source ~/.bash_login
case "$OS" in
IRIX)
stty sane dec
stty erase
;;
# SunOS)
# stty erase
# ;;
*)
stty sane
;;
esac
Ce fichier contient des ordres de paramétrage spécifiques qui sont normalement exécutés seulement quand vous vous connectez au système. Dans l'exemple nous l'utilisons pour définir la valeur de umask et pour afficher une liste des utilisateurs connectés. Cet utilisateur obtient aussi le calendrier du mois :
#######################################################################
# #
# Bash_login file #
# #
# instructions à exécuter par le Shell Bash à l'étape de connection #
# (sourced from .bash_profile) #
# #
#######################################################################
# paramétrer les permissions par défaut
umask 002 # Toutes pour moi, lecture pour le groupe et les autres
# diverses actions
w
cal `date +"%m"` `date +"%Y"`
En l'absence de ~/.bash_profile et ~/.bash_login, ~/.profile
est lu. Il peut définir le même paramétrage, qui alors peut être
accessible aux autres Shells. Rappelez-vous que les autres Shells
peuvent mal interpréter la syntaxe Bash.
Aujourd'hui il est plus courant
d'utiliser un Shell hors connection, par exemple quand vous vous
connectez via une interface graphique de type X terminal. A l'ouverture
de la fenêtre, l'utilisateur n'a pas besoin de fournir un nom et un mot
de passe : pas d'authentification. Bash cherche ~/.bashrc
dans ce cas, et de même à la connection ce fichier est référencé dans
le fichier de configuration de connection, ce qui évite d'entrer le
même paramétrage dans différents fichiers.
Dans ce fichier utilisateur, .bashrc, un ensemble de variables pour des programmes spécifiques et d'alias est défini après que le fichier à usage global /etc/bashrc ait été lu :
franky ~>cat.bashrc
# /home/franky/.bashrc
# Source de définitions globales
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# shell options
set -o noclobber
# mes variables Shell
export PS1="\[\033[1;44m\]\u \w\[\033[0m\] "
export PATH="$PATH:~/bin:~/scripts"
# mes alias
alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias ss='ssh octarine'
alias ll='ls -la'
# paramétrage de mozilla
MOZILLA_FIVE_HOME=/usr/lib/mozilla
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
MOZ_DIST_BIN=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
export MOZILLA_FIVE_HOME LD_LIBRARY_PATH MOZ_DIST_BIN MOZ_PROGRAM
# paramétrage des fontes
alias xt='xterm -bg black -fg white &'
# paramétrage de BitchX
export IRCNAME="frnk"
# La finfranky ~>
Ce fichier contient des instructions spécifiques pour la procédure de déconnexion. Dans cet exemple, la fenêtre du terminal est effacée à la déconnexion. C'est utile pour les connections à distance qui de cette façon laisse une fenêtre vide après la déconnexion.
franky ~>cat.bash_logout
#######################################################################
# #
# Bash_logout file #
# #
# instructions exécutées par le Shell Bash à la déconnexion #
# #
#######################################################################
clearfranky ~>
Quand vous modifiez n'importe lequel des fichiers ci-dessus, les utilisateurs doivent soit se reconnecter, soit exécuter (source) le fichier modifié afin que prennent effet les modifications. De la deuxième manière, les modifications sont appliquées à la session active du Shell :
Notez que source resourcefile est équivalent à . resourcefile.
Si vous vous trouvez perdu avec tous ces fichiers de configuration, et que vous ne ciblez pas où un certain paramètre est défini, employez echo, tout comme pour debugger un script ; voir la Section 3.2, « Débugger qu'une partie du script ». Vous pouvez ajouter des lignes comme celles-ci :
echo "Avant exécution de .bash_profile.."
ou comme celles-ci :
echo "Avant définition de PS1 dans .bashrc:"
export PS1="[la bonne valeur]"
echo "PS1 est défini comme ceci $PS1"
Comme dans l'exemple ci-dessus, les variables Shell sont en majuscule par convention. Bash garde une liste de 2 types de variables :
Les variables Globales ou variables d'environnement sont disponibles dans tous les Shells. Les commandes env ou printenv peuvent être employées pour afficher les variables d'environnement. Ces programmes font partie du paquetage sh-utils.
Ci-dessous un affichage fréquent :
franky ~>printenv
CC=gcc
CDPATH=.:~:/usr/local:/usr:/
CFLAGS=-O2 -fomit-frame-pointer
COLORTERM=gnome-terminal
CXXFLAGS=-O2 -fomit-frame-pointer
DISPLAY=:0
DOMAIN=hq.xalasys.com
e=
TOR=vi
FCEDIT=vi
FIGNORE=.o:~
G_BROKEN_FILENAMES=1
GDK_USE_XFT=1
GDMSESSION=Default
GNOME_DESKTOP_SESSION_ID=Default
GTK_RC_FILES=/etc/gtk/gtkrc:/nethome/franky/.gtkrc-1.2-gnome2
GWMCOLOR=darkgreen
GWMTERM=xterm
HISTFILESIZE=5000
history_control=ignoredups
HISTSIZE=2000
HOME=/nethome/franky
HOSTNAME=octarine.hq.xalasys.com
INPUTRC=/etc/inputrc
IRCNAME=franky
JAVA_HOME=/usr/java/j2sdk1.4.0
LANG=en_US
LDFLAGS=-s
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
LESSCHARSET=latin1
LESS=-edfMQ
LESSOPEN=|/usr/bin/lesspipe.sh %s
LEX=flex
LOCAL_MACHINE=octarine
LOGNAME=franky
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;
41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;
32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;
31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;
35:*.xpm=01;35:*.png=01;35:*.tif=01;35:
MACHINES=octarine
MAILCHECK=60
MAIL=/var/mail/franky
MANPATH=/usr/man:/usr/share/man/:/usr/local/man:/usr/X11R6/man
MEAN_MACHINES=octarine
MOZ_DIST_BIN=/usr/lib/mozilla
MOZILLA_FIVE_HOME=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
MTOOLS_FAT_COMPATIBILITY=1
MYMALLOC=0
NNTPPORT=119
NNTPSERVER=news
NPX_PLUGIN_PATH=/plugin/ns4plugin/:/usr/lib/netscape/plugins
OLDPWD=/nethome/franky
OS=Linux
PAGER=less
PATH=/nethome/franky/bin.Linux:/nethome/franky/bin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/bin:/usr/sbin:/bin:/sbin:.
PS1=\[\033[1;44m\]franky is in \w\[\033[0m\]
PS2=More input>
PWD=/nethome/franky
SESSION_MANAGER=local/octarine.hq.xalasys.com:/tmp/.ICE-unix/22106
SHELL=/bin/bash
SHELL_LOGIN=--login
SHLVL=2
SSH_AGENT_PID=22161
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SSH_AUTH_SOCK=/tmp/ssh-XXmhQ4fC/agent.22106
START_WM=twm
TERM=xterm
TYPE=type
USERNAME=franky
USER=franky
_=/usr/bin/printenv
VISUAL=vi
WINDOWID=20971661
XAPPLRESDIR=/nethome/franky/app-defaults
XAUTHORITY=/nethome/franky/.Xauthority
XENVIRONMENT=/nethome/franky/.Xdefaults
XFILESEARCHPATH=/usr/X11R6/lib/X11/%L/%T/%N%C%S:/usr/X11R6/lib/X11/%l/%T/%N%C%S:/usr/X11R6/lib/X11/%T/%N%C%S:
/usr/X11R6/lib/X11/%L/%T/%N%S:/usr/X11R6/lib/X11/%l/%T/%N%S:/usr/X11R6/lib/X11/%T/%N%S
XKEYSYMDB=/usr/X11R6/lib/X11/XKeysymDB
XMODIFIERS=@im=none
XTERMID=
XWINHOME=/usr/X11R6
X=X11R6
YACC=bison -y
Les variables locales ne sont visibles que dans le Shell courant. La commande intégrée set sans aucune option fait afficher une liste de toutes les variables (y compris les variables d'environnement ) et les fonctions. L'affichage sera trié et dans un format réutilisable.
franky ~>diffset.sortedprintenv.sorted| grep"<"| awk'{ print $2 }'
BASE=/nethome/franky/.Shell/hq.xalasys.com/octarine.aliases
BASH=/bin/bash
BASH_VERSINFO=([0]="2"
BASH_VERSION='2.05b.0(1)-release'
COLUMNS=80
DIRSTACK=()
DO_FORTUNE=
EUID=504
GROUPS=()
HERE=/home/franky
HISTFILE=/nethome/franky/.bash_history
HOSTTYPE=i686
IFS=$'
LINES=24
MACHTYPE=i686-pc-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PIPESTATUS=([0]="0")
PPID=10099
PS4='+
PWD_REAL='pwd
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
THERE=/home/franky
UID=504
![]() |
Awk |
|---|---|
|
L'outil GNU Awk est expliqué au Chapitre 6, Le langage de programmation GNU awk. |
A part distinguer les variables selon leur portée - locale/globale -, nous pouvons aussi les distinguer par catégories selon ce qu'elles contiennent. De ce point de vue, les variables se distinguent en 4 types :
Nous traiterons ces types au Chapitre 10, Un peu plus sur les variables. Dans l'immédiat, nous allons travailler avec des valeurs de variables de type chaîne et entier.
Les variables sont sensibles à la casse et en majuscule par défaut. Donner des noms en minuscule aux variables locales est une convention parfois employée. Cependant, vous êtes libre de nommer comme vous voulez ou de mélanger la casse. Le nom peut aussi comprendre des chiffres, mais un nom commençant par un chiffre n'est pas admis :
prompt>export1number=1
bash: export: `1number=1': not a valid identifier
Pour affecter une valeur dans un Shell, la commande est
Divers exemples avec minuscules et majuscules, chiffres et espaces :
franky ~>MYVAR1="2"franky ~>echo$MYVAR1
2franky ~>first_name="Franky"franky ~>echo$first_name
Frankyfranky ~>full_name="Franky M. Singh"franky ~>echo$full_name
Franky M. Singhfranky ~>MYVAR-2="2"
bash: MYVAR-2=2: command not foundfranky ~>MYVAR1="2"
bash: MYVAR1: command not foundfranky ~>MYVAR1="2"
bash: 2: command not foundfranky ~>unsetMYVAR1first_namefull_namefranky ~>echo$MYVAR1$first_name$full_name
<--no output-->franky ~>
Une variable créée comme celles ci-dessus est seulement visible par le Shell actif. C'est une variable locale: les processus enfants de ce Shell actif ne connaîtront pas cette variable. Afin de faire connaître ces variables à un sous-Shell, nous avons besoin de faire un export avec l'intégrée export. Les variables exportées sont appelées les variables d'environnement. Définir et exporter sont souvent 2 actions faites en même temps.
Un sous-Shell peut changer la valeur de variables héritées de son parent, mais cette modification n'affecte pas le parent. Cet exemple en fait la démonstration :
franky ~>full_name="Franky M. Singh"franky ~>bashfranky ~>echo$full_namefranky ~>exitfranky ~>exportfull_namefranky ~>bashfranky ~>echo$full_name
Franky M. Singhfranky ~>exportfull_name="Charles the Great"franky ~>echo$full_name
Charles the Greatfranky ~>exitfranky ~>echo$full_name
Franky M. Singhfranky ~>
Bash utilise certaines variables Shell de la même manière que Bourne Shell. Dans certains cas, Bash assigne une valeur par défaut à la variable. La table ci-dessous donne un aperçu de ces variables Shell de base :
Tableau 3.1. Variables réservées Bourne Shell
| Nom de variable | Définition |
|---|---|
| CDPATH | Une liste des répertoires, séparés par deux points( :), utilisés comme chemin de recherche pour l'intégrée cd. |
| HOME | Le répertoire racine de l'utilisateur actif ; le chemin par défaut pour l'intégrée cd. La valeur de cette variable est aussi utilisée par l'expansion du tilde |
| IFS | Une liste de caractères qui peuvent séparer les champs ; utilisé par Shell pour découper les mots lors du processus d'expansion. |
Si à ce paramètre est affecté un nom de fichier et que la variable MAILPATH n'est pas définie, Bash informe l'usager de l'arrivée d'un mail dans le fichier spécifié. |
|
| MAILPATH | Une liste de fichiers, séparés par deux points (:), dont se sert le Shell régulièrement pour rechercher les nouveaux mails. |
| OPTARG | La valeur de l'argument de la dernière option traitée par l'intégrée getopts. |
| OPTIND | Le rang de l'argument de la dernière option traitée par l'intégré getopts. |
| PATH | Une liste de répertoires, séparés par deux points( :), dans lesquels le Shell recherche les commandes. |
| PS1 | La principale chaîne d'invite. La valeur par défaut est « '\s-\v\$ ' ». |
| PS2 | La chaîne alternative d'invite. La valeur par défaut est « '> ' ». |
Ces variables sont définies ou utilisées par Bash, mais les autres Shells normalement ne les traitent pas spécialement.
Tableau 3.2. Les variables réservées de Bash
| Nom de variable | Définition |
|---|---|
| auto_resume | Cette variable configure la façon dont le Shell interprète la saisie à la ligne de commande comme étant des ordres de contrôle de travaux. |
| BASH | Le chemin complet où se trouve l'exécutable du Bash actif. |
| BASH_ENV | Si cette variable est définie quand Bash est invoqué pour exécuter un script Shell, sa valeur est interprétée(expansion) et utilisée comme nom de fichier de démarrage à lire avant d'exécuter le script. |
| BASH_VERSION | Le numéro de version du Bash actif. |
| BASH_VERSINFO | Un tableau en lecture dont chaque élément mémorise un niveau de la version du Bash actif. |
| COLUMNS | Utilisé par l'intégrée select pour déterminer la largeur du terminal lors de l'affichage de listes de sélection. Automatiquement défini à la réception d'un signal SIGWINCH. |
| COMP_CWORD | Un index dans ${COMP_WORDS} qui pointe sur le mot où se trouve le curseur. |
| COMP_LINE | La ligne de commande courante. |
| COMP_POINT | Index qui point la position du curseur dans la commande courante. |
| COMP_WORDS | Une variable tableau dont chaque élément renvoie un mot de la commande courante. |
| COMPREPLY | Une variable tableau d'où Bash tire des interprétations possibles qui ont été générées par une fonction Shell dans le processus de génération. |
| DIRSTACK | Une variable tableau mémorisant le contenu de la pile de répertoires. |
| EUID | Le nombre identifiant l'utilisateur actif. |
| FCEDIT | L'éditeur utilisé par défaut par l'option -e de l'intégrée fc. |
| FIGNORE | Une liste de suffixes à ignorer, séparés par deux points ( :), quand se produit la génération de noms de fichiers. |
| FUNCNAME | Contient le nom de fonction si une fonction Shell est en train de s'exécuter. |
| GLOBIGNORE | Une liste de patrons, séparés par deux points ( :), qui sert à définir les fichiers à ignorer lors de la génération de nom de fichiers. |
| GROUPS | Un tableau qui mémorise les groupes auxquels l'utilisateur appartient. |
| histchars | Jusqu'à 3 caractères permettant de contrôler l'expansion d'historique, la substitution rapide, et le découpage en mots. |
| HISTCMD | Le numéro d'historique, ou le rang dans la liste d'historique de la commande en cours. |
| HISTCONTROL | Détermine si la commande en cours est ajoutée au fichier d'historique. |
| HISTFILE | Le nom de fichier dans lequel l'historique des commandes est conservé. La valeur par défaut est ~/.bash_history. |
| HISTFILESIZE | Détermine le nombre maximum de lignes que mémorise le fichier d'historique ; par défaut 500. |
| HISTIGNORE | Une liste de patrons, séparés par deux points ( :), qui sert à déterminer quelles commandes sont mémorisées dans l'historique. |
| HISTSIZE | Détermine le nombre maximum de commandes que mémorise le fichier d'historique ; par défaut 500. |
| HOSTFILE | Contient le nom d'un fichier au format de /etc/hosts qui devrait être lu quand le Shell a besoin du nom de machine hôte. |
| HOSTNAME | Délivre le nom de la machine hôte. |
| HOSTTYPE | Une chaîne qui décrit la machine sur laquelle Bash est en train de tourner. |
| IGNOREEOF | Détermine l'action du Shell quand il reçoit le caractère EOF et uniquement celui-là. |
| INPUTRC | Délivre le nom du fichier d'initialisation de Readline, se substituant à /etc/inputrc. |
| LANG | Utilisé pour tenter de déterminer le particularisme local lorsque qu'aucune variable commençant par LC_ ne spécifie la catégorie. |
| LC_ALL | Cette variable se substitue à LANG et à toute autre variable LC_ en spécifiant une catégorie de particularisme local. |
| LC_COLLATE | Cette variable détermine l'ordre des lettres lors du tri du résultat de l'expansion des noms ainsi que le comportement des expressions des intervalles, des classes d'équivalences, et de la comparaison de chaînes lors de la recherche de motifs et l'expansion des noms de fichiers. |
| LC_CTYPE | Cette variable détermine l'interprétation des caractères et le comportement des classes de caractères [NdT : ex : [ :alpha] ] lors de l'expansion des noms de fichiers et de la recherche de patrons. |
| LC_MESSAGES | Cette variable détermine le particularisme utilisé pour traduire les chaînes entre guillemets précédés par un « $ ». |
| LC_NUMERIC | Cette variable détermine la catégorie des particularismes employés pour formater les nombres. |
| LINENO | Le numéro de la ligne en train d'être traitée dans le script ou la fonction Shell. |
| LINES | Utilisé par l'intégrée select pour déterminer la longueur de colonne lors de l'affichage de listes de sélection. |
| MACHTYPE | Une chaîne qui décrit complètement le type de système sur lequel Bash tourne, dans le format standard GNU CPU-COMPANY-SYSTEM. |
| MAILCHECK | Intervalle de temps (en secondes) entre 2
vérifications de présence de mail dans le fichier
spécifié par MAILPATH ou MAIL. |
| OLDPWD | Contient le nom du répertoire précédent accédé par l'intégrée cd. |
| OPTERR | Si défini à 1, Bash affiche les messages d'erreur générés par l'intégrée getopts. |
| OSTYPE | Une chaîne décrivant le système d'exploitation sur lequel Bash tourne. |
| PIPESTATUS | Un tableau contenant une liste des statuts d'exécution des processus les plus récemment exécutés en avant-plan (éventuellement une seule commande). |
| POSIXLY_CORRECT | Si cette variable est définie quand bash démarre, le Shell entre en mode POSIX. |
| PPID | L'identifiant du process parent du Shell. |
| PROMPT_COMMAND | Définie, la valeur est
interprétée comme une commande à exécuter
avant l'affichage de chaque invite (PS1). |
| PS3 | La valeur de cette variable est utilisée comme l'invite pour la commande select. Par défaut « '#? ' » |
| PS4 | La valeur est l'invite affichée avant que la commande soit affichée en echo quand l'option -x est activée ; par defaut « '+ ' ». |
| PWD | Renvoie le nom de répertoire courant défini par l'intégrée cd. |
| RANDOM | Chaque fois que cette variable est référencée, un entier entre 0 et 32767 est généré. Le fait d'assigner une valeur à cette variable réinitialise le générateur. |
| REPLY | Paramètre par défaut de l'intégrée read. |
| SECONDS | Renvoie le nombre de secondes écoulées depuis que le Shell est lancé. |
| SHELLOPTS | Une liste des options Shell activées, séparées par deux points( :). |
| SHLVL | Valeur augmentée de 1 chaque fois qu'une nouvelle instance de Bash est lancée. |
| TIMEFORMAT | Cette valeur est un paramètre utilisé pour formater le résultat de chronométrage des instructions exécutées dans un tube (pipeline) lorsque le mot réservé time est spécifié. |
| TMOUT | Défini à une valeur supérieure à zéro, TMOUT est considéré comme le temps imparti maximum à l'intégrée read.
Dans un Shell interactif, la valeur est considérée comme un nombre de
secondes durant lesquelles une saisie est attendue. Bash se termine
après ce laps de temps si aucune entrée n'est faite. |
| UID | Le nombre, le véritable identifiant, de l'usagé actif. |
Le Shell considère certains paramètres spécifiquement. Ces paramètres ne peuvent qu'être référencés ; leur affectation n'est pas permise.
Tableau 3.3. Les variables Bash spéciales
| Nom | Définition |
|---|---|
$* |
Est
remplacé par tous les paramètres positionnels, sauf le premier $0.
Quand l'expansion se produit entre guillemets, cela revient à avoir un
seul mot avec la valeur de chaque paramètre séparée par le premier
caractère de la variable spéciale IFS. |
$@ |
Est remplacé par tous les paramètres positionnels, sauf le premier $0. Quand l'expansion se produit entre guillemets, chaque paramètre est un mot à part entière. |
$# |
Renvoie le nombre de paramètres positionnels en décimal. |
$? |
Renvoie le statut d'exécution de l'instruction la plus récemment exécutée en avant-plan dans un tube. |
$- |
Renvoie les options déclarées lors de l'invocation de l'intégrée set, ou celles positionnées par le Shell lui-même (tel que -i). |
$$ |
Renvoie l'identifiant du process du Shell. |
$! |
Renvoie l'identifiant du process de la commande la plus récemment exécutée en tâche de fond (asynchrone). |
$0 |
Renvoie le nom du Shell ou du script Shell actif. |
$_ |
Au démarrage du Shell, contient le nom complet du fichier exécutable actif - script ou Shell - tel que passé dans la liste d'arguments. Ensuite, renvoie le dernier argument de la commande précédente après expansion. Et aussi valorisé avant chaque exécution de commande avec la valeur du chemin complet de cette commande, puis exporté dans l'environnement d'exécution. A la vérification de présence de mails, ce paramètre contient le nom du fichier de mails. |
![]() |
$* versus $@ |
|---|---|
|
L'implémentation de « $* » a toujours été un problème et aurait dû être remplacé pratiquement par le comportement de « $@ ». Dans presque tous les cas quand le programmeur utilise « $* », il veut dire « $@ ». « $* » peut être la cause de bugs et même de trou de sécurité dans votre programme. |
Les paramètres positionnels sont les mots qui suivent le nom d'un script Shell. Ils définissent les variables $1, $2, $3 etc. Autant que nécessaire, ces variables sont ajoutées dans un tableau interne. $# mémorise le nombre de paramètres, comme démontré dans ce simple script :
#!/bin/bash
# positional.sh
# Ce script lit 3 paramètres positionnels et les affiche.
POSPAR1="$1"
POSPAR2="$2"
POSPAR3="$3"
echo "$1 est le premier paramètre positionnel, \$1."
echo "$2 est le deuxième paramètre positionnel, \$2."
echo "$3 est le troisième paramètre positionnel, \$3."
echo
echo "Le nombre total de paramètres positionnels est $#."
A l'exécution on peut donner autant de paramètres que l'on veut :
franky ~>positional.shun deux trois quatre cinq
un est le premier paramètre positionnel, $1.
deux est le deuxième paramètre positionnel, $2
trois est le troisième paramètre positionnel, $3.
Le nombre total de paramètres positionnels est 5.franky ~>positional.shun deux
un est le premier paramètre positionnel, $1.
deux est le deuxième paramètre positionnel, $2
est le troisième paramètre positionnel, $3.
Le nombre total de paramètres positionnels est 2
Plus de précisions sur l'évaluation de ces paramètres au Chapitre 7, Les instructions de condition et à la Section 7, « L'intégrée shift ».
Quelques exemples sur les autres paramètres spéciaux :
franky ~>grepdictionary/usr/share/dict/words
dictionaryfranky ~>echo$_
/usr/share/dict/wordsfranky ~>echo$$
10662franky ~>mozilla &
[1] 11064franky ~>echo$!
11064franky ~>echo$0
bashfranky ~>echo$?
0franky ~>lsdoesnotexist
ls: doesnotexist: No such file or directoryfranky ~>echo$?
1franky ~>
En plus de rendre le script plus lisible, les variables vous permettent d'utiliser un même script dans divers environnements ou pour des finalités multiples. Prenez l'exemple suivant, un script très simple qui effectue une sauvegarde du répertoire racine de franky vers un serveur distant :
#!/bin/bash
# Ce script fait une sauvegarde de mon répertoire personnel.
cd /home
# Ceci crée le fichier archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1
# Avant supprimer l'ancien fichier bzip2. Redirige les erreurs parce que ceci en génère quand l'archive
# n'existe pas. Puis crée un nouveau fichier compressé.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar
# Copie le fichier vers un autre hôte - nous avons une clé ssh pour effectuer ce travail sans intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1
# Crée un marqueur temporel dans un fichier journal..
date > /home/franky/log/home_backup.log
echo backup succeeded > /home/franky/log/home_backup.log
#!/bin/bash
# Ce script fait une sauvegarde de mon répertoire racine.
# Modifier les valeurs des variables pour que le script tourne pour vous :
BACKUPDIR=/home
BACKUPFILES=franky
TARFILE=/var/tmp/home_franky.tar
BZIPFILE=/var/tmp/home_franky.tar.bz2
SERVER=bordeaux
REMOTEDIR=/opt/backup/franky
LOGFILE=/home/franky/log/home_backup.log
cd $BACKUPDIR
# Ceci crée le fichier d'archive
tar cf $TARFILE $BACKUPFILES > /dev/null 2>&1
# D'abord supprimer l'ancien fichier bzip2. Redirige les erreurs parce que ceci en génère quand l'archive
# n'existe pas. Puis crée un nouveau fichier compressé.
rm $BZIPFILE 2> /dev/null
bzip2 $TARFILE
# Copie le fichier vers un autre hôte - nous avons une clé ssh pour effectuer ce travail sans intervention.
scp $BZIPFILE $SERVER:$REMOTEDIR > /dev/null 2>&1
# Crée un marqueur temporel dans un fichier journal..
date > $LOGFILE
echo backup succeeded > $LOGFILE
![]() |
Répertoires volumineux et faible bande passante |
|---|---|
|
Tout le monde peut comprendre l'exemple ci-dessus, en utilisant un répertoire réduit et un hôte de son sous-réseau. En fonction de votre bande passante, de la taille du répertoire et de l'endroit du serveur distant, cela peut prendre un temps terriblement long de faire la sauvegarde. Pour les répertoires les plus volumineux et une bande passante faible, employez rsync pour garder les répertoires synchronisés entre les 2 machines. |
Le caractère Echap sert à inhiber la signification spéciale d'un caractère unique. Le slash inversé sans guillemets, \, est utilisé comme caractère Echap dans Bash. Il préserve le sens littéral du caractère le suivant, à l'exception de saut de ligne. Si un caractère 'saut de ligne' apparaît juste après le slash inversé, cela marque la continuation de la ligne quand elle est plus longue que la largeur du terminal ; le slash inversé est ôté du flot entré et donc en fait ignoré.
franky ~>date=20021226franky ~>echo$date
20021226franky ~>echo\$date
$date
Les apostrophes (') sont utilisées pour préserver la valeur littérale des caractères enfermés entre apostrophes. Une apostrophe ne peut pas être enfermée entre apostrophes, même si elle est précédée par un slash inversée.
Continuons avec l'exemple précédent :
franky ~>echo'$date'
$date
Avec les guillemets la valeur littérale de tous les caractères est préservée, sauf pour le $, les apostrophes inversées (``) et le slash inversé.
Le $ et `` conservent leur sens spécial à l'intérieur de guillemets.
Un guillemet peut être protégé à l'intérieur de guillemets en le faisant précéder par \.
franky ~>echo"$date"
20021226franky ~>echo"`date`"
Sun Apr 20 11:22:06 CEST 2003franky ~>echo"I'd say: \"Go for it!\""
I'd say: "Go for it !"franky ~>echo"\"More input>"franky ~>echo"\\"
\
Après que la commande ait été décomposée en éléments (voir la Section 4.1.1, « La syntaxe Shell »), ces éléments ou mots sont interprétés ou autrement dit résolus. Il y a 8 sortes d'expansion effectuées, lesquelles vont être traitées dans les sections suivantes dans l'ordre où le processus opère.
Après toutes les sortes d'expansions effectuées, guillemets et apostrophes sont éliminés.
L'expansion d'accolade est un mécanisme par lequel des chaînes peuvent être arbitrairement générées. Les patrons sujets à expansion prennent la forme d'un préfixe optionnel, suivi d'une série de chaînes séparées par des virgules, le tout à l'intérieur d'accolades, suivi par un suffixe optionnel. Le préfixe enrichit chaque chaîne au début, puis à son tour le suffixe enrichit la fin, résultant en une expansion de gauche à droite.
L'expansion d'accolades peut être imbriquée. Le résultat des chaînes ainsi obtenues n'est pas trié ; l'ordre de gauche à droite est préservé.
franky ~>echosp{el,il,al}l
spell spill spall
Si un mot commence par un tilde non protégé (« ~ »),
tous les caractères jusqu'au premier slash non-protégé (ou tous les
caractères si il n'y a pas de slash non-protégé) sont considérés comme
un préfixe tilde. Si aucun des
caractères dans le préfixe tilde n'est protégé, ces caractères qui
suivent le tilde sont considérés comme un nom de connection possible.
Si ce nom de connection est la chaîne nulle, le tilde est remplacé par
la valeur de la variable Shell HOME. Si HOME
n'est pas défini, le répertoire racine de l'utilisateur exécutant le
Shell est utilisé à la place. Sinon, le préfixe tilde est remplacé par
le répertoire racine associé au nom de connection spécifié.
Si le préfixe tilde est « ~+ », la valeur de la variable Shell PWD remplace le préfixe tilde. Si le préfixe tilde est « ~- », la valeur de la variable Shell OLDPWD, si définie, s'y substitue.
Si le nom de connection est invalide, ou si l'expansion de tilde échoue, le mot est laissé tel quel.
franky ~>exportPATH="$PATH:~/testdir"
~/testdir sera interprété en $HOME/testdir, donc si $HOME est /var/home/franky, le répertoire /var/home/franky/testdir sera ajouté au contenu de la variable PATH.
Le caractère « $ » introduit l'expansion de paramètre, la substitution de commande ou l'expansion arithmétique. Le nom du paramètre - ou symbole - à interpréter peut être enchâssé entre accolades. Elles sont optionnelles mais utiles à la séparation des caractères du symbole à interpréter de ceux suivant immédiatement.
Vous êtes certainement familier avec l'expansion de paramètre directe, parce qu'elle est fréquente même dans les cas les plus simples, tel que celui ci-dessus ou le suivant :
franky ~>echo$SHELL
/bin/bash
Voici un exemple d'expansion indirecte :
franky ~>echo${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
Notez que cela ne donne pas la même chose que echo $N*.
La construction suivante permet la création du nom de variable si il n'existe pas :
franky ~>echo$FRANKYfranky ~>echo${FRANKY:=Franky}
Franky
Nous approfondirons l'utilisation de l'accolade dans le traitement des variables au Chapitre 10, Un peu plus sur les variables. Les pages info de Bash fournissent aussi d'autres informations.
La substitution de commande permet de remplacer la commande elle-même par son résultat. La substitution de commande survient quand une commande est enchâssée ainsi :
ou ainsi avec les apostrophes inversées :
franky ~>echo`date`
Thu Feb 6 10:06:20 CET 2003
L'expansion arithmétique permet l'évaluation d'une expression arithmétique et la substitution par le résultat. Le format pour l'expansion arithmétique est :
L'évaluation d'une expression arithmétique est faite en entiers de taille fixe sans contrôle de dépassement - bien que la division par zéro soit détectée comme une erreur. Les opérateurs sont à peu près les mêmes que dans le langage de programmation C. Par ordre de priorité décroissante, la liste ressemble à ceci :
Tableau 3.4. Opérateurs arithmétiques
| Opérateur | sens |
|---|---|
| VAR++ et VAR-- | variable: post-incrément et post-décrément |
| ++VAR et --VAR | variable: pré-incrément et pré-décrément |
| - et + | moins et plus |
| ! et ~ | négation logique et bit à bit |
| ** | exponentiation |
| *, / et % | multiplication, division, reste |
| + et - | addition, soustraction |
| << and >> | Décalage des bits à gauche ou à droite |
| <=, >=, < et > | opérateurs de comparaison |
| == et != | égalité et inégalité |
| & | ET logique |
| ^ | OU logique exclusif |
| | | OU logique |
| && | ET logique |
| || | OU logique |
| expr ? expr : expr | évaluation conditionnelle |
| =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^= et |= | affectations |
| , | séparateur entre expressions |
Cependant, ceci ne fait qu'évaluer l'EXPRESSION, et ne teste pas :
franky ~>echo$[365*24]
8760
Voir Section 1.2.2, « Comparaisons numériques », entre autres, pour des exemples pratiques de scripts.
La substitution de processus
est effectuée par les systèmes qui admettent les tubes (pipes) nommés
(FIFO : NdT=First In First Out=premier entré, premier sorti) ou la
méthode /dev/fd de nommage de fichiers ouverts. Ca se présente sous la forme de
Plus de détails à la Section 2.3, « Redirection et descripteurs de fichiers ».
Le Shell recherche dans le résultat de l'expansion de paramètre, de la substitution de commande, et de l'expansion arithmétique des mots qui n'ont pas été interprétés du fait des guillemets.
Le Shell traite chaque caractère de $IFS
comme un délimiteur, et découpe le résultat des
autres expressions en mots sur la base de ces caractères. Si IFS n'est pas déclaré, ou si il vaut exactement « '<space><tab><newline>' », sa valeur par défaut, alors toute suite de caractères IFS sert à délimiter les mots. Si IFS Si IFS a une valeur autre que celle par défaut, alors les suites d'« espace » et « Tab » sont ignorées au début et à la fin du mot, du moment que l'espace est inclut dans IFS (un caractère espace IFS). Tout caractère dans IFS qui n'est pas un espace IFS, accolé à un caractère espace IF, délimite un champ. Une suite de caractère espace IFS est aussi traitée comme un délimiteur. Si la valeur de IFS est nulle, le découpage en mots n'intervient pas.
Un argument vide (« "" » or « '' ») est conservé. Un argument ayant une valeur nulle, suite à l'expansion d'un paramètre, est éliminé. Si un paramètre non valorisé est interprété à l'intérieur de guillemets, il en résulte un argument nul qui est conservé.
![]() |
Expansion et découpage en mots |
|---|---|
|
Si aucune expansion ne se produit, aucun découpage n'est effectué |
Après le découpage en mots, à moins que l'option -f ait été utilisée (voir Section 3.2, « Débugger qu'une partie du script »), Bash scanne chaque mot pour les caractères « * », « ? », et « [ » Si l'un de ces caractères apparaît, alors le mot est considéré comme étant un PATRON,
et est remplacé par la liste des noms de fichiers correspondants au
patron triée par ordre alphabétique. Si aucun nom de fichier ne
correspond, et que l'option Shell nullglob est désactivée, le mot est laissé en l'état. Si l'option nullglob est activée, et qu'aucune correspondance n'est trouvée, le mot est éliminé. Si l'option Shell nocaseglob
est activée, la correspondance est recherchée sans
considérer la casse des caractères alphabétiques.
La variable Shell GLOBIGNORE peut être utilisée pour restreindre l'ensemble de fichiers en correspondance avec le patron. Si GLOBIGNORE est activé, les noms qui correspondent à l'un des patrons dans GLOBIGNORE sont retirés de la liste de correspondance. Les noms de fichiers . et .. sont toujours ignorés, même si GLOBIGNORE est désactivé. Cependant, déclarerGLOBIGNORE a pour effet d'activer l'option Shell dotglob, donc tous les autres fichiers commençant par « . » correspondront. Pour garder la possibilité d'ignorer les fichiers commençant par « . », indiquer « .* » comme étant un des patrons à ignorer dans GLOBIGNORE. L'option dotglob est désactivé quand GLOBIGNORE n'est pas déclaré.
Un alias permet de substituer un mot à une chaîne de caractère quand il est utilisé comme premier mot d'une commande simple. Le Shell maintient une liste d'alias qui sont déclarés ou invalidés avec les intégrées alias et unalias . Saisir alias sans options pour afficher une liste des alias connus du Shell courant.
franky: ~>alias
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias PAGER='less -r'
alias Txterm='export TERM=xterm'
alias XARGS='xargs -r'
alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias e='vi'
alias egrep='grep -E'
alias ewformat='fdformat -n /dev/fd0u1743; ewfsck'
alias fgrep='grep -F'
alias ftp='ncftp -d15'
alias h='history 10'
alias fformat='fdformat /dev/fd0H1440'
alias j='jobs -l'
alias ksane='setterm -reset'
alias ls='ls -F --color=auto'
alias m='less'
alias md='mkdir'
alias od='od -Ax -ta -txC'
alias p='pstree -p'
alias ping='ping -vc1'
alias sb='ssh blubber'
alias sl='ls'
alias ss='ssh octarine'
alias sss='ssh -C server1.us.xalasys.com'
alias sssu='ssh -C -l root server1.us.xalasys.com'
alias tar='gtar'
alias tmp='cd /tmp'
alias unaliasall='unalias -a'
alias vi='eval `resize`;vi'
alias vt100='export TERM=vt100'
alias which='type'
alias xt='xterm -bg black -fg white &'franky ~>
Les alias sont utiles pour spécifier une version par défaut d'une commande qui existe en plusieurs versions sur le système, ou pour spécifier les options par défaut d'une commande. Un autre emploi des alias est de permettre la correction des fautes de frappes.
Les alias ne sont pas remplacés quand le Shell n'est pas interactif, sauf si l'option expand_aliases est activée par l'intégrée shopt shell.
Un alias est créé par l'intégrée alias . Pour une déclaration permanente, ajouter la commande alias dans l'un de vos scripts d'initialisation ; si vous l'entrez seulement sur la ligne de commande, il sera connu que durant la session.
franky ~>aliasdh='df -h'franky ~>dh
Filesystem Size Used Avail Use% Mounted on
/dev/hda7 1.3G 272M 1018M 22% /
/dev/hda1 121M 9.4M 105M 9% /boot
/dev/hda2 13G 8.7G 3.7G 70% /home
/dev/hda3 13G 5.3G 7.1G 43% /opt
none 243M 0 243M 0% /dev/shm
/dev/hda6 3.9G 3.2G 572M 85% /usr
/dev/hda5 5.2G 4.3G 725M 86% /varfranky ~>unaliasdhfranky ~>dh
bash: dh: command not foundfranky ~>
Bash lit toujours au moins une ligne complète saisie avant d'exécuter une des commandes de cette ligne. L'alias est interprété quand la commande est lue, non pas quand elle est exécutée. De ce fait, une définition d'alias apparaissant sur la même ligne qu'une autre commande ne prendra effet qu'à la lecture de la ligne suivante. Les commandes suivant la définition de l'alias sur la ligne ne seront pas affectées par le nouvel alias. Ce comportement joue aussi quand une fonction est exécutée. Un alias est interprété quand la définition d'une fonction est lue, pas quand la fonction est exécutée, parce que la définition de fonction est elle-même une commande composée. En conséquence, l'alias définit dans une fonction n'est pas utilisable tant que la fonction n'a pas été exécutée. En toute sécurité, toujours définir les alias sur des lignes séparées, et ne pas employer alias dans des commandes composées.
Les processus enfants n'héritent pas des alias. Bourne shell (sh) ne reconnaît pas les alias.
Plus sur les fonctions au Chapitre 11, Fonctions.
![]() |
Les fonctions sont plus rapides |
|---|---|
|
Les alias sont recherchés après les fonctions et donc leur résolution est plus lente. Alors que les alias sont plus faciles à comprendre, les fonctions Shell sont préférées aux alias pour la plupart des usages. |
Utilisez l'option -o de set pour afficher toutes les options Shell :
willy:~>set-o
allexport off
braceexpand on
emacs on
errexit off
hashall on
histexpand on
history on
ignoreeof off
interactive-comments on
keyword off
monitor on
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physical off
posix off
privileged off
verbose off
vi off
xtrace off
Les options Shell peuvent être modifiées soit par rapport à celles par défaut à l'appel du Shell, soit au cours des traitements Shell. Elles peuvent être aussi intégrées aux fichiers de configuration des ressources Shell.
La commande suivante exécute un script en mode compatible POSIX :
willy:~/scripts>bash--posixscript.sh
willy:~/test>set-onoclobberwilly:~/test>touchtestwilly:~/test>date >test
bash: test: cannot overwrite existing filewilly:~/test>set+onoclobberwilly:~/test>date >test
L'exemple ci-dessus montre l'usage de l'option noclobber ,
qui évite que les fichiers existants soient écrasés par les opérations
de redirection. La même chose joue pour les options à 1 caractère, par
exemple -u, qui, activée, traite les
variables non déclarées comme des erreurs, et quitte un Shell
non-interactif quand survient une telle erreur :
willy:~>echo$VARwilly:~>set-uwilly:~>echo$VAR
bash: VAR: unbound variable
Cette option est aussi utile pour détecter des valeurs incorrectes affectées à des variables : la même erreur se produira aussi, par exemple, quand une chaîne de caractère est affectée à une variable qui a été déclarée explicitement comme devant contenir une valeur numérique.
willy:~/testdir>set-onoglobwilly:~/testdir>touch*willy:~/testdir>ls-l*
-rw-rw-r-- 1 willy willy 0 Feb 27 13:37 *
Résumé
Dans ce chapitre nous abordons :
L'utilisation des expressions régulières
Les métacaractères des expressions régulières
Trouver des patrons dans les fichiers et autres résultats
Les intervalles de caractères et les classes en Bash
Tableau 4.1. Opérateurs d'expression régulière
| Opérateur | Effet |
|---|---|
| . | Correspond à tout caractère |
| ? | L'élément précédent est optionnel et sera présent au plus une fois. |
| * | L'élément précédent sera présent zéro fois ou plus. |
| + | L'élément précédent sera présent une fois ou plus. |
| {N} | L'élément précédent sera présent exactement N fois. |
| {N,} | L'élément précédent sera présent N ou plus de fois. |
| {N,M} | L'élément précédent sera présent au moins N fois, mais pas plus de M fois. |
| - | représente l'intervalle si il n'est pas premier ou dernier dans une liste ou le dernier point d'un intervalle dans une liste. |
| ^ | Correspond à une chaîne vide au début de la ligne ; représente aussi les caractères ne se trouvant pas dans l'intervalle d'une liste. |
| $ | Correspond à la chaîne vide à la fin d'une ligne. |
| \b | Correspond à la chaîne vide au début ou à la fin d'un mot. |
| \B | Correspond à la chaîne vide à l'intérieur d'un mot. |
| \< | Correspond à la chaîne vide au début d'un mot. |
| \> | Correspond à la chaîne vide à la fin d'un mot. |
grep cherche dans les fichiers en entrée les lignes qui contiennent une correspondance dans une liste donnée de patrons. Quand il trouve une correspondance dans une ligne, il copie la ligne sur la sortie standard (par défaut), ou sur tout autre type de sortie que vous avez requise par les options.
cathy ~>greproot/etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologincathy ~>grep-nroot/etc/passwd
1:root:x:0:0:root:/root:/bin/bash
12:operator:x:11:0:operator:/root:/sbin/nologincathy ~>grep-vbash/etc/passwd| grep-vnologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
news:x:9:13:news:/var/spool/news:
mailnull:x:47:47::/var/spool/mqueue:/dev/null
xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/false
rpc:x:32:32:Portmapper RPC user:/:/bin/false
nscd:x:28:28:NSCD Daemon:/:/bin/false
named:x:25:25:Named:/var/named:/bin/false
squid:x:23:23::/var/spool/squid:/dev/null
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false
apache:x:48:48:Apache:/var/www:/bin/falsecathy ~>grep-cfalse/etc/passwd
7cathy ~>grep-ips~/.bash*| grep-vhistory
/home/cathy/.bashrc:PS1="\[\033[1;44m\]$USER is in \w\[\033[0m\] "
Puis elle affiche le numéro des lignes contenant cette chaîne.
Puis elle compte le nombre de comptes qui ont /bin/false comme Shell.
Maintenant voyons ce que nous pouvons faire d'autre avec grep et des expressions régulières.
![]() |
Si vous n'êtes pas sous Linux |
|---|---|
|
Nous utilisons GNU grep dans ces exemples, parce qu'il admet les expressions régulières étendues. GNU grep
se trouve par défaut sur les systèmes Linux. Si vous
travaillez sur un système propriétaire, vérifiez
avec l'option |
cathy ~>grep^root/etc/passwd
root:x:0:0:root:/root:/bin/bash
cathy ~>grep:$/etc/passwd
news:x:9:13:news:/var/spool/news:
cathy ~>grepexport~/.bashrc| grep'\<PATH'
export PATH="/bin:/usr/lib/mh:/lib:/usr/bin:/usr/local/bin:/usr/ucb:/usr/dbin:$PATH"
Pareillement, \> cherche à la fin d'un mot.
cathy ~>grep-w//etc/fstab
LABEL=/ / ext3 defaults 1 1
Si cette option est absente, toutes les lignes de la table du système de fichiers seront affichées.
cathy ~>grep[yf]/etc/group
sys:x:3:root,bin,adm
tty:x:5:
mail:x:12:mail,postfix
ftp:x:50:
nobody:x:99:
floppy:x:19:
xfs:x:43:
nfsnobody:x:65534:
postfix:x:89:
Dans cet exemple, toutes les lignes contenant soit « y » ou « f » sont affichées.
cathy ~>touch"*"cathy ~>ls"*"
*
cathy ~>ls-ld[a-cx-z]*
drwxr-xr-x 2 cathy cathy 4096 Jul 20 2002 app-defaults/
drwxrwxr-x 4 cathy cathy 4096 May 25 2002 arabic/
drwxrwxr-x 2 cathy cathy 4096 Mar 4 18:30 bin/
drwxr-xr-x 7 cathy cathy 4096 Sep 2 2001 crossover/
drwxrwxr-x 3 cathy cathy 4096 Mar 22 2002 xml/
![]() |
Note |
|---|---|
|
La commande grep peut faire bien plus que les quelques opérations vues ici ; nous l'avons juste utilisée à titre d'illustration pour les expressions régulières. La version GNU de grep est fourni avec un bon lot de documentations, qu'il vous est recommandé de lire ! |
Ces exercices vous aideront à maîtriser les expressions régulières.
Depuis le répertoire /etc/group, afficher toutes les lignes commençant avec la chaîne « daemon ».
Imprimer toutes les lignes de ce même fichier qui ne contiennent pas la chaîne.
Mettre ces commandes dans un script Shell qui générera un résultat lisible.
Avec la table des fichiers du système (/etc/fstab par exemple), lister les disques locaux.
Afficher les fichiers de configuration de /etc qui contiennent des chiffres dans leur nom.
Résumé
À la fin de ce chapitre vous aurez connaissance des sujets suivants :
Qu'est-ce que sed ?
L'usage en mode immédiat de sed
Les expressions régulières et l'édition de flot
Utiliser des commandes sed dans un script
![]() |
Ceci est une introduction |
|---|---|
|
Ces explications sont loin d'être complètes et certainement pas faites pour être considérées comme le manuel utilisateur de sed. Ce chapitre est seulement inclus afin de montrer quelques aspects intéressants dans les chapitres suivants, et parce que tout utilisateur avancé devrait avoir une connaissance de base de cet éditeur. Pour plus d'informations, se référer aux pages man et info de sed. |
Le programme sed peut effectuer substitutions et suppressions avec des expressions régulières, comme celles utilisées avec la commande grep ; voir Section 2, « Exemples en utilisant grep ».
Les commandes d'édition sont similaires à celles utilisées dans l'éditeur vi :
Tableau 5.1. Commandes d'édition Sed
| Commande | Effet |
|---|---|
| a\ | Ajoute le texte sous la ligne courante. |
| c\ | Remplace le texte de la ligne courante par le nouveau texte. |
| d | Supprime le texte. |
| i\ | Insère le texte au dessus de la ligne courante. |
| p | Imprime le texte. |
| r | Lit un fichier. |
| s | Cherche et remplace du texte. |
| w | Ecrit dans un fichier. |
| Option | Effet |
|---|---|
-e SCRIPT |
Ajoute les commandes de SCRIPT au jeu de commandes à exécuter sur le flot en entrée. |
-f |
Ajoute les commandes contenues dans le fichier SCRIPT-FILE au jeu de commandes à exécuter sur le flot d'entrée. |
-n |
Mode Silencieux. |
-V |
Affiche les informations de version et s'arrête. |
Voici notre fichier texte d'exemple :
sandy ~>cat-nexemple
1 This is the first line of an example text.
2 It is a text with erors.
3 Lots of erors.
4 So much erors, all these erors are making me sick.
5 This is a line not containing any errors.
6 This is the last line.sandy ~>
sandy ~>sed'/erors/p'exemple
This is the first line of an example text.
It is a text with erors.
It is a text with erors.
Lots of erors.
Lots of erors.
So much erors, all these erors are making me sick.
So much erors, all these erors are making me sick.
This is a line not containing any errors.
This is the last line.sandy ~>
sandy ~>sed-n'/erors/p'exemple
It is a text with erors.
Lots of erors.
So much erors, all these erors are making me sick.sandy ~>
sandy ~>sed'/erors/d'exemple
This is the first line of an example text.
This is a line not containing any errors.
This is the last line.sandy ~>
La commande d a pour effet d'exclure des lignes de l'affichage.
Les lignes dont le début correspond à un patron donné et la fin à un autre sont affichées comme ça :
sandy ~>sed-n'/^This.*errors.$/p'exemple
This is a line not containing any errors.sandy ~>
sandy ~>sed'2,4d'exemple
This is the first line of an example text.
This is a line not containing any errors.
This is the last line.sandy ~>
sandy ~>sed'3,$d'exemple
This is the first line of an example text.
It is a text with erors.sandy ~>
Ceci affiche seulement les 2 premières lignes du fichier exemple.
sandy ~>sed-n'/a text/,/This/p'exemple
It is a text with erors.
Lots of erors.
So much erors, all these erors are making me sick.
This is a line not containing any errors.sandy ~>
sandy ~>sed's/erors/errors/'exemple
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these erors are making me sick.
This is a line not containing any errors.
This is the last line.sandy ~>
sandy ~>sed's/erors/errors/g'exemple
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these errors are making me sick.
This is a line not containing any errors.
This is the last line.sandy ~>
Pour insérer une chaîne au début de chaque ligne du fichier, par exemple pour citer :
sandy ~>sed's/^/> /'exemple
> This is the first line of an example text.
> It is a text with erors.
> Lots of erors.
> So much erors, all these erors are making me sick.
> This is a line not containing any errors.
> This is the last line.sandy ~>
Insérer une chaîne à la fin de chaque ligne :
sandy ~>sed's/$/EOL/'exemple
This is the first line of an example text.EOL
It is a text with erors.EOL
Lots of erors.EOL
So much erors, all these erors are making me sick.EOL
This is a line not containing any errors.EOL
This is the last line.EOLsandy ~>
Commandes de recherche et remplacement multiples sont séparées avec l'option -e :
sandy ~>sed-e's/erors/errors/g'-e's/last/final/g'exemple
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these errors are making me sick.
This is a line not containing any errors.
This is the final line.sandy ~>
![]() |
Plus d'exemples |
|---|---|
|
Plein d'exemples sed se trouvent dans les scripts de démarrage de votre machine, lesquels sont d'ordinaire dans
|
sandy ~>catscript.sed
1i\
<html>\
<head><title>sed generated html</title></head>\
<body bgcolor="#ffffff">\
<pre>
$a\
</pre>\
</body>\
</html>sandy ~>cattxt2html.sh
#!/bin/bash
# Ceci est un script simple pour convertir du texte en HTML.
# D'abord nous éliminons tous les caractères de saut de ligne, de sorte que l'ajout
# ne se produise qu'une fois, puis nous remplaçons les sauts de ligne.
echo "converting $1..."
SCRIPT="/home/sandy/scripts/script.sed"
NAME="$1"
TEMPFILE="/var/tmp/sed.$PID.tmp"
sed "s/\n/^M/" $1 | sed -f $SCRIPT | sed "s/^M/\n/" > $TEMPFILE
mv $TEMPFILE $NAME
echo "done."sandy ~>
$1 stocke le premier paramètre d'une commande donnée, dans ce cas le nom du fichier à convertir :
sandy ~>cattest
line1
line2
line3
Plus sur les paramètres positionnels au Chapitre 7, Les instructions de condition.
sandy ~>txt2html.shtest
converting test...
done.sandy ~>cattest
<html>
<head><title>sed generated html</title></head>
<body bgcolor="#ffffff">
<pre>
line1
line2
line3
</pre>
</body>
</html>sandy ~>
Ce n'est pas vraiment la bonne méthode ; c'est juste un exemple pour démontrer le potentiel de sed. Voir la Section 3, « Les variables Gawk » pour une solution plus décente à ce problème, avec les constructions awk BEGIN et END.
![]() |
sed facile |
|---|---|
|
Les éditeurs sophistiqués, permettant la mise en relief de la syntaxe, reconnaissent la syntaxe sed. Cela peut être d'une grande aide si vous avez tendance à oublier des slashs inversés. |
Résumé
Dans ce chapitre nous aborderons :
Qu'est-ce que gawk ?
L'emploi de commandes gawk sur la ligne de commande
Comment formater du texte avec gawk
Comment gawk utilise les expressions régulières
Gawk dans les scripts
Gawk et les variables
![]() |
Pour s'amuser un peu |
|---|---|
|
Comme pour sed, de nombreux livres ont été écrits sur les nombreuses versions de awk. Cette introduction est loin d'être complète et vise seulement à faire comprendre les exemples des chapitres suivants.. Pour approfondir, le mieux est de débuter avec la documentation qui accompagne GNU awk : « GAWK: Effective AWK Programming: A User's Guide for GNU Awk ». |
Gawk est la version GNU du programme couramment disponible sous UNIX awk , un autre éditeur par lot populaire. Du fait que le programme awk n'est souvent qu'un lien vers gawk, nous nous y référerons en tant que awk.
![]() |
Qu'est-ce que cela veut dire ? |
|---|---|
|
dans les années 1970, 3 programmeurs se sont joints pour créer le langage. Leurs noms étaient Aho, Kernighan et Weinberger. Ils prirent la première lettre de chacun de leur nom pour nommer ce langage. Donc le nom du langage aurait aussi bien pu être « wak ». |
Il y a plusieurs façons de lancer awk. Si le programme est court, il est plus facile de le lancer depuis la ligne de commande :
Si de multiples changements doivent être fait, peut-être régulièrement sur de multiples fichiers, il est plus facile de mémoriser les commandes awk dans un script. Ce qui se lit comme ceci :
La commande print de awk affiche les données sélectionnées depuis le fichier d'entrée.
Quand awk lit une ligne d'un fichier, il divise la ligne en champs basé sur le séparateur de champs en entrée, FS, qui est une variable awk (voir Section 3.2, « Les séparateurs de résultat »). Cette variable est prédéfinie avec un ou plusieurs espaces et tabulations.
Les variables $1, $2, $3, ..., $N stockent les valeurs du premier, second, troisième jusqu'au dernier champ de la ligne traitée. La variable $0
(zéro) stocke la valeur de la ligne entière. Ceci est illustré dans
l'image ci-dessous, où nous voyons 6 colonnes dans l'affichage de la
commande df :
Dans le résultat de ls -l, il y a 9 colonnes. L'instruction print utilise ces champs comme ceci :
kelly@octarine ~/test>ls-l| awk'{ print $5 $9 }'
160orig
121script.sed
120temp_file
126test
120twolines
441txt2html.shkelly@octarine ~/test>
Sans formater, avec seulement le séparateur de résultat, l'affichage est peu lisible. En insérant quelques tabulations et une chaîne pour indiquer la nature du champs ce sera bien mieux :
kelly@octarine ~/test>ls-ldh*| grep-vtotal| \
awk'{ print "Size is " $5 " bytes for " $9 }'
Size is 160 bytes for orig
Size is 121 bytes for script.sed
Size is 120 bytes for temp_file
Size is 126 bytes for test
Size is 120 bytes for twolines
Size is 441 bytes for txt2html.shkelly@octarine ~/test>
Le slash inversé dans cet exemple marque la continuation de la ligne. Voir Section 3.2, « Le caractère Echap (escape) ».
On peut prendre en compte autant de colonnes que l'on veut et même bouleverser l'ordre. Dans l'exemple ci-dessous on en trouve la démonstration qui affiche les partitions les plus critiques :
kelly@octarine ~>df-h| sort-rnk5| head-3| \
awk'{ print "Partition " $6 "\t: " $5 " full!" }'
Partition /var : 86% full!
Partition /usr : 85% full!
Partition /home : 70% full!kelly@octarine ~>
Le tableau ci-dessous donne un aperçu des caractères spéciaux de formatage :
Tableau 6.1. Caractères de formatage pour gawk
| Séquence | sens |
|---|---|
| \a | sonnerie |
| \n | Saut de ligne |
| \t | Tabulation |
Une expression régulière peut être utilisée comme patron en l'enfermant entre slashs. L'expression régulière est alors comparée à chaque enregistrement de texte. La syntaxe est celle-ci :
L'exemple suivant affiche seulement les informations des disques locaux, les systèmes de fichiers réseaux n'y sont pas :
kelly is in ~>df-h| awk'/dev\/hd/ { print $6 "\t: " $5 }'
/ : 46%
/boot : 10%
/opt : 84%
/usr : 97%
/var : 73%
/.vol1 : 8%kelly is in ~>
Le Slash doit être protégé, parce qu'il a un sens spécial pour le programme awk.
kelly is in /etc>ls-l| awk'/\<(a|x).*\.conf$/ { print $9 }'
amd.conf
antivir.conf
xcdroast.conf
xinetd.confkelly is in /etc>
Afin de faire précéder le résultat par un commentaire, employer l'instruction BEGIN :
kelly is in /etc>ls-l| \
awk'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.confkelly is in /etc>
kelly is in /etc>ls-l| \
awk'/\<[a|x].*\.conf$/ { print $9 } END { print \
"Can I do anything else for you, mistress?" }'
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf
Can I do anything else for you, mistress?kelly is in /etc>
Au fur et à mesure que les commandes deviennent complexes, vous voudrez les mémoriser dans un script, pour être réemployées. Un script awk contient des instructions awk définissant des patrons et des actions.
Pour illustrer nous allons produire un rapport qui affiche nos partitions les plus pleines. Voir Section 2.2, « Formater les champs ».
kelly is in ~>catdiskrep.awk
BEGIN { print "*** WARNING WARNING WARNING ***" }
/\<[8|9][0-9]%/ { print "Partition " $6 "\t: " $5 " full!" }
END { print "*** Donnez de l'argent pour un nouveau disque VITE ! ***" }
kelly is in ~> df -h | awk -f diskrep.awk
*** WARNING WARNING WARNING ***
Partition /usr : 97% full!
*** Donnez de l'argent pour un nouveau disque VITE ! ***kelly is in ~>
awk d'abord affiche le message de début, puis formate toutes les lignes qui contiennent un 8 ou un 9 au début de chaque mot, suivi par un autre chiffre et le signe de pourcentage. Un message final est ajouté.
![]() |
Mise en relief de la syntaxe |
|---|---|
|
Awk est un langage de programmation . Sa syntaxe est reconnue par la plupart des éditeurs qui font la mise en relief de la syntaxe comme pour d'autres langages tel que C, Bash, HTML, etc. |
Tandis que awk traite le fichier en entrée, il utilise plusieurs variables. Certaines sont modifiables, d'autres sont en lecture.
Le séparateur de champs, qui est soit un simple caractère, soit une expression régulière, contrôle la façon dont awk découpe l'enregistrement entré en champs. L'enregistrement en entrée est examiné à la recherche de séquences de caractères qui correspondent au séparateur défini ; les champs eux-mêmes sont les textes entre chaque séparateur.
kelly is in ~>awk'BEGIN { FS=":" } { print $1 "\t" $5 }'/etc/passwd
--output omitted--
kelly Kelly Smith
franky Franky B.
eddy Eddy White
willy William Black
cathy Catherine the Great
sandy Sandy Li Wongkelly is in ~>
Dans un script awk, cela ressemblerait à ça :
kelly is in ~>catprintnames.awk
BEGIN { FS=":" }
{ print $1 "\t" $5 }kelly is in ~>awk-fprintnames.awk /etc/passwd
--output omitted--
« Sandy L. Wong, 64 Zoo St., Antwerp, 2000X »
Vous écrivez une commande ou un script, qui affiche le nom de la personne dans cet enregistrement :
Mais une personne pourrait avoir un doctorat, et ça pourrait s'écrire comme ça :
« Sandy L. Wong, Doctorat, 64 Zoo St., Antwerp, 2000X »
Le séparateur de champs en entrée est par défaut un ou des espaces ou des tabulations.
Les champs sont habituellement séparés par des espaces dans le résultat. Ceci est visible quand vous employez la syntaxe correcte pour la commande print où les paramètres sont séparés par des virgules :
kelly@octarine ~/test>cattest
record1 data1
record2 data2kelly@octarine ~/test>awk'{ print $1 $2}'test
record1data1
record2data2kelly@octarine ~/test>awk'{ print $1, $2}'test
record1 data1
record2 data2kelly@octarine ~/test>
Le résultat d'une instruction print est appelée un enregistrement de résultat. Chaque commande print produit un enregistrement de résultat, et ajoute une chaîne appelée le séparateur d'enregistrement de résultat, ORS (NdT : output record separator). La valeur par défaut de cette variable est « \n », le caractère saut de ligne. Donc, chaque instruction print génère une ligne distincte.
kelly@octarine ~/test>awk'BEGIN { OFS=";" ; ORS="\n-->\n" } \
{ print $1,$2}'test
record1;data1
-->
record2;data2
-->kelly@octarine ~/test>
L'intégré NR stocke le nombre d'enregistrements qui sont traités.
Il est incrémenté après la lecture d'une nouvelle ligne d'entrée. Vous
pouvez l'utiliser à la fin pour compter le nombre total
d'enregistrements, ou à chaque enregistrement de résultat :
kelly@octarine ~/test>catprocessed.awk
BEGIN { OFS="-" ; ORS="\n--> done\n" }
{ print "Record number " NR ":\t" $1,$2 }
END { print "Number of records processed: " NR }kelly@octarine ~/test>awk-fprocessed.awk test
Record number 1: record1-data1
--> done
Record number 2: record2-data2
--> done
Number of records processed: 2
--> donekelly@octarine ~/test>
En plus des variables intégrées, vous pouvez définir les vôtres. Quand awk rencontre une référence à une variable qui n'existe pas (qui n'est pas prédéfinie), la variable est créée et initialisée à une chaîne nulle. Pour toutes les références suivantes, la valeur de la variable est la dernière valeur affectée. Une variable peut être une chaîne ou une valeur numérique. Le contenu des champs en entrée peut aussi être affecté à une variable.
kelly@octarine ~>catrevenues
20021009 20021013 consultancy BigComp 2500
20021015 20021020 training EduComp 2000
20021112 20021123 appdev SmartComp 10000
20021204 20021215 training EduComp 5000kelly@octarine ~>cattotal.awk
{ total=total + $5 }
{ print "Send bill for " $5 " dollar to " $4 }
END { print "---------------------------------\nTotal revenue: " total }kelly@octarine ~>awk-ftotal.awk test
Send bill for 2500 dollar to BigComp
Send bill for 2000 dollar to EduComp
Send bill for 10000 dollar to SmartComp
Send bill for 5000 dollar to EduComp
---------------------------------
Total revenue: 19500kelly@octarine ~>
Les raccourcis de type C comme VAR+= value sont aussi acceptés.
L'exemple de la Section 3.2, « Ecrire des fichiers de résultat » devient bien plus facile quand on utilise un script awk :
kelly@octarine ~/html>catmake-html-from-text.awk
BEGIN { print "<html>\n<head><title>Awk-generated HTML</title></head>\n<body bgcolor=\"#ffffff\">\n<pre>" }
{ print $0 }
END { print "</pre>\n</body>\n</html>" }
Et les commandes à exécuter sont aussi bien plus directe quand on utilise awk plutôt que sed :
kelly@octarine ~/html>awk-fmake-html-from-text.awk testfile>file.html
![]() |
Exemples d'Awk sur votre système |
|---|---|
|
Nous nous référons encore au répertoire qui contient les scripts d'initialisation de votre système. Entrez une commande similaire à la suivante pour voir d'autres exemples pratiques de l'usage très répandu de la commande awk :
|
Pour un contrôle du format du résultat plus précis que celui fournit par print, employez printf. La commande printf peut spécifier une largeur de champs pour chaque élément, de même que divers choix de formatage des nombres (tel que la base de calcul à considérer, si il faut afficher un exposant, si le signe est à afficher, et combien de chiffres à afficher après la virgule). Ceci est fait en ajoutant une chaîne appelée chaîne de formatage, qui contrôle comment et où afficher les autres arguments.
Il y a quelques exemples concret où awk peut être pratique.
Pour le premier exercice, l'entrée sont les lignes de la forme suivante :
Username:Firstname:Lastname:Telephone number
Faire un script awk qui convertit une telle ligne en un enregistrement LDAP à ce format :
dn: uid=Username, dc=example, dc=com
cn: Firstname Lastname
sn: Lastname
telephoneNumber: Telephone number
Créer un fichier contenant quelques enregistrements de test et vérifiez..
Créer un script Bash utilisant awk
et les commandes standard UNIX qui affiche les 3 utilisateurs les plus
gros consommateurs d'espaces disques dans le répertoire /home (si il ne situe pas dans une partition distincte, faire le script pour la partition / ;
celle-ci existe sur tout système UNIX). D'abord, exécutez les commandes
depuis la ligne de commande. Puis mettez-les dans un script. Le script
devrait produire un résultat compréhensible (lisible par le chef). Si
tout semble fonctionner, faire en sorte que le script vous envoie le
résultat par mail (employez par exemple mail -s Disk space usage <you@your_comp> < result).
Si le démon des quotas tourne, utilisez ses informations ; si non utilisez find.
Créer un résultat de style XML à partir d'une liste séparée par des tabulations de la forme suivante :
Meaning very long line with a lot of description
meaning another long line
othermeaning more longline
testmeaning looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line, but i mean really looooong.
Le résultat devrait être :
<row>
<entry>Meaning</entry>
<entry>
very long line
</entry>
</row>
<row>
<entry>meaning</entry>
<entry>
long line
</entry>
</row>
<row>
<entryothermeaning</entry>
<entry>
more longline
</entry>
</row>
<row>
<entrytestmeaning</entry>
<entry>
looooooooooooooooooooooooooooooooooooooong line, but i mean really looooooooooooooooooooooooooooooooooooooooooooooooooong.
</entry>
</row>
En plus, si vous connaissez quelque peu XML, écrivez un script BEGIN et END pour compléter la table. Ou faites le en HTML.
Résumé
Dans ce chapitre nous traiterons de l'emploi de conditions dans les scripts Bash. Ceci comprend les sujets suivants :
L'instruction if
L'usage du statut d'exécution d'une commande
Comparer et tester les entrées et des fichiers
les blocs if/then/else
Les blocs if/then/elif/else
Utiliser et tester les paramètres positionnels
Les instructions if imbriquées
Les expressions booléennes
Utiliser les instructions case
La syntaxe la plus compacte de la commande if est :
Tableau 7.1. Expressions primitives
| Primitives | sens |
|---|---|
[ -a FICHIER ] |
Vrai si FICHIER existe. |
[ -b FICHIER ] |
Vrai si FICHIER existe et est un fichier de type bloc. |
[ -c FICHIER ] |
Vrai si FICHIER existe et est un fichier de type caractère. |
[ -d FICHIER ] |
Vrai si FICHIER existe et est de type répertoire. |
[ -e FICHIER ] |
Vrai si FICHIER existe. |
[ -f FICHIER ] |
Vrai si FICHIER existe et est un fichier régulier. |
[ -g FICHIER ] |
Vrai si FICHIER existe et son bit SGID est positionné. |
[ -h FICHIER ] |
Vrai si FICHIER existe et est un lien symbolique. |
[ -k FICHIER ] |
Vrai si FICHIER existe et son bit collant est positionné. |
[ -p FICHIER ] |
Vrai si FICHIER existe et est un tube nommé (FIFO). |
[ -r FICHIER ] |
Vrai si FICHIER existe et est lisible. |
[ -s FICHIER ] |
Vrai si FICHIER existe et a une taille supérieure à zéro. |
[ -t FD ] |
Vrai si le descripteur de fichier FD est ouvert et qu'il se réfère à un terminal. |
[ -u FICHIER ] |
Vrai si FILE existe et son bit SUID (Set User ID) est positionné. |
[ -w FICHIER ] |
Vrai si FICHIER existe et est en écriture. |
[ -x FICHIER ] |
Vrai si FICHIER existe et est exécutable. |
[ -O FICHIER ] |
Vrai si FICHIER existe et appartient à l'identifiant effectif de l'utilisateur. |
[ -G FICHIER ] |
Vrai si FICHIER existe et appartient à l'identifiant effectif du groupe. |
[ -L FICHIER ] |
Vrai si FICHIER existe et est un lien symbolique. |
[ -N FICHIER ] |
Vrai si FICHIER existe et qu'il a été modifié depuis qu'il a été lu. |
[ -S FICHIER ] |
Vrai si FICHIER existe et est un connecteur réseau (socket). |
[ FILE1 -nt FILE2 ] |
Vrai si FILE1 a été modifié plus récemment que FILE2, ou si FILE1 existe et FILE2 n'existe pas. |
[ FILE1 -ot FILE2 ] |
Vrai si FILE1 est plus ancien que FILE2, ou si FILE2 existe et FILE1 non. |
[ FILE1 -ef FILE2 ] |
Vrai si FILE1 et FILE2 se réfère à la même entité et même numéro d'inode. |
[ -o OPTIONNAME ] |
Vrai si l'option Shell « OPTIONNAME » est activée. |
[ -z STRING ] |
Vrai si la longueur de « STRING » est zéro. |
[ -n STRING ] or [ STRING ] |
Vrai si la longueur de « STRING » n'est pas zéro. |
| [ STRING1 == STRING2 ] | Vrai si les chaînes sont identiques. « = » peut être employé au lieu de « == » pour une stricte compatibilité POSIX. |
| [ STRING1 != STRING2 ] | Vrai si les chaînes ne sont pas égales. |
| [ STRING1 < STRING2 ] | Vrai si « STRING1 » précède « STRING2 » selon le lexique du paramétrage local. |
| [ STRING1 > STRING2 ] | Vrai si « STRING1 » suit « STRING2 » selon le lexique du paramétrage local. |
| [ ARG1 OP ARG2 ] | « OP » est -eq, -ne, -lt, -le, -gt ou l'option -ge. Ces opérateurs arithmétiques binaires renvoient vrai si « ARG1 »
est égal, non égal, inférieur, supérieur ou
égal, supérieur, ou supérieur ou égal
à « ARG2 », respectivement. « ARG1 » et « ARG2 » sont des entiers. |
Les expressions peuvent être combinées avec les opérateurs suivants dans l'ordre de leur préséance :
Tableau 7.2. Combinaison d'expressions
| Opération | Effet |
|---|---|
| [ ! EXPR ] | Vrai si EXPR est faux. |
| [ ( EXPR ) ] | Renvoie la valeur de EXPR. Ceci peut être utilisé pour modifier la préséance normale des opérateurs. |
| [ EXPR1 -a EXPR2 ] | Vrai si EXPR1 et EXPR2 sont vrai.. |
| [ EXPR1 -o EXPR2 ] | Vrai si soit EXPR1 ou EXPR2 est vrai. |
Le premier exemple contrôle l'existence d'un fichier :
anny ~>catmsgcheck.sh
#!/bin/bash
echo "Ce script vérifie si le fichier des messages existe."
echo "Vérification..."
if [ -f /var/log/messages ]
then
echo "/var/log/messages existe."
fi
echo
echo "...fait."anny ~>./msgcheck.sh
Ce script vérifie si le fichier des messages existe.
Vérification...
/var/log/messages existe.
...fait.
A ajouter dans vos fichier de configuration Bash :
# Ces lignes affichent un message si l'option noclobber option est positionnée :
if [ -o noclobber ]
then
echo "Vos fichiers sont protégés contre une réécriture accidentelle du fait d'une redirection."
fi
![]() |
L'environnement |
|---|---|
|
L'exemple ci-dessus fonctionnera si il est soumis à la ligne de commande :
Cependant, si vous employez les tests de conditions qui dépendent de l'environnement, vous pourriez obtenir des résultats variables alors que vous exécutez la même commande dans un script, parce que le script ouvrira un nouveau Shell, dans lequel les variables et options attendues pourraient ne pas être définies automatiquement. |
L'exemple suivant montre un simple test :
anny ~>if[ $? -eq 0 ]More input>then echo'That was a good job!'More input>fi
That was a good job!anny ~>
anny ~>if! grep $USER/etc/passwdMore input>then echo"votre compte utilisateur ne se trouve pas sur le système local"; fi
votre compte utilisateur ne se trouve pas sur le système localanny >echo$?
0anny >
Le même résultat peut être obtenu comme ceci :
anny >grep$USER/etc/passwdanny >if[ $? -ne 0 ]; then echo"pas un compte local"; fi
pas un compte localanny >
Les exemples ci-dessous emploient des comparaisons numériques :
anny >num=`wc -l work.txt`anny >echo$num
201anny >if[ "$num" -gt "150" ]More input>then echo ; echo"vous avez assez travaillé pour aujourd'hui."More input>echo ; fi
vous avez assez travaillé pour aujourd'hui.anny >
#!/bin/bash
# Calculer le numéro de semaine à partir de la commande date :
WEEKOFFSET=$[ $(date +"%V") % 2 ]
# Tester si il y a un reste. Si pas de reste, c'est une semaine paire donc envoyer un message.
# Sinon, ne rien faire.
if [ $WEEKOFFSET -eq "0" ]; then
echo "Dimanche soir, les éboueurs passent." | mail -s "Les éboueurs passent" your@your_domain.org
fi
Un exemple de comparaison de chaînes avec le test de l'identifiant utilisateur :
if [ "$(whoami)" != 'root' ]; then
echo "Vous ne détenez pas la permission de lancer $0 en tant que non administrateur."
exit 1;
fi
[ "$(whoami)" != 'root' ] && ( echo vous êtes connectés avec un compte non administrateur; exit 1 )
Une expression régulière peut être employée aussi dans les comparaisons :
anny >genre="féminin"anny >if[[ "$genre" == f* ]]More input>then echo"Très honoré, Madame."; fi
Très honoré, Madame.anny >
![]() |
Les vrais Programmeurs |
|---|---|
|
La plupart des programmeurs préféreront employer l'intégrée test qui est équivalent à l'emploi du crochet de comparaison, comme ceci : test "$(whoami)" != 'root' && (echo vous êtes connectés avec un compte non administrateur; exit 1) |
![]() |
No exit? |
|---|---|
|
Si vous appelez exit dans un sous-Shell, celui-ci ne passera pas de variables à son parent. Employez { and } au lieu de ( and ) si vous ne voulez pas que Bash en fourchant crée un sous-Shell. |
freddy scripts>genre="masculin"freddy scripts>if[[ "$genre" == "f*" ]]More input>then echo"Très honoré, Madame."More input>else echo"Comment se fait-il que le verre de Madame soit vide ?"More input>fi
Comment se fait-il que le verre de Madame soit vide ?freddy scripts>
![]() |
[] versus [[]] |
|---|---|
|
Contrairement à |
Un autre exemple, tiré de celui de la Section 1.2.1, « Tester le statut d'exécution » :
anny ~>su-
Password:[root@elegance root]#if! grep ^$USER/etc/passwd1>/dev/null>then echo"votre compte utilisateur ne se trouve pas sur le système local">else echo"votre compte utilisateur ne se trouve pas sur le système local">fi
votre compte utilisateur se trouve dans /etc/passwd file[root@elegance root]#
Nous permutons vers le compte root pour montrer l'effet du else - votre root est d'ordinaire un compte local tandis que votre compte personnel peut être géré par un système central, tel qu'un serveur LDAP.
Au lieu de déclarer une variable puis d'exécuter un script, il est fréquemment plus élégant de mettre la valeur de la variable dans la ligne de commande.
Pour ce faire nous employons les paramètres positionnels $1, $2, ..., $N. $# mémorise le nombre de paramètres de la ligne de commande. $0 mémorise le nom du script.
Voici un autre exemple avec 2 paramètres :
anny ~>catweight.sh
#!/bin/bash
# Ce script affiche un message au sujet de votre poids si vous donnez
# votre poids en kilos et votre taille en centimètres.
weight="$1"
height="$2"
idealweight=$[$height - 110]
if [ $weight -le $idealweight ] ; then
echo "Vous devriez manger un peu plus gras."
else
echo "Vous devriez manger un peu plus de fruits."
fianny ~>bash-xweight.sh55 169
+ weight=55
+ height=169
+ idealweight=59
+ '[' 55 -le 59 ']'
+ echo 'Vous devriez manger un peu plus gras.'
Vous devriez manger un peu plus gras.
L'exemple suivant montre comment changer le script précédent de sorte qu'il affiche un message si plus ou moins de 2 paramètres sont donnés :
anny ~>catweight.sh
#!/bin/bash
# Ce script affiche un message au sujet de votre poids si vous donnez
# votre poids en kilos et votre taille en centimètres.
if [ ! $# == 2 ]; then
echo "Usage: $0 poids_en_kilos taille_en_centimètres"
exit
fi
weight="$1"
height="$2"
idealweight=$[$height - 110]
if [ $weight -le $idealweight ] ; then
echo "Vous devriez manger un peu plus gras."
else
echo "Vous devriez manger un peu plus de fruits."
fianny ~>weight.sh70 150
Vous devriez manger un peu plus de fruits.anny ~>weight.sh70 150 33
Usage: ./weight.sh poids_en_kilos taille_en_centimètres
Consulter la Section 2.5, « Emploi de l'instruction exit et du if » pour voir une façon plus élégante d'afficher des messages de mode d'emploi.
Ce test est fait dans beaucoup de scripts, parce que il n'y a pas d'intérêt à lancer un programme si vous savez qu'il ne va pas fonctionner :
#!/bin/bash
# Ce script donne des informations au sujet d'un fichier.
FILENAME="$1"
echo "Properties for $FILENAME:"
if [ -f $FILENAME ]; then
echo "Size is $(ls -lh $FILENAME | awk '{ print $5 }')"
echo "Type is $(file $FILENAME | cut -d":" -f2 -)"
echo "Inode number is $(ls -i $FILENAME | cut -d" " -f1 -)"
echo "$(df -h $FILENAME | grep -v Mounted | awk '{ print "On",$1", \
which is mounted as the",$6,"partition."}')"
else
echo "Le fichier est non-existant."
fi
![]() |
Nom de fichier avec des espaces |
|---|---|
|
L'exemple plus haut échouera si la valeur de |
Ceci est un exemple que vous pouvez mettre dans votre crontab pour une exécution quotidienne :
anny /etc/cron.daily>catdisktest.sh
#!/bin/bash
# Ce script fait un test très simple pour contrôler l'espace disque.
space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -`
alertvalue="80"
if [ "$space" -ge "$alertvalue" ]; then
echo "Au moins un de mes disques est bientôt plein !" | mail -s "daily diskcheck" root
else
echo "Espace disque correct" | mail -s "daily diskcheck" root
fi
Voici un exemple testant l'année bissextile :
anny ~/testdir>cattestleap.sh
#!/bin/bash
# Ce script teste si nous sommes dans une année bissextile ou pas.
year=`date +%Y`
if [ $[$year % 400] -eq "0" ]; then
echo "This is a leap year. Février a 29 jours."
elif [ $[$year % 4] -eq 0 ]; then
if [ $[$year % 100] -ne 0 ]; then
echo "Année bissextile, Février a 29 jours."
else
echo "Année non bissextile. Février a 28 jours."
fi
else
echo "Année non bissextile. Février a 28 jours."
fianny ~/testdir>date
Tue Jan 14 20:37:55 CET 2003anny ~/testdir>testleap.sh
Année non bissextile.
Le script ci-dessus peut être abrégé avec les opérateurs booléens « AND » (&&) et « OR » (||).
Nous employons le double crochet pour tester les expressions arithmétiques, voir la Section 4.6, « L'expansion arithmétique ». Ceci est équivalent à l'instruction let. Ici, vous allez être bloqué si vous employez les crochets, si vous essayez quelque chose de la sorte $[$year % 400], parce que ici, les crochets ne représentent pas une vraie commande mais eux-mêmes.
Parmi d'autres éditeurs, gvim est l'un de ceux qui supporte les codes de couleur selon le format de fichier ; de tel éditeurs sont pratiques pour pister les erreurs d'écriture.
Nous avons déjà rencontré l'instruction exit dans la Section 2.1.3, « Tester le nombre de paramètres ». Il achève l'exécution du script. Il est plus souvent utilisé si l'entrée requise de l'utilisateur est incorrecte, si une instruction a échouée ou si une autre erreur intervient.
L'instruction exit admet un argument optionnel.
Cet argument est le code sous forme d'entier du statut
d'exécution, qui est renvoyé au parent et stocké
dans la variable $?.
Un argument à zéro
signifie que le script s'est exécuté correctement. Tout autre valeur
peut être employée par le programmeur pour renvoyer divers messages au
parent, afin que divers traitements soient activés selon l'échec ou la
réussite du processus enfant. Si aucun argument n'est donné à la
commande exit, le Shell parent exploite la valeur courante de la variable $?.
anny ~/testdir>catpenguin.sh
#!/bin/bash
# Ce script vous laisse présenter divers menus à Tux. Il ne sera heureux que
# quand il aura du poisson. Nous avons aussi ajouté un dauphin et (logiquement) un chameau.
if [ "$menu" == "poisson" ]; then
if [ "$animal" == "pingouin" ]; then
echo "Hmmmmmm poisson... Tux heureux !"
elif [ "$animal" == "dauphin" ]; then
echo "Pweetpeettreetppeterdepweet !"
else
echo "*prrrrrrrt*"
fi
else
if [ "$animal" == "pingouin" ]; then
echo "Tux déteste ça. Tux veut du poisson !"
exit 1
elif [ "$animal" == "dauphin" ]; then
echo "Pweepwishpeeterdepweet !"
exit 2
else
echo "Voulez-vous lire cette affiche ?!"
exit 3
fi
fi
Ce script est appelé depuis le suivant, qui donc exporte ses variables menu et animal :
anny ~/testdir>catfeed.sh
#!/bin/bash
# Ce script procède selon le statut d'exécution renvoyé par penguin.sh
export menu="$1"
export animal="$2"
feed="/nethome/anny/testdir/penguin.sh"
$feed $menu $animal
case $? in
1)
echo "Gaffe : Vous feriez mieux de lui donner du poisson, avant qu'il ne s'énerve..."
;;
2)
echo "Gaffe : C'est à cause de gens comme vous qu'il quitte la terre tout le temps..."
;;
3)
echo "Gaffe : Achetez la nourriture que le zoo fournit pour les animaux, i@**@, comment pensez-vous que nous survivons ?"
;;
*)
echo "Gaffe : N'oubliez pas le guide !"
;;
esac
anny ~/testdir>./feed.shapple penguin
Tux déteste ça. Tux veut du poisson !
Gaffe : Vous feriez mieux de lui donner du poisson, avant qu'il ne s'énerve...
anny ~/testdir>catdisktest.sh
#!/bin/bash
# Ce script fait un test très simple pour vérifier l'espace disque.
space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -`
case $space in
[1-6]*)
Message="Tout est bon."
;;
[7-8]*)
Message="Commencer à songer à faire de la place. Il y a une partition qui est $space % pleine."
;;
9[1-8])
Message="Dépêchez-vous avec ce nouveau disque.. Une partition est $space % pleine."
;;
99)
Message="Je suis en train de me noyer ! Il y a une partition à $space % !"
;;
*)
Message="Il semble que je tourne avec un espace disque inexistant..."
;;
esac
echo $Message | mail -s "disk report `date`" annyanny ~/testdir>
Vous avez un nouveau mail.anny ~/testdir>tail-16/var/spool/mail/anny
From anny@octarine Tue Jan 14 22:10:47 2003
Return-Path: <anny@octarine>
Received: from octarine (localhost [127.0.0.1])
by octarine (8.12.5/8.12.5) with ESMTP id h0ELAlBG020414
for <anny@octarine>; Tue, 14 Jan 2003 22:10:47 +0100
Received: (from anny@localhost)
by octarine (8.12.5/8.12.5/Submit) id h0ELAltn020413
for anny; Tue, 14 Jan 2003 22:10:47 +0100
Date: Tue, 14 Jan 2003 22:10:47 +0100
From: Anny <anny@octarine>
Message-Id: <200301142110.h0ELAltn020413@octarine>
To: anny@octarine
Subject: disk report Tue Jan 14 22:10:47 CET 2003
Commencer à songer à faire de la place. Il y a une partition qui est 87 % pleine.anny ~/testdir>
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status anacron
;;
restart)
stop
start
;;
condrestart)
if test "x`pidof anacron`" != x; then
stop
start
fi
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
exit 1
esac
Les tâches à exécuter dans chaque
cas, telles arrêter ou démarrer le démon, sont définies par des
fonctions, dont la source est partiellement dans le fichier /etc/rc.d/init.d/functions. Voir le Chapitre 11, Fonctions pour plus d'explications.
Voici quelques idées pour vous lancer dans l'écriture de scripts if :
Faire la même chose avec une instruction case et une variante de l'usage de la commande date.
Modifier le script leaptest.sh dans
Section 2.4, « Opérations booléennes » afin qu'il nécessite un paramètre,
l'année. Tester que exactement un seul paramètre est
passé.
Ecrire un script appelé
whichdaemon.sh qui vérifie que les démons
httpd et init sont lancés sur
votre système. Si un httpd est lancé, le script
devrait afficher un message comme « Cette machine fait tourner un
serveur WEB. » Employez ps pour contrôler les
processus.
Écrire un script qui fait la sauvegarde de votre
répertoire racine sur une machine distante en utilisant
scp. Le script devrait écrire son rapport dans un
fichier journal, par exemple ~/log/homebackup.log.
Si vous n'avez pas de seconde machine pour y copier la sauvegarde, se
servir de scp pour tester la copie sur la machine
locale. Ceci nécessite des clés SSH entre 2 hôtes, ou sinon vous devez
fournir un mot de passe. La création de clés SSH est expliquée dans le
man
ssh-keygen.
Adaptez le script à partir du 1er exemple à la Section 3.1, « Les conditions simplifiées » pour inclure le cas de l'occupation de exactement 90% de l'espace disque, et de moins de 10% de l'espace disque.
Le script devrait se servir de tar
cf pour la création de la sauvegarde et
gzip ou bzip2 pour la
décompression du fichier .tar. Mettre tous les noms
de fichiers dans des variables. Mettre le nom du serveur distant et du
répertoire distant dans une variable. Ce sera plus facile de réutiliser
ce script ou d'y faire des modifications dans le futur.
Le script devrait vérifier l'existence d'une archive compressée. Si elle existe, la supprimer d'abord pour éviter les messages d'erreur.
Le script devrait aussi contrôler l'espace disque disponible.
Avoir à l'esprit qu'à un moment donné vous pourrez avoir en même temps
sur le disque les données dans votre répertoire racine, celles dans le
fichier .tar et celle dans l'archive compressée. Si
il n'y a pas assez d'espace, quitter avec un message d'erreur dans le
fichier journal.
Le script devrait nettoyer l'archive compressée avant de se terminer.
Résumé
Dans ce chapitre nous expliquerons comment interagir avec les utilisateurs de nos scripts :
En affichant des messages et des explications conviviaux à l'intention des utilisateurs
Récupérer la saisie utilisateur
Demander une entrée utilisateur
Utiliser les descripteurs de fichiers pour lire et écrire depuis et sur de multiples fichiers
Comme exemple d'ajout de commentaires, nous écrirons le feed.sh et le penguin.sh de la Section 2.1.2, « Contrôle des paramètres de la ligne de commande » de façon améliorée :
michel ~/test>catpenguin.sh
#!/bin/bash
# Ce script vous laisse présenter divers menus à Tux. Il ne sera heureux que
# quand il aura du poisson. Pour s'amuser un peu, nous ajoutons quelques animaux.
if [ "$menu" == "poisson" ]; then
if [ "$animal" == "pingouin" ]; then
echo -e "Hmmmmmm poisson... Tux heureux !\n"
elif [ "$animal" == "dauphin" ]; then
echo -e "\a\a\aPweetpeettreetppeterdepweet !\a\a\a\n"
else
echo -e "*prrrrrrrt*\n"
fi
else
if [ "$animal" == "pingouin" ]; then
echo -e "Tux déteste ça. Tux veut du poisson !\n"
exit 1
elif [ "$animal" == "dauphin" ]; then
echo -e "\a\a\a\a\a\aPweepwishpeeterdepweet !\a\a\a"
exit 2
else
echo -e "Voulez-vous lire cette affiche ?! Ne pas nourrir les "$animal"s !\n"
exit 3
fi
fimichel ~/test>catfeed.sh
#!/bin/bash
# Ce script agit en fonction du statut d'exécution renvoyé par penguin.sh
if [ "$#" != "2" ]; then
echo -e "Utilisation du script feed:\t$0 nourriture nom-animal \n"
exit 1
else
export menu="$1"
export animal="$2"
echo -e "Nourrissage $menu to $animal...\n"
feed="/nethome/anny/testdir/penguin.sh"
$feed $menu $animal
result="$?"
echo -e "Nourrissage fait.\n"
case "$result" in
1)
echo -e "Gaffe : \"Vous feriez mieux de lui donner du poisson, Sinon il s'énerve...\"\n"
;;
2)
echo -e "Gaffe : \"Pas étonnant qu'il fuit notre planète...\"\n"
;;
3)
echo -e "Gaffe : \"Achetez la nourriture fournie par le zoo à l'entrée, i***\"\n"
echo -e "Gaffe : \"Vous voulez les empoisonner ?\"\n"
;;
*)
echo -e "Gaffe : \"N'oubliez pas le guide !\"\n"
;;
esac
fi
echo "Fin..."
echo -e "\a\a\aMerci de votre visite. En espérant vous revoir bientôt !\n"michel ~/test>feed.shapple camel
Nourrir le chameau avec des pommes...
Avez-vous vu l'affiche ?! Ne pas nourrir les chameaux !
Nourrissage fait.
Gaffe : "Achetez la nourriture que le zoo fournie à l'entrée, i ***"
Gaffe : "Vous voulez les empoisonner ?"
Fin...
Merci de votre visite. En espérant vous revoir bientôt !michel ~/test>feed.shapple
Utilisation du script feed : ./feed.sh menu nom-animal
Plus d'informations sur les caractères d'échappement à la Section 3.2, « Le caractère Echap (escape) ». Le tableau suivant donne un aperçu des séquences reconnues par la commande echo :
Tableau 8.1. Séquences d'échappement reconnues par la commande echo
| Séquence | sens |
|---|---|
| \a | Alerte (sonnerie). |
| \b | Retour arrière. |
| \c | Supprime les saut de lignes résiduel à la fin. |
| \e | Escape. |
| \f | Saut de page. |
| \n | Saut de ligne. |
| \r | Retour chariot. |
| \t | Tabulation horizontale. |
| \v | Tabulation verticale. |
| \\ | Slash inversé. |
| \ONNN | Le caractère sur 8 bits dont la valeur en base octal est NNN (de 0 à 3 chiffres en octal). |
| \NNN | Le caractère sur 8 bits dont la valeur en base octal est NNN (de 1 à 3 chiffres en octal). |
| \xHH | Le caractère sur 8 bits avec la valeur en base hexadécimale (de 1 à 2 chiffres en hexadécimal). |
Les caractères de la valeur de la variable IFS sont employés pour découper l'entrée en mots ou jetons ; voir la Section 4.8, « Le découpage de mots ».
Le caractère slash inversé peut être utilisé pour inhiber le sens
particulier du caractère lu suivant et pour la continuation de la ligne.
Si aucun nom n'est fourni, la ligne lue est affectée à la variable REPLY.
La commande read renvoie un code à zéro, sauf si un caractère de fin de fichier est rencontré, si read dépasse son temps imparti ou si un descripteur de fichier invalide est fourni en argument à l'option -u option.
Les options suivantes sont supportées par l'intégrée Bash read :
Tableau 8.2. Options de l'intégrée read
| Option | sens |
|---|---|
-a ANAME |
Les mots sont affectés séquentiellement aux éléments de la variable tableau ANAME, en commençant par l'index 0. Tous les éléments sont supprimés de ANAME avant l'affectation. Les autres arguments NAME sont ignorés. |
-d DELIM |
Le premier caractère de DELIM est utilisé pour terminer la ligne entrée, plutôt que le saut de ligne. |
| -e | readline est utilisé pour obtenir la ligne. |
-n NCHARS |
read s'arrête après avoir lu NCHARS caractères plutôt que d'attendre une ligne entrée complète. |
-p PROMPT |
Affiche le PROMPT,
sans saut de ligne final, avant de tenter de lire tout autre entrée.
L'invite est affichée seulement si l'entrée vient d'un terminal. |
| -r | Si cette option est donnée, le slash inversé n'agit pas comme caractère d'échappement. Le slash inversé est considéré comme faisant parti de la ligne. En particulier, un couple « saut de ligne-slash inversé » ne devrait pas être utilisé comme symbole de continuation de ligne. |
| -s | Mode Silencieux. Si l'entrée provient d'un terminal, les caractères n'y sont pas renvoyés. |
-t TIMEOUT |
Donne un temps imparti à read et renvoie une erreur si une ligne complète n'a pas été lue avant TIMEOUT secondes. Cette option n'a pas d'effet si read n'a pas son entrée depuis un terminal ou un tube. |
-u FD |
Obtenir les lignes entrées depuis le fichier de descripteur FD. |
Ceci est un rapide exemple, améliorant le script leaptest.sh du chapitre précédent :
michel ~/test>catleaptest.sh
#!/bin/bash
# Ce script teste si vous avez saisi une année bissextile ou pas.
echo "Saisissez une année que vous voulez tester (4 chiffres), puis appuyer sur [ENTREE] :"
read year
if (( ("$year" % 400) == "0" )) || (( ("$year" % 4 == "0") && ("$year" % 100 !=
"0") )); then
echo "$année bissextile."
else
echo "année non bissextile."
fimichel ~/test>leaptest.sh
Saisissez une année que vous voulez tester (4 chiffres), puis appuyer sur [ENTREE] :
2000
2000 année bissextile.
michel ~/test>catfriends.sh
#!/bin/bash
# Ce programme garde votre carnet d'adresse à jour.
friends="/var/tmp/michel/friends"
echo "Bonjour, "$USER". Ce script vous enregistrera dans la base de données des amis de Michel."
echo -n "Saisir votre nom et appuyer sur [ENTREE] : "
read name
echo -n "Saisir votre sexe et appuyer sur [ENTREE] : "
read -n 1 gender
echo
grep -i "$name" "$friends"
if [ $? == 0 ]; then
echo "Vous êtes déjà enregistré, terminé."
exit 1
elif [ "$gender" == "m" ]; then
echo "Vous êtes ajouté à la liste des amis de Michel."
exit 1
else
echo -n "Quel âge avez-vous ? "
read age
if [ $age -lt 25 ]; then
echo -n "De quelle couleur sont vos cheveux ? "
read colour
echo "$name $age $colour" >> "$friends"
echo "Vous êtes ajouté à la liste des amis de Michel. Merci beaucoup !"
else
echo "Vous êtes ajouté à la liste des amis de Michel."
exit 1
fi
fimichel ~/test>cpfriends.sh /var/tmp; cd/var/tmpmichel ~/test>touchfriends; chmoda+wfriendsmichel ~/test>friends.sh
Bonjour, michel. Ce script vous enregistrera dans la base de données des amis de Michel.
Saisir votre nom et appuyer sur [ENTREE] : michel
Saisir votre sexe et appuyer sur [ENTREE] : m
Vous êtes ajouté à la liste des amis de Michel.michel ~/test>catfriends
D'autres gens peuvent maintenant lancer le script :
[anny@octarine tmp]$friends.sh
Bonjour, anny. Ce script vous enregistrera dans la base de données des amis de Michel.
Saisir votre nom et appuyer sur [ENTREE] : anny
Saisir votre sexe et appuyer sur [ENTREE] :f
Quel âge avez-vous ? 22
De quelle couleur sont vos cheveux ? noir
Vous êtes ajouté à la liste des amis de Michel.
Finalement, la liste friends ressemble à ceci :
tille 24 noir
anny 22 noir
katya 22 blonde
maria 21 noir
--output omitted--
Bien sûr, cette situation n'est pas idéale, parce que chacun peut renseigner (mais pas se retirer) du fichier de Michel. Vous pouvez palier ce défaut en utilisant des accès privilégiés au fichier de script, voir SUID et SGID dans le guide d'introduction à Linux.
L'affichage ci-dessous montre comment les descripteurs réservés pointent sur des entités concrètes :
michel ~>ls-l/dev/std*
lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stderr -> ../proc/self/fd/2
lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stdin -> ../proc/self/fd/0
lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stdout -> ../proc/self/fd/1michel ~>ls-l/proc/self/fd/[0-2]
lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/0 -> /dev/pts/6
lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/1 -> /dev/pts/6
lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/2 -> /dev/pts/6
Quand vous exécutez n'importe quelle commande, les étapes suivantes sont déroulées, dans l'ordre :
michel ~>date
Fri Jan 24 11:05:50 CET 2003michel ~>at1107
avertissement : les commandes seront exécutées avec (par ordre)
a) $SHELL b) login shell c)/bin/shat>ls-l/proc/self/fd/>/var/tmp/fdtest.atat><EOT>
job 10 at 2003-01-24 11:07michel ~>cat/var/tmp/fdtest.at
total 0
lr-x------ 1 michel michel 64 Jan 24 11:07 0 -> /var/spool/at/!0000c010959eb (deleted)
l-wx------ 1 michel michel 64 Jan 24 11:07 1 -> /var/tmp/fdtest.at
l-wx------ 1 michel michel 64 Jan 24 11:07 2 -> /var/spool/at/spool/a0000c010959eb
lr-x------ 1 michel michel 64 Jan 24 11:07 3 -> /proc/21949/fd
michel ~>crontab-l
# NE PAS EDITER CE FICHIER - éditer le modèle et le réinstaller.
# (/tmp/crontab.21968 installed on Fri Jan 24 11:30:41 2003)
# (Cron version -- $Id: chap8.xml,v 1.9 2006/09/28 09:42:45 tille Exp $)
32 11 * * * ls -l /proc/self/fd/ > /var/tmp/fdtest.cronmichel ~>cat/var/tmp/fdtest.cron
total 0
lr-x------ 1 michel michel 64 Jan 24 11:32 0 -> pipe:[124440]
l-wx------ 1 michel michel 64 Jan 24 11:32 1 -> /var/tmp/fdtest.cron
l-wx------ 1 michel michel 64 Jan 24 11:32 2 -> pipe:[124441]
lr-x------ 1 michel michel 64 Jan 24 11:32 3 -> /proc/21974/fd
Dans l'exemple précédent il apparaît clairement que vous pouvez fournir les fichiers d'entrée et de sortie à un script (voir Section 2.4, « Fichier d'entrée et fichier de sortie » pour plus de détails), mais certains oublient de rediriger les erreurs - un affichage dont peut dépendre la suite. Aussi, si vous êtes chanceux, les erreurs vous seront adressées par mail et d'éventuels dysfonctionnements pourront vous apparaître. Si vous n'êtes pas chanceux, les erreurs feront planter votre script et ne seront ni capturées ni adressées nulle part, par conséquent vous ne pourrez débugger.
Quand vous redirigez les erreurs, faites attention à l'ordre
de préséance. Par exemple, cette commande lancée
dans /var/spool
ls -l * 2> /var/tmp/unaccessible-in-spool
va rediriger la sortie standard de la commande ls vers le fichier unaccessible-in-spool dans /var/tmp. La commande
ls -l * > /var/tmp/spoollist 2>&1
redirigera et le standard d'entrée et le standard d'erreur vers le fichier spoollist. La commande
ls -l * 2 >& 1 > /var/tmp/spoollist
dirige seulement le standard de sortie vers le fichier de destination, parce que le standard d'erreurs est copié vers le standard de sortie avant que le standard de sortie soit redirigé.
Par commodité, les erreurs sont souvent redirigées vers /dev/null,
si il est sûr qu'elles n'ont pas d'intérêt. Des centaines d'exemples
peuvent être trouvés dans les scripts de lancement de votre système.
Bash
autorise à la fois le standard de sortie et le standard d'erreurs à
être redirigés vers le fichier dont le nom est le résultat de
l'expansion de FILE avec cette forme :
&> FILE
C'est l'équivalent de > FILE 2>&1,
la forme employée dans les exemples précédents.
C'est aussi combiné souvent avec la redirection vers /dev/null,
par exemple quand vous voulez juste qu'une commande s'exécute,
quelque soit le résultat ou le statut qu'elle donne.
michel ~>filterbody.txt.gz| catheader.txt-footer.txt
Ce texte est affiché au début de chaque travail d'affichage et merci à l'administrateur d'avoir mis en place
une si bonne infrastructure d'affichage.
Texte à filtrer.
Ce texte est à afficher à la fin de chaque travail d'affichage.
michel ~>filterbody.txt| catheader.txt /dev/fd/0 footer.txt| lp
pour assigner le descripteur N au fichier file en sortie, et
michel ~>exec4>result.txtmichel ~>filterbody.txt| catheader.txt /dev/fd/0 footer.txt>&4michel ~>catresult.txt
Ce texte est affiché au début de chaque travail d'impression et remercie l'administrateur d'avoir mis en place pour nous
une infrastructure d'impression si efficace.
Texte à filtrer.
Ce texte est à afficher à la fin de chaque travail d'affichage.
![]() |
Le descripteur 5 |
|---|---|
|
L'emploi de ce descripteur de fichier peut être cause de soucis, voir the Advanced Bash-Scripting Guide, chapitre 16. Il vous est sérieusement recommandé de ne pas l'employer. |
michel ~/testdir>catsysnotes.sh
#!/bin/bash
# Ce script fait un index des fichiers de configuration importants, les sauvegarde tous dans
# un fichier et autorise l'ajout de commentaires à chaque fichier.
CONFIG=/var/tmp/sysconfig.out
rm "$CONFIG" 2>/dev/null
echo "Le résultat sera mémorisé dans $CONFIG."
# Crée fd 7 avec la cible de fd 0 (save stdin "value")
exec 7<&0
# update fd 0 to target file /etc/passwd
exec < /etc/passwd
# Read the first line of /etc/passwd
read rootpasswd
echo "Sauvegarde des info de root..."
echo "Les infos du compte root :" >> "$CONFIG"
echo $rootpasswd >> "$CONFIG"
# Modifie fd 0 pour cibler fd 7 (old fd 0 target); supprime fd 7
exec 0<&7 7<&-
echo -n "Entrez un commentaire ou [ENTER] sans commentaire : "
read comment; echo $comment >> "$CONFIG"
echo "Mémorise les infos de l'hôte..."
# D'abord préparer un fichier hôte sans commentaires
TEMP="/var/tmp/hosts.tmp"
cat /etc/hosts | grep -v "^#" > "$TEMP"
exec 7<&0
exec < "$TEMP"
read ip1 name1 alias1
read ip2 name2 alias2
echo "La configuration de l'hôte local :" >> "$CONFIG"
echo "$ip1 $name1 $alias1" >> "$CONFIG"
echo "$ip2 $name2 $alias2" >> "$CONFIG"
exec 0<&7 7<&-
echo -n "Entrez un commentaire ou [ENTER] sans commentaire : "
read comment; echo $comment >> "$CONFIG"
rm "$TEMP"michel ~/testdir>sysnotes.sh
Le résultat sera mémorisé dans /var/tmp/sysconfig.out.
Sauvegarde des info de root...
Entrez des commentaires [ENTER] for no comment : pense-bête pour mot de passe : vacance
Sauvegarde des informations système...
Entrez des commentaires [ENTER] for no comment : dans le DNS centralmichel ~/testdir>cat/var/tmp/sysconfig.out
Les infos du compte root :
root:x:0:0:root:/root:/bin/bash
pense-bête pour mot de passe : vacance
Votre configuration sur la machine locale :
127.0.0.1 localhost.localdomain localhost
192.168.42.1 tintagel.kingarthur.com tintagel
dans le DNS central
Suit un exemple simple de redirection du standard d'erreurs sur un tube :
michel ~>catlistdirs.sh
#!/bin/bash
# Ce script garde le standard de sortie, tandis qu'il redirige le standard d'erreurs
# afin d'être traité par awk.
INPUTDIR="$1"
# fd 6 targets fd 1 target (console out) in current shell
exec 6>&1
# fd 1 targets pipe, fd 2 targets fd 1 target (pipe),
# fd 1 targets fd 6 target (console out), fd 6 closed, execute ls
ls "$INPUTDIR"/* 2>&1 >&6 6>&- \
# Closes fd 6 for awk, but not for ls.
| awk 'BEGIN { FS=":" } { print "YOU HAVE NO ACCESS TO" $2 }' 6>&-
# fd 6 closed for current shell
exec 6>&-
michel ~>catstartsurf.sh
#!/bin/bash
# Ce script fournit aux usagers un moyen facile de choisir entre plusieurs navigateurs.
echo "Voici les navigateurs WEB de ce système :"
# Début du document 'intégré'
cat << BROWSERS
mozilla
links
lynx
konqueror
opera
netscape
BROWSERS
# Fin du document 'intégré'
echo -n "Lequel préférez-vous ? "
read browser
echo "Démarrage de $browser, Merci de patienter..."
$browser &michel ~>startsurf.sh
Voici les navigateurs WEB de ce système :
mozilla
links
lynx
konqueror
opera
netscapeLequel préférez-vous ?opera
Démarrage de opera, Merci de patienter...
#!/bin/bash
# Ce script installe un paquetage automatiquement avec yum.
if [ $# -lt 1 ]; then
echo "Utilisation : $0 package."
exit 1
fi
yum install $1 << CONFIRM
y
CONFIRM
[root@picon bin]#./install.shtuxracer
Gathering header information file(s) from server(s)
Server: Fedora Linux 2 - i386 - core
Server: Fedora Linux 2 - i386 - freshrpms
Server: JPackage 1.5 for Fedora Core 2
Server: JPackage 1.5, generic
Server: Fedora Linux 2 - i386 - updates
Finding updated packages
Downloading needed headers
Resolving dependencies
Dependencies resolved
I will do the following:
[install: tuxracer 0.61-26.i386]Is this ok [y/N]:EnterDownloading Packages
Running test transaction:
Test transaction complete, Success!
tuxracer 100 % done 1/1
Installed: tuxracer 0.61-26.i386
Transaction(s) Complete
Voir info tar ou Introduction à Linux, chapitre 9 : « Preparing your data » for background information.
Ecrire un script appelé simple-useradd.sh qui ajoute un utilisateur au système local. Le script devrait :
Ne prendre qu'un seul paramètre, ou sinon sortir avec un message d'utilisation.
Contrôler /etc/passwd et sélectionner le premier identifiant non affecté. Afficher un message contenant l'identifiant.
Créer un groupe privé pour cet utilisateur, en contrôlant le fichier /etc/group. Afficher un message contenant l'identifiant du groupe.
Rassembler des informations sur l'utilisateur : un commentaire décrivant cet utilisateur, choix dans une liste de Shell (tester sa validité, si non sortir avec un message), la date d'expiration du compte, les autres groupes auxquels ce nouvel utilisateur peut appartenir.
Avec les informations obtenues, ajouter une ligne à
/etc/passwd, /etc/group et
/etc/shadow ; créer le répertoire racine de
l'utilisateur (avec les autorisations correctes ! Ajouter
l'utilisateur aux groupes secondaires désirés.
Définir le mot de passe de cet utilisateur à une chaîne connue.
Réécrire le script de la Section 2.1.4, « Test de l'existence d'un fichier » afin qu'il lise son entrée depuis la saisie utilisateur plutôt que du premier paramètre.
Résumé
À la fin de ce chapitre, vous serez capable de
Ecrire des boucles for, while and until , et décider quelle boucle convient à quel besoin.
Utiliser les intégrées Bash break et continue
Ecrire des scripts avec l'instruction select.
Ecrire des scripts qui admettent un nombre variable de paramètres.
La syntaxe de cette boucle est :
Si [in LIST] est absent, il est remplacé par in $@ et for exécute les COMMANDES une fois pour chaque paramètre positionnel déclaré (voir Section 2.5, « Paramètres spéciaux » et Section 2.1.2, « Contrôle des paramètres de la ligne de commande »).
Le statut retourné est le statut d'exécution de la
dernière commande exécutée. Si aucune commande
n'est exécutée parce que LIST ne résulte en aucun élément, le code retour est zéro.
NOM peut être tout nom de variable, même si i est employé très souvent. LIST
peut être toute liste de mots, chaînes ou nombres qui
peuvent être des littéraux ou générés
par toute commande. Les COMMANDES
à exécuter peuvent être aussi toute commande système, script, programme
ou instruction Shell. Au premier passage dans la boucle, NOM est valorisé à la valeur du premier élément dans LIST.
Au deuxième passage, sa valeur est donnée par le second
élément dans la liste, et ainsi de suite. La boucle
termine quand NOM a pris une fois la valeur de chaque élément de LIST et qu'il ne reste plus d'éléments dans LIST.
[carol@octarine ~/articles]ls*.xml
file1.xml file2.xml file3.xml[carol@octarine ~/articles]ls*.xml>list[carol@octarine ~/articles]foriin`cat list`; do cp"$i" "$i".bak; done[carol@octarine ~/articles]ls*.xml*
file1.xml file1.xml.bak file2.xml file2.xml.bak file3.xml file3.xml.bak
for i in `ls /sbin`; do file /sbin/$i | grep ASCII; done
[carol@octarine ~/html]cathtml2php.sh
#!/bin/bash
# specific conversion script for my html files to php
LIST="$(ls *.html)"
for i in "$LIST"; do
NEWNAME=$(ls "$i" | sed -e 's/html/php/')
cat beginfile > "$NEWNAME"
cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME"
cat endfile >> "$NEWNAME"
done
![]() |
La commande basename |
|---|---|
|
Plutôt que d'employer sed pour remplacer le suffixe |
![]() |
Caractères spéciaux |
|---|---|
|
Vous aurez des soucis si la liste est transformée en noms de fichiers contenant des espaces et autres caractères irréguliers. Une construction plus appropriée pour obtenir la liste serait d'utiliser la fonction globale du Shell, comme ceci : for i in $PATHNAME/*; do |
CONTROL-COMMAND peut être toute(s) commande(s) qui peut s'achever avec un statut de succès ou d'échec. Le CONSEQUENT-COMMANDS peut être tout programme, script ou bloc Shell.
Voici un exemple pour les impatients :
#!/bin/bash
# Le script ouvre 4 fenêtres de terminal.
i="0"
while [ $i -lt 4 ]
do
xterm &
i=$[$i+1]
done
#!/bin/bash
# Ce script copie les fichiers de mon répertoire racine dans le répertoire du serveur WEB.
# (Utilisez des clés scp et SSH pour un répertoire distant)
# Un nouveau répertoire est créé à chaque heure.
PICSDIR=/home/carol/pics
WEBDIR=/var/www/carol/webcam
while true; do
DATE=`date +%Y%m%d`
HOUR=`date +%H`
mkdir $WEBDIR/"$DATE"
while [ $HOUR -ne "00" ]; do
DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
mkdir "$DESTDIR"
mv $PICDIR/*.jpg "$DESTDIR"/
sleep 3600
HOUR=`date +%H`
done
done
Ce petit script peut être utilisé pour des tests de simulation ; il génère des fichiers :
#!/bin/bash
# Ce script génère un fichier toute les 5 minutes
while true; do
touch pic-`date +%s`.jpg
sleep 300
done
![]() |
Mettez à profit le système |
|---|---|
|
L'exemple précédent existe pour le besoin de la démonstration. Des contrôles réguliers peuvent être facilement faits avec l'outil système cron. Ne pas oublier de rediriger les sorties et les erreurs quand un script est utilisé par crontab! |
Ce script peut être interrompu par l'usager quand une séquence Ctrl+C est frappée :
#!/bin/bash
# Ce script vous apporte sagesse
FORTUNE=/usr/games/fortune
while true; do
echo "Sur quel sujet voulez-vous un conseil ?"
cat << topics
politique
startrek
noyau
sports
excusesbidon
magie
amour
littérature
drogues
éducation
topics
echo
echo -n "Faites votre choix : "
read topic
echo
echo "Conseil gratuit sur le sujet $topic : "
echo
$FORTUNE $topic
echo
done
Script amélioré de picturesort.sh (voir Section 2.2.2, « Des boucles while imbriquées »),
qui teste l'espace disque disponible. Si pas assez d'espace disque
disponible, supprimer les images des mois
précédents :
#!/bin/bash
# Ce script copie les fichiers de mon répertoire racine dans le répertoire du serveur WEB.
# Un nouveau répertoire est créé à chaque heure.
# Si les images prennent trop de place, les plus anciennes sont supprimées.
while true; do
DISKFUL=$(df -h $WEBDIR | grep -v File | awk '{print $5 }' | cut -d "%" -f1 -)
until [ $DISKFUL -ge "90" ]; do
DATE=`date +%Y%m%d`
HOUR=`date +%H`
mkdir $WEBDIR/"$DATE"
while [ $HOUR -ne "00" ]; do
DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
mkdir "$DESTDIR"
mv $PICDIR/*.jpg "$DESTDIR"/
sleep 3600
HOUR=`date +%H`
done
DISKFULL=$(df -h $WEBDIR | grep -v File | awk '{ print $5 }' | cut -d "%" -f1 -)
done
TOREMOVE=$(find $WEBDIR -type d -a -mtime +30)
for i in $TOREMOVE; do
rm -rf "$i";
done
done
Notez l'initialisation des variables HOUR et DISKFULL et l'emploi d'options avec ls et date afin d'obtenir une liste correcte pour TOREMOVE.
[carol@octarine ~/testdir]catarchiveoldstuff.sh
#!/bin/bash
# Ce script crée un sous-répertoire dans le répertoire courant où sont gardés les
# fichiers supprimés.
# Cela pourrait être adapté à cron (avec modifications) pour être exécuté
# chaque semaine ou mois.
ARCHIVENR=`date +%Y%m%d`
DESTDIR="$PWD/archive-$ARCHIVENR"
mkdir "$DESTDIR"
# avec guillemets pour récupérer les noms de fichiers ayant des espaces, avec read -d pour la suite
# fool-proof usage:
find "$PWD" -type f -a -mtime +5 | while read -d $'\000' file
do
gzip "$file"; mv "$file".gz "$DESTDIR"
echo "$file archived"
done
Les fichiers sont compressés avant d'être déplacés dans le répertoire d'archive.
Cet exemple montre une boucle while qui peut être interrompue. Ceci est une version légèrement améliorée du script wisdom.sh de la Section 2.2.3, « Contrôle d'une boucle while avec des saisies au clavier ».
#!/bin/bash
# Ce script vous apporte sagesse
# Vous pouvez maintenant quitter d'une façon décente.
FORTUNE=/usr/games/fortune
while true; do
echo "Sur quel sujet voulez-vous un conseil?"
echo "1. politique"
echo "2. startrek"
echo "3. noyau"
echo "4. sports"
echo "5. excusesbidon"
echo "6. magie"
echo "7. amour"
echo "8. littérature"
echo "9. drogues"
echo "10. éducation"
echo
echo -n "Entrez votre choix, ou 0 pour quitter : "
read choice
echo
case $choice in
1)
$FORTUNE politique
;;
2)
$FORTUNE startrek
;;
3)
$FORTUNE noyau
;;
4)
echo "Le sport est une perte d'argent, d'énergie et de temps."
echo "Retournez à votre clavier."
echo -e "\t\t\t\t -- \"Unhealthy is my middle name\" Soggie."
;;
5)
$FORTUNE excusesbidon
;;
6)
$FORTUNE magie
;;
7)
$FORTUNE amour
;;
8)
$FORTUNE littérature
;;
9)
$FORTUNE drogues
;;
10)
$FORTUNE éducation
;;
0)
echo "OK, au revoir!"
break
;;
*)
echo "Ceci n'est pas un choix valide, taper un chiffre entre 0 et 10."
;;
esac
done
Mémorisez que break quitte la boucle, pas le script. Ceci se voit en ajoutant une commande echo à la fin du script. Cet echo sera aussi exécuté à la saisie qui provoque l'exécution du break (quand l'usager frappe « 0 »).
Dans les boucles imbriquées, break autorise la spécification de la boucle dont il faut sortir. Voir les pages Bash info pour plus de détails.
[carol@octarine ~/test]cattolower.sh
#!/bin/bash
# Ce script convertit tous les noms de fichiers contenant des majuscules en nom de fichier contenant que des minuscules
LIST="$(ls)"
for name in "$LIST"; do
if [[ "$name" != *[[:upper:]]* ]]; then
continue
fi
ORIG="$name"
NEW=`echo $name | tr 'A-Z' 'a-z'`
mv "$ORIG" "$NEW"
echo "nouveau nom pour $ORIG est $NEW"
done
[carol@octarine ~/test]rm*[carol@octarine ~/test]touchtest Test TEST[carol@octarine ~/test]bash-xtolower.sh
++ ls
+ LIST=test
Test
TEST
+ [[ test != *[[:upper:]]* ]]
+ continue
+ [[ Test != *[[:upper:]]* ]]
+ ORIG=Test
++ echo Test
++ tr A-Z a-z
+ NEW=test
+ mv -b Test test
+ echo 'nouveau nom pour Test est test'
new name for Test is test
+ [[ TEST != *[[:upper:]]* ]]
+ ORIG=TEST
++ echo TEST
++ tr A-Z a-z
+ NEW=test
+ mv -b TEST test
+ echo 'nouveau nom pour TEST est test'
nouveau nom pour TEST est test[carol@octarine ~/test]ls-a
./ ../ test test~
tr fait parti du paquet textutils, il peut effectuer toute sorte de transformation de caractère.
LIST
est interprété, ce qui génère une liste d'éléments. L'expansion est
affichée sur le standard d'erreurs ; chaque élément est précédé d'un
numéro. Si in LIST est absent, les paramètres positionnels sont affichés, comme si in $@ avait été spécifié. LIST est affiché une fois seulement.
Voici un exemple très simple, mais comme vous le constatez, il n'est pas très convivial :
[carol@octarine testdir]catprivate.sh
#!/bin/bash
echo "Ce script peut mettre un accès privé à tout fichier de ce répertoire."
echo "Entrez le numéro du fichier que vous voulez protéger :"
select FILENAME in *;
do
echo "Vous avez sélectionné $FILENAME ($REPLY), il est maintenant accessible que par vous."
chmod go-rwx "$FILENAME"
done[carol@octarine testdir]./private.sh
Ce script peut mettre un accès privé à tout fichier de ce répertoire.
Entrez le numéro du fichier que vous voulez protéger :
1) archive-20030129
2) bash
3) private.sh
#? 1
Vous avez sélectionné archive-20030129 (1)
#?
Déclarer l'invite PS3 et ajouter la possibilité de quitter l'améliore :
#!/bin/bash
echo "Ce script peut mettre un accès privé à tout fichier de ce répertoire."
echo "Entrez le numéro du fichier que vous voulez protéger"
PS3="Votre choix : "
QUIT="QUITTER CE PROGRAMME - Je me sens plus en confiance là."
touch "$QUIT"
select FILENAME in *;
do
case $FILENAME in
"$QUIT")
echo "Fin."
break
;;
*)
echo "Vous avez sélectionné $FILENAME ($REPLY)"
chmod go-rwx "$FILENAME"
;;
esac
done
rm "$QUIT"
Si N est zéro ou supérieur à $# les paramètres positionnels ne sont pas changés (le nombre total de paramètres, voir Section 2.1.2, « Contrôle des paramètres de la ligne de commande »)
et la commande n'a pas d'effet. Si N est absent, il est considéré
valant 1. Le code renvoyé est zéro à moins que N soit supérieur à $# ou inférieur à zéro, sinon il est différent de zéro.
#!/bin/bash
# Ce script peut éliminer des fichiers qui n'ont pas été accédés depuis plus de 365 jours.
USAGE="Utilisation : $0 dir1 dir2 dir3 ... dirN"
if [ "$#" == "0" ]; then
echo "$USAGE"
exit 1
fi
while (( "$#" )); do
if [[ $(ls "$1") == "" ]]; then
echo "Répertoire vide, rien à faire."
else
find "$1" -type f -a -atime +365 -exec rm -i {} \;
fi
shift
done
![]() |
-exec versus xargs |
|---|---|
|
La commande find ci-dessus peut être remplacée par ce qui suit :
La commande xargs
construit et exécute des lignes de commandes depuis l'entrée standard.
Ceci présente l'avantage que la ligne de commande est renseignée
jusqu'à ce que la limite du système soit atteinte. Seulement à ce
moment la commande à exécuter sera lancée, dans l'exemple ci-dessus ce
serait rm. Si il y a
plus de paramètres, une nouvelle ligne de commande sera utilisée,
jusqu'à ce qu'elle soit elle aussi pleine ou jusqu'à ce qu'il n'y ait
plus de paramètres. La même chose avec find |
Dans l'exemple suivant, nous avons modifié le script de la Section 2.4.4, « Les documents intégrés (NdT : here documents, que l'on appele aussi 'document lié') » afin qu'il accepte de multiples paquets à installer d'un coup :
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Utilisation : $0 package(s)"
exit 1
fi
while (($#)); do
yum install "$1" << CONFIRM
y
CONFIRM
shift
done
Pouvez-vous expliquer pourquoi il est si important de mettre les variables entre guillemets dans l'exemple de la Section 4.2, « Redirection des sorties » ?
Ecrivez un script similaire à celui de la Section 5.1, « L'intégrée break », mais pensez à un moyen de quitter après que l'usager ait effectué 3 boucles.
Penser à une meilleur solution que move -b pour le script de la Section 5.3, « Exemples »
pour éviter d'écraser les fichiers existants. Par exemple, tester si un
fichier existe ou pas. Ne faites pas de travail inutile!
Réécrire le script whichdaemon.sh de la Section 2.4, « Opérations booléennes », de sorte qu'il :
Affiche une liste des serveurs à contrôler, tel que Apache, le serveur SSH, le démon NTP, un démon nom, un démon d'administration, etc.
Pour chaque choix l'utilisateur peut afficher des informations importantes, telles que le nom du serveur WEB, les informations de trace NTP, etc.
Optionnellement, prévoir une possibilité pour les utilisateurs de contrôler d'autres serveurs que ceux listés. Dans de tels cas, vérifiez que au moins le processus en question tourne.
Revoir les scripts de la Section 2.2.4, « Calcul d'une moyenne ». Remarquez comment les caractères entrés autre que q sont traités. Réécrire ce script afin qu'il affiche un message si des caractères sont saisis.
Résumé
Dans ce chapitre, nous aborderons l'emploi plus poussé des variables et paramètres. Une fois achevé, vous serez capable de :
Déclarer et utiliser un tableau de variables
Spécifier le type de variable que vous voulez utiliser
Rendre les variables en lecture seule
Employer set pour affecter une valeur à une variable
[bob in ~]VARIABLE=12[bob in ~]echo$VARIABLE
12[bob in ~]VARIABLE=string[bob in ~]echo$VARIABLE
string
Il y a des cas où vous voulez éviter
ce genre de comportement, par exemple quand vous manipulez des numéros
de téléphone et autres codifications. A part les entiers et les
variables, vous pourriez aussi vouloir spécifier une variable avec une
valeur constante. Ceci est souvent fait au début du script, quand la
valeur de la constante est définie. Ensuite, il est seulement fait
référence au nom de la variable stockant la constante, de sorte que
quand la logique veut que la constante soit changée, cela n'est fait
qu'à un endroit. Une variable peut aussi être une série de variables de
tout type, c'est à dire un tableau de variables (VAR0VAR1, VAR2, ... VARN).
Avec l'instruction declare nous pouvons encadrer l'affectation de valeur à une variable.
La syntaxe de declare est la suivante :
Tableau 10.1. Options de l'intégrée declare
| Option | sens |
|---|---|
-a |
Variable tableau. |
-f |
Utilise uniquement les noms de fonction |
-i |
La variable doit être considérée en tant qu'entier, une évaluation arithmétique est effectuée quand une valeur est assignée à la variable (voir Section 4.6, « L'expansion arithmétique »). |
-p |
Affiche les attributs et la valeur de chaque variable. Quand -p est employé, les options supplémentaires sont ignorées. |
-r |
fait que la variable est en lecture seule. A cette variable ne peut alors lui être affecté une autre valeur par une instruction ultérieure, de même qu'elle ne peut être supprimée. |
-t |
Donne à chaque variable l'attribut trace. |
-x |
Marque chaque variable comme exportée pour les commandes suivantes via l'environnement. |
L'exemple suivant montre comment l'assignation du type de variable influence la valeur.
[bob in ~]declare-iVARIABLE=12[bob in ~]VARIABLE=string[bob in ~]echo$VARIABLE
0[bob in ~]declare-pVARIABLE
declare -i VARIABLE="0"
[bob in ~]OTHERVAR=blah[bob in ~]declare-pOTHERVAR
declare -- OTHERVAR="blah"
Voir les pages info de Bash pour une aide sur le statut renvoyé.
La valeur de ces variables ne peut plus être changée par une instruction ultérieure. Si l'option -f est donnée, chaque variable réfère à une fonction Shell ; voir Chapitre 11, Fonctions. If -a
est spécifié, chaque variable réfère
à un tableau de variables. Si aucun argument n'est donné,
ou si -p est indiqué, une liste de toutes les variables en lecture est affichée. Avec l'option -p le résultat peut être réutilisé comme entrée.
Le
statut d'exécution est zéro, à moins qu'une option invalide ait été
spécifiée, qu'une des variables ou fonctions n'existe pas, ou que -f ait été fourni en tant que nom de variable au lieu d'un nom de fonction.
[bob in ~]readonlyTUX=penguinpower[bob in ~]TUX=Mickeysoft
bash: TUX: readonly variable
Un tableau est une variable contenant plusieurs valeurs. Toute variable peut être utilisée comme étant un tableau. Il n'y a pas de limite maximum à la taille d'un tableau, ni de besoin que les éléments soient indexés ou assignés de façon contiguë. Les tableaux démarrent à zéro : le premier élément est donc adressé avec le numéro 0.
Une déclaration indirecte peut se faire avec la syntaxe suivante de déclaration de variable :
Le INDEXNR est traité comme une expression arithmétique qui doit être évalué comme nombre positif.
Une déclaration explicite d'un tableau est faite avec l'intégrée declare :
Une déclaration avec un numéro d'index sera aussi acceptée, mais le numéro d'index sera ignoré. Des attributs du tableau peuvent être spécifiés en employant les intégrées declare et readonly. Les attributs s'appliquent à toutes les variables du tableau ; vous ne pouvez avoir des tableaux mitigés.
Les variables de tableau peuvent aussi être créées avec une affectation composée selon ce format :
Ajouter un élément manquant ou suplémentaire à un tableau se fait avec la syntaxe :
Afin de se référer au contenu d'un élément du tableau, employer le symbole accolade. C'est nécessaire, comme vous le voyez dans l'exemple suivant, pour échapper à l'interprétation du Shell des opérateurs d'expansion. Si le numéro d'index est @ ou *, tous les éléments du tableau sont considérés.
[bob in ~]ARRAY=(one two three)[bob in ~]echo${ARRAY[*]}
one two three[bob in ~]echo$ARRAY[*]
one[*][bob in ~]echo${ARRAY[2]}
three[bob in ~]ARRAY[3]=four[bob in ~]echo${ARRAY[*]}
one two three four
L'intégrée unset est employée pour détruire un tableau ou des variables éléments du tableau :
[bob in ~]unsetARRAY[1][bob in ~]echo${ARRAY[*]}
one three four[bob in ~]unsetARRAY[bob in ~]echo${ARRAY[*]}
<--no output-->
Exemples pratiques de la manipulation de tableaux sont difficiles à trouver. Vous trouverez plein de scripts qui ne font pas autre chose sur votre système que de calculer des séries mathématiques avec des tableaux, par exemple. Et ça devrait être l'un des exemples les plus intéressants...la plupart des scripts ne font que montrer d'une façon hyper simplifiée et théorique ce que vous pouvez faire avec les tableaux.
#!/bin/bash
if [ $(whoami) != 'root' ]; then
echo "Must be root to run $0"
exit 1;
fi
if [ -z $1 ]; then
echo "Utilisation : $0 </path/to/httpd.conf>"
exit 1
fi
httpd_conf_new=$1
httpd_conf_path="/usr/local/apache/conf"
login=htuser
farm_hosts=(web03 web04 web05 web06 web07)
for i in ${farm_hosts[@]}; do
su $login -c "scp $httpd_conf_new ${i}:${httpd_conf_path}"
su $login -c "ssh $i sudo /usr/local/apache/bin/apachectl graceful"
done
exit 0
D'abord 2 tests sont
effectués pour contrôler que l'utilisateur idoïne
fait s'exécuter ce script avec les paramètres ad hoc. Les noms des hôtes qui doivent être configurés sont listés dans le tableau farm_hosts.
Puis tous ces hôtes sont chargés avec le fichier de configuration
Apache, après quoi le démon est redémarré. Notez l'emploi de commandes
de la suite Secure Shell, qui encryptent les connections aux hôtes
distants.
Merci, Eugène et ses collègues, pour cette contribution.
Dan Richter a fourni l'exemple suivant. Voici le problème auquel il était confronté :
#!/bin/bash
# Ceci est le script : get-tester-address.sh
#
# D'abord nous testons si Bash admet les tableaux..
# (Les tableaux ont été ajoutés récemment.)
#
whotest[0]='test' || (echo 'Echec : les tableaux ne sont pas admis dans cette version de Bash.' && exit 2)
#
# Our list of candidates. (Vous êtes libre d'ajouter
# ou d'enlever des candidats.)
#
wholist=(
'Bob Smith <bob@example.com>'
'Jane L. Williams <jane@example.com>'
'Eric S. Raymond <esr@example.com>'
'Larry Wall <wall@example.com>'
'Linus Torvalds <linus@example.com>'
)
#
# Compte le nombre de testeurs candidats.
# (Boucle jusqu'à trouver une chaîne vide.)
#
count=0
while [ "x${wholist[count]}" != "x" ]
do
count=$(( $count + 1 ))
done
#
# Maintenant nous calculons à qui c'est le tour.
#
week=`date '+%W'` # La semaine dans l'année (0..53).
week=${week#0} # Elimine de possible zéro au début.
let "index = $week % $count" # week modulo count = la personne gâtée
email=${wholist[index]} # Récupérer l'adresse email de cette personne.
echo $email # Affiche l'adresse email.
email=`get-tester-address.sh` # Trouver à qui envoyer le courriel.
hostname=`hostname` # Le nom de la machine locale.
#
# Envoyer le courriel à la bonne personne.
#
mail $email -s '[Demo Testing]' <<EOF
La personne gâtée de la semaine est : $email
Rappel : la liste de démonstrations est ici :
http://web.example.com:8080/DemoSites
(Ce courriel a été généré par $0 depuis ${hostname}.)
EOF
La syntaxe ${#VAR} calcul le nombre de caractères d'une variable. Si VAR vaut « * » ou « @ »,
cette valeur est remplacée par le nombre de paramètres
positionnels ou le nombre d'éléments dans le tableau en général. En voici une démonstration ci-dessous :
[bob in ~]echo$SHELL
/bin/bash[bob in ~]echo${#SHELL}
9[bob in ~]ARRAY=(one two three)[bob in ~]echo${#ARRAY}
3
[bob in ~]echo${TEST:-test}
test[bob in ~]echo$TEST
[bob in ~]exportTEST=a_string[bob in ~]echo${TEST:-test}
a_string[bob in ~]echo${TEST2:-$TEST}
a_string
Cette forme est souvent employée dans les tests conditionnels, par exemple dans celui-ci :
[ -z "${COLUMNS:-}" ] && COLUMNS=80
C'est une notation plus courte pour
if [ -z "${COLUMNS:-}" ]; then
COLUMNS=80
fi
Voir la Section 1.2.3, « Comparaisons de chaînes » pour plus de détails au sujet de ce type de test de condition.
Si le tiret (-) est remplacé par le signe égal (=), la valeur est affectée au paramètre si il n'existe pas :
[bob in ~]echo$TEST2[bob in ~]echo${TEST2:=$TEST}
a_string[bob in ~]echo$TEST2
a_string
La syntaxe suivante teste l'existence d'une variable. Si elle n'est pas déclarée, l'expansion de WORD est affichée sur le standard de résultat et un Shell non-interactif se termine. Une démonstration :
[bob in ~]catvartest.sh
#!/bin/bash
# Ce script teste si une variable est déclarée. Si non,
# Il quitte en affichant un message.
echo ${TESTVAR:?"Il y a tellement encore que je voudrais faire..."}
echo "TESTVAR est déclarée, nous pouvons traiter."[bob in testdir]./vartest.sh
./vartest.sh: line 6: TESTVAR: Il y a tellement encore que je voudrais faire...[bob in testdir]exportTESTVAR=present[bob in testdir]./vartest.sh
present
TESTVAR est déclarée, nous pouvons traiter.
Avec « + » au lieu du point d'exclamation la variable prend la valeur de l'expansion de WORD ; si elle n'existe pas, rien ne se produit.
Pour éliminer d'une variable un nombre de caractères égal à OFFSET, la syntaxe à employer est :
[bob in ~]exportSTRING="thisisaverylongname"[bob in ~]echo${STRING:4}
isaverylongname[bob in ~]echo${STRING:6:5}
avery
Si VAR est une variable tableau indexée par « * » ou « @ », l'opération de substitution de patron est effectuée pour chaque élément du tableau
l'un après l'autre, et l'expansion est la liste
résultante. Ceci est montré dans l'exemple
ci-dessous :
[bob in ~]echo${ARRAY[*]}
one two one three one four[bob in ~]echo${ARRAY[*]#one}
two three four[bob in ~]echo${ARRAY[*]#t}
one wo one hree one four[bob in ~]echo${ARRAY[*]#t*}
one wo one hree one four[bob in ~]echo${ARRAY[*]##t*}
one one one four
[bob in ~]echo$STRING
thisisaverylongname[bob in ~]echo${STRING%name}
thisisaverylong
Résumé
Dans ce chapitre nous aborderons :
Qu'est-ce qu'une fonction
Création et affichage de fonctions depuis la ligne de commande
Fonctions dans les scripts
Passer des arguments à une fonction
Quand utiliser une fonction
Les fonctions emploient plutôt la syntaxe
![]() |
Erreurs communes |
|---|---|
|
Les accolades doivent être séparées du corps de la fonction par un espace, sinon elles sont interprétées d'une mauvaise façon. Le corps d'une fonction doit se terminer par un point-virgule ou un saut de ligne. |
Quand une fonction est exécutée, les arguments de la fonction deviennent les paramètres positionnels le temps de l'exécution. Le paramètre spécial #
qui est remplacé par le nombre de paramètres positionnels
est modifié en conséquence. Le paramètre
positionnel 0 est inchangé. La variable Bash FUNCNAME est valorisé avec le nom de la fonction, tandis qu'elle s'exécute.
Si l'intégrée return
est exécutée dans une fonction, la fonction s'interrompt et l'exécution
reprend avec la commande qui suit la fonction appelée. Quand une
fonction s'achève, les valeurs des paramètres positionnels et le
paramètre spécial #
sont restaurés à la valeur qu'ils avaient avant
l'exécution de la fonction. Si un argument numérique est
donné à return, c'est ce statut qui est retourné. Un exemple simple :
[lydia@cointreau ~/test]catshowparams.sh
#!/bin/bash
echo "Ce script montre l'emploi d'arguments de fonction."
echo
echo "Le paramètre positionnel 1 pour le script est $1."
echo
test ()
{
echo "Le paramètre positionnel 1 pour la fonction est $1."
RETURN_VALUE=$?
echo "Le code retour de cette fonction est $RETURN_VALUE."
}
test other_param[lydia@cointreau ~/test]./showparams.shparameter1
Ce script montre l'emploi d'arguments de fonction.
Le paramètre positionnel 1 pour le script est 1.
Le paramètre positionnel 1 pour la fonction est other_param.
Le code retour de cette fonction est 0.[lydia@cointreau ~/test]
if [ $RETVAL -eq 0 ]; then
<lancer le démon>
Ou comme cet exemple tiré du script /etc/init.d/amd, où l'optimisation de Bash est mis en oeuvre.
[ $RETVAL = 0 ] && touch /var/lock/subsys/amd
Le dimanche, seul bupbash est exécuté.
#/bin/bash
LOGFILE="/nethome/tille/log/backupscript.log"
echo "Starting backups for `date`" >> "$LOGFILE"
buplinux()
{
DIR="/nethome/tille/xml/db/linux-basics/"
TAR="Linux.tar"
BZIP="$TAR.bz2"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"
cd "$DIR"
tar cf "$TAR" src/*.xml src/images/*.png src/images/*.eps
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
echo -e "Done backing up Linux course:\nSource files, PNG and EPS images.\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}
bupbash()
{
DIR="/nethome/tille/xml/db/"
TAR="Bash.tar"
BZIP="$TAR.bz2"
FILES="bash-programming/"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"
cd "$DIR"
tar cf "$TAR" "$FILES"
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
echo -e "Done backing up Bash course:\n$FILES\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}
DAY=`date +%w`
if [ "$DAY" -lt "2" ]; then
echo "It is `date +%A`, only backing up Bash course." >> "$LOGFILE"
bupbash
else
buplinux
bupbash
fi
echo -e "Remote backup `date` SUCCESS\n----------" >> "$LOGFILE"
Il pourrait être observé que toutes les étapes peuvent être combinées en une commande telle que
Résumé
Dans ce chapitre nous traiterons les sujets suivants :
Signaux disponibles
Intérêt des signaux
Emploi de l'instruction trap
Comment éviter que les usagers interrompent votre programme
SIGHUP par défaut fait quitter le Shell. Un Shell interactif enverra un SIGHUP à tous les travaux, en exécution ou pas ; voir la documentation sur l'intégrée disown si vous souhaitez désactiver ce comportement pour un processus particulier. Utilisez l'option huponexit pour tuer tous les travaux à la réception du signal SIGHUP avec l'intégrée shopt.
Les signaux suivants peuvent être envoyés en utilisant le Shell Bash :
Tableau 12.1. Les signaux de contrôle dans Bash
| Combinaison standard de touches | sens |
|---|---|
| Ctrl+C | Le signal d'interruption, envoie SIGINT à tous les travaux s'exécutant dans le Shell courant. |
| Ctrl+Y | Le caractère delayed suspend. Provoque la suspension d'un processus actif quand il tente de lire son entrée depuis le terminal. Le contrôle est rendu au Shell, l'utilisateur peut renvoyer en tâche de fond, réactiver ou tuer le processus. 'Delayed suspend' n'est pas une fonctionnalité connue de tous les systèmes. |
| Ctrl+Z | Le signal suspend envoie SIGTSTP à un programme en train de s'exécuter, donc il s'arrête et redonne le contrôle au Shell. |
![]() |
Paramètres du terminal |
|---|---|
|
Vérifiez les paramètres stty. La suspension et la reprise d'affichage sont généralement désactivées si vous utilisez des émulations « modernes » de terminaux. Le xterm standard reconnaît Ctrl+S et Ctrl+Q par défaut. |
Les 2 commandes kill envoient le signal TERM si aucun n'est donné.
Voici une liste des principaux signaux :
Tableau 12.2. Signaux courants de kill
| Nom du signal | Valeur du signal | Effet |
|---|---|---|
| SIGHUP | 1 | Suspend |
| SIGINT | 2 | Interruption depuis le clavier |
| SIGKILL | 9 | signal kill |
| SIGTERM | 15 | signal d'arrêt d'exécution |
| SIGSTOP | 17,19,23 | Stoppe le processus |
![]() |
SIGKILL et SIGSTOP |
|---|---|
|
SIGKILL et SIGSTOP ne peuvent pas être trappés, bloqués ou ignorés. |
maud: ~>ps-ef| grepstuck_process
maud 5607 2214 0 20:05 pts/5 00:00:02 stuck_processmaud: ~>kill-95607maud: ~>ps-ef| grepstuck_process
maud 5614 2214 0 20:15 pts/5 00:00:00 grep stuck_process
[1]+ Killed stuck_process
La syntaxe de l'instruction trap est directe :
#!/bin/bash
# traptest.sh
trap "echo Booh!" SIGINT SIGTERM
echo "pid is $$"
while : # Ceci est équivalent à « while true ».
do
sleep 60 # Ce script ne fait pas vraiment quelque chose.
done
Résumé
Ce document donne une vue globale des possibilités courantes d'un Shell et des spécificités possibles.
Tableau A.1. Fonctionnalités courantes du Shell
| Commande | sens |
|---|---|
| > | Redirige la sortie |
| >> | Ajoute en fin de fichier |
| < | Redirige l'entrée |
| << | Document en ligne (redirige l'entrée) |
| | | Sortie par un tube |
| & | Place le travail en tâche de fond. |
| ; | Sépare des commandes sur une même ligne |
| * | Correspond à n'importe quel(s) caractère(s) dans un nom de fichier |
| ? | Correspond à n'importe quel caractère unique dans un nom de fichier |
| [ ] | Correspond à n'importe quels caractères inclus |
| ( ) | S'exécute dans un sous-Shell |
| ` ` | Substitue le contenu par le résultat de la commande incluse |
| " " | Guillemets ou citation partielle (permet l'expansion de variables et de commandes) |
| ' ' | Apostrophes ou citation totale (pas d'expansion) |
| \ | Citation du caractère qui suit (NdT : emploi du caractère dans son sens littéral->échappement) |
| $var | Emploie la valeur de la variable |
| $$ | Identifiant du processus |
| $0 | Nom de la Commande |
| $n | Nième argument (N entre 0 et 9) |
# |
Commence un commentaire |
| bg | Exécution en tâche de fond |
| break | Sortir d'une instruction de boucle |
| cd | Change de répertoire |
| continue | Passe à l'itération suivante d'une boucle dans un programme |
| echo | Affiche le résultat |
| eval | Evalue les arguments |
| exec | Exécute un nouveau processus Shell |
| fg | Exécution dans la session en cours |
| jobs | Affiche les travaux en cours |
| kill | Termine un travail en cours |
| newgrp | Change de groupe l'utilisateur |
| shift | Décale les paramètres positionnels |
| stop | Suspend un travail en tâche de fond |
| suspend | Suspend un travail en cours dans la session |
| time | Chronomètre une commande |
| umask | Donne ou liste les permissions sur les fichiers |
| unset | Supprime une variable ou une fonction |
| wait | Attend qu'une tâche de fond se termine |
![]() |
Compatibilité des Shell |
|---|---|
|
Parce que Bash est un sur-ensemble de sh, toutes les commandes sh fonctionnent en Bash - mais pas vice versa. Bash a bien plus de possibilités qui lui sont propres, et, comme le montre la table suivante, beaucoup de possibilités venant d'autres Shell. Parce que le Turbo C Shell est un sur-ensemble de csh, toutes les commandes csh fonctionnent en tcsh, mais l'inverse n'est pas vrai. |
Tableau A.2. Différences de fonctionnalités des Shell
| sh | Bash | ksh | csh | Signification/Action |
|---|---|---|---|---|
| $ | $ | $ | % | L'invite utilisateur par défaut |
| >| | >| | >! | Force la redirection | |
> fichier 2>&1 |
&> fichier ou > fichier 2>&1 |
> fichier 2>&1 |
>& fichier |
Redirige stdout et stderr sur fichier |
| { } | { } | Expansion des éléments de la liste | ||
| `commande` | `commande` ou $(commande) | $(commande) | `commande` | Remplace par le résultat de la commande incluse |
$HOME |
$HOME |
$HOME |
$home |
Répertoire utilisateur |
| ~ | ~ | ~ | Symbole équivalent au répertoire utilisateur | |
~+, ~-, dirs |
~+, ~- |
=-, =N |
Accède à la pile des répertoires | |
var=value |
VAR=value |
var=value |
set var=value |
Affectation de variable |
export var |
export VAR=value |
export var=val |
setenv var val |
Publie une variable d'environnement |
${nnnn} |
${nn} |
Les paramètres peuvent être référencés au delà des 9 premiers | ||
"$@" |
"$@" |
"$@" |
Chaque argument est connu comme une valeur indépendante | |
$# |
$# |
$# |
$#argv |
Le nombre d'arguments |
$? |
$? |
$? |
$status |
Statut d'exécution de la commande la plus récente |
$! |
$! |
$! |
PID de la tâche de fond la plus récente | |
$- |
$- |
$- |
Options classiques | |
. fichier |
source fichier ou . fichier |
. fichier |
source fichier |
Lecture de commandes depuis un fichier |
| alias x='y' | alias x=y | alias x y | Nom x est équivalent à la commande y | |
| case | case | case | switch ou case | Décline différentes éventualités |
| done | done | done | end | Fini une instruction de boucle |
| esac | esac | esac | endsw | Marque la fin du case ou du switch |
exit n |
exit n |
exit n |
exit (expr) |
Quitte avec un statut d'exécution |
| for/do | for/do | for/do | foreach | Boucles sur plusieurs variables |
set -f, set -o nullglob|dotglob|nocaseglob|noglob |
noglob | Ignore la substitution de caractères dans la génération de fichier | ||
| hash | hash | alias -t |
hashstat | Affiche les commandes 'hash' (trace les alias) |
hash cmds |
hash cmds |
alias -t cmds |
rehash | Mémorise où se situe la commande |
hash -r |
hash -r |
unhash | Annule la mémorisation | |
| history | history | history | Liste les commandes passées | |
| ArrowUp+Enter ou !! | r | !! | Relance la commande précédente | |
!str |
r str |
!str |
Relance la commande la plus récemment passée qui commence par « str » | |
!cmd:s/x/y/ |
r x=y cmd |
!cmd:s/x/y/ |
Remplace « x » par « y » dans la commande la plus récemment passée commençant par « cmd », puis exécute. | |
if [ $i -eq 5 ] |
if [ $i -eq 5 ] |
if ((i==5)) |
if ($i==5) |
Echantillon de tests de conditions |
| fi | fi | fi | endif | Marque la fin de l'instruction if |
| ulimit | ulimit | ulimit | limit | Déclare une limite de ressource |
| pwd | pwd | pwd | dirs | Affiche le répertoire courant |
| read | read | read | $< | Lecture depuis l'entrée |
trap 2 |
trap 2 |
trap 2 |
onintr | A pour effet d'ignorer les interruptions |
| unalias | unalias | unalias | Détruit les alias | |
| until | until | until | Begin until loop | |
| while/do | while/do | while/do | while | Begin while loop |
Version 1.1, March 2000
Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
Formate des fichiers qui puissent être imprimés sur une imprimante PostScript.
Créer un nouvel utilisateur ou modifier les informations par défaut de nouveaux utilisateurs.
Exécute des commandes périodiquement, ne suppose pas que l'ordinateur fonctionne en continu.
Place en file d'attente, examine ou supprime des travaux en attente d'exécution.
Ajoute un système de fichiers MS-DOS à une disquette formatée en faible densité.
Monte un système de fichiers ou affiche les informations sur les systèmes de fichiers montés.
Contrôle les opérations des périphériques à bande magnétique.
Chronomètre une commande simple ou affiche l'utilisation des ressources.
Affiche la route que les paquets prennent jusqu'à un hôte réseau.
Un contrôleur d'intégrité de fichiers sur les systèmes UNIX.
Gestionnaire de tabulations du système de gestion de fenêtre X.