Un shell est l’interpréteur de commandes pour le système d’exploitation. Bash est mon shell préféré, mais chaque shell Linux interprète les commandes tapées par l’utilisateur ou le sysadmin dans une forme que le système d’exploitation peut utiliser. Lorsque les résultats sont renvoyés au programme shell, celui-ci les envoie à STDOUT qui, par défaut, les affiche dans le terminal. Tous les shells que je connais sont aussi des langages de programmation.
Des fonctionnalités comme la complétion de tabulation, le rappel et l’édition de la ligne de commande, et des raccourcis comme les alias, contribuent à sa valeur en tant que shell puissant. Son mode d’édition de la ligne de commande par défaut utilise Emacs, mais l’une de mes fonctionnalités préférées de Bash est que je peux le changer en mode Vi pour utiliser des commandes d’édition qui font déjà partie de ma mémoire musculaire.
Cependant, si vous pensez à Bash uniquement comme un shell, vous manquez une grande partie de sa véritable puissance. En faisant des recherches pour mon cours d’auto-apprentissage de Linux en trois volumes (sur lequel cette série d’articles est basée), j’ai appris des choses sur Bash que je n’avais jamais connues en plus de 20 ans de travail avec Linux. Certaines de ces nouvelles connaissances concernent son utilisation en tant que langage de programmation. Bash est un langage de programmation puissant, un langage parfaitement conçu pour être utilisé sur la ligne de commande et dans les scripts shell.
Cette série en trois parties explore l’utilisation de Bash comme langage de programmation d’interface de ligne de commande (CLI). Ce premier article examine une certaine programmation simple en ligne de commande avec Bash, les variables et les opérateurs de contrôle. Les autres articles explorent les types de fichiers Bash, les opérateurs logiques de type chaîne de caractères, numérique et autres qui fournissent une logique de contrôle du flux d’exécution, les différents types d’extensions du shell et les boucles for, while et until qui permettent des opérations répétitives. Ils examineront également certaines commandes qui simplifient et soutiennent l’utilisation de ces outils.
Le shell
Un shell est l’interpréteur de commandes pour le système d’exploitation. Bash est mon shell préféré, mais chaque shell Linux interprète les commandes tapées par l’utilisateur ou le sysadmin dans une forme que le système d’exploitation peut utiliser. Lorsque les résultats sont renvoyés au programme shell, il les affiche dans le terminal. Tous les shells que je connais sont aussi des langages de programmation.
Bash signifie Bourne Again Shell parce que le shell Bash est basé sur l’ancien shell Bourne qui a été écrit par Steven Bourne en 1977. De nombreux autres shells sont disponibles, mais ce sont les quatre que je rencontre le plus fréquemment :
- csh : Le shell C pour les programmeurs qui aiment la syntaxe du langage C
- ksh : Le shell Korn, écrit par David Korn et populaire auprès des utilisateurs d’Unix
- tcsh : Une version de csh avec plus de fonctionnalités de facilité d’utilisation
- zsh : Le shell Z, qui combine de nombreuses fonctionnalités d’autres shells populaires
Tous les shells ont des commandes intégrées qui complètent ou remplacent celles fournies par les utilitaires de base. Ouvrez la page de manuel du shell et trouvez la section « BUILT-INS » pour voir les commandes qu’il fournit.
Chaque shell a sa propre personnalité et sa propre syntaxe. Certains fonctionneront mieux pour vous que d’autres. J’ai utilisé le shell C, le shell Korn, et le shell Z. J’aime toujours le shell Bash plus que n’importe lequel d’entre eux. Utilisez celui qui fonctionne le mieux pour vous, même si cela peut vous obliger à essayer certains des autres. Heureusement, il est assez facile de changer de shell.
Tous ces shells sont des langages de programmation, ainsi que des interpréteurs de commandes. Voici un tour rapide de quelques constructions et outils de programmation qui font partie intégrante de Bash.
Bash comme langage de programmation
La plupart des sysadmins ont utilisé Bash pour émettre des commandes qui sont généralement assez simples et directes. Mais Bash peut aller au-delà de la saisie de commandes uniques, et de nombreux sysadmins créent des programmes de ligne de commande simples pour effectuer une série de tâches. Ces programmes sont des outils courants qui permettent d’économiser du temps et des efforts.
Mon objectif, lorsque j’écris des programmes CLI, est d’économiser du temps et des efforts (c’est-à-dire d’être le sysadmin paresseux). Les programmes CLI soutiennent cela en listant plusieurs commandes dans une séquence spécifique qui s’exécutent l’une après l’autre, de sorte que vous n’avez pas besoin de regarder la progression d’une commande et de taper la commande suivante lorsque la première se termine. Vous pouvez aller faire d’autres choses et ne pas avoir à surveiller continuellement la progression de chaque commande.
Qu’est-ce qu’un « programme »?
Le Free On-line Dictionary of Computing (FOLDOC) définit un programme comme suit : « Les instructions exécutées par un ordinateur, par opposition au dispositif physique sur lequel elles s’exécutent ». Le WordNet de l’Université de Princeton définit un programme comme suit : » …une séquence d’instructions qu’un ordinateur peut interpréter et exécuter… « . Wikipedia a également une bonne entrée sur les programmes informatiques.
Donc, un programme peut consister en une ou plusieurs instructions qui exécutent une tâche spécifique et liée. Une instruction de programme informatique est également appelée une déclaration de programme. Pour les sysadmins, un programme est généralement une séquence de commandes shell. Tous les shells disponibles pour Linux, du moins ceux que je connais, ont au moins une forme de base de capacité de programmation, et Bash, le shell par défaut de la plupart des distributions Linux, ne fait pas exception.
Bien que cette série utilise Bash (parce qu’il est si omniprésent), si vous utilisez un shell différent, les concepts généraux de programmation seront les mêmes, bien que les constructions et la syntaxe puissent différer quelque peu. Certains interpréteurs de commandes peuvent prendre en charge certaines fonctionnalités que d’autres ne prennent pas en charge, mais ils offrent tous une certaine capacité de programmation. Les programmes de shell peuvent être stockés dans un fichier pour une utilisation répétée, ou ils peuvent être créés sur la ligne de commande selon les besoins.
Programmes CLI simples
Les programmes de ligne de commande les plus simples sont une ou deux déclarations de programme consécutives, qui peuvent être liées ou non, qui sont entrées sur la ligne de commande avant que la touche Entrée soit pressée. La deuxième déclaration d’un programme, s’il y en a une, pourrait dépendre des actions de la première, mais il n’est pas nécessaire qu’elle le soit.
Il y a aussi un peu de ponctuation syntaxique qui doit être clairement énoncé. Lorsque vous saisissez une seule commande sur la ligne de commande, l’appui sur la touche Entrée termine la commande par un point-virgule implicite ( ;). Lorsqu’il est utilisé dans un programme shell CLI saisi sur une seule ligne de commande, le point-virgule doit être utilisé pour terminer chaque instruction et la séparer de la suivante. La dernière déclaration d’un programme shell CLI peut utiliser un point-virgule explicite ou implicite.
Une certaine syntaxe de base
Les exemples suivants clarifieront cette syntaxe. Ce programme consiste en une seule commande avec un terminateur explicite:
$ echo "Hello world." ;
Hello world.
Cela peut sembler ne pas être un grand programme, mais c’est le premier programme que je rencontre avec chaque nouveau langage de programmation que j’apprends. La syntaxe peut être un peu différente pour chaque langage, mais le résultat est le même.
Détaillons un peu ce programme trivial mais omniprésent. Vos résultats seront différents des miens parce que j’ai fait d’autres expériences, alors que vous pouvez n’avoir que les répertoires et les fichiers par défaut qui sont créés dans le répertoire d’accueil du compte la première fois que vous vous connectez à un compte via le bureau de l’interface graphique.
$ echo "My home directory." ; ls ;
My home directory.
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1
Cela a un peu plus de sens. Les résultats sont liés, mais les déclarations de programme individuelles sont indépendantes les unes des autres. Remarquez que j’aime mettre des espaces avant et après le point-virgule car cela rend le code un peu plus facile à lire. Essayez à nouveau ce petit programme CLI sans point-virgule explicite à la fin :
$ echo "My home directory." ; ls
Il n’y a aucune différence dans la sortie.
Quelque chose à propos des variables
Comme tous les langages de programmation, le shell Bash peut traiter des variables. Une variable est un nom symbolique qui fait référence à un emplacement spécifique en mémoire qui contient une valeur quelconque. La valeur d’une variable est modifiable, c’est-à-dire qu’elle est variable.
Bash ne tape pas les variables comme le C et les langages apparentés, en les définissant comme des entiers, des points flottants ou des types de chaîne. En Bash, toutes les variables sont des chaînes de caractères. Une chaîne de caractères qui est un nombre entier peut être utilisée dans l’arithmétique des nombres entiers, qui est le seul type de mathématiques que Bash est capable de faire. Si des mathématiques plus complexes sont nécessaires, la commande bc peut être utilisée dans les programmes et les scripts CLI.
Les variables se voient attribuer des valeurs et peuvent être utilisées pour faire référence à ces valeurs dans les programmes et les scripts CLI. La valeur d’une variable est définie à l’aide de son nom mais n’est pas précédée du signe $. L’affectation VAR=10 définit la valeur de la variable VAR à 10. Pour imprimer la valeur de la variable, vous pouvez utiliser l’instruction echo $VAR. Commencez par des variables de type texte (c’est-à-dire non numériques).
Les variables Bash font partie de l’environnement du shell jusqu’à ce qu’elles soient désactivées.
Vérifiez la valeur initiale d’une variable qui n’a pas été assignée ; elle doit être nulle. Attribuez ensuite une valeur à la variable et imprimez-la pour vérifier sa valeur. Vous pouvez faire tout cela dans un seul programme CLI :
$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
Hello World
$
Note : la syntaxe de l’affectation des variables est très stricte. Il ne doit y avoir aucun espace de part et d’autre du signe égal (=) dans l’instruction d’affectation.
La ligne vide indique que la valeur initiale de MyVar est nulle. La modification et la définition de la valeur d’une variable se font de la même manière. Cet exemple montre à la fois la valeur initiale et la nouvelle valeur.
Comme mentionné, Bash peut effectuer des calculs arithmétiques entiers, ce qui est utile pour calculer une référence à l’emplacement d’un élément dans un tableau ou faire des problèmes mathématiques simples. Il n’est pas adapté aux calculs scientifiques ou à tout ce qui nécessite des décimales, comme les calculs financiers. Il existe de bien meilleurs outils pour ces types de calculs.
Voici un calcul simple :
$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63
Que se passe-t-il lorsque vous effectuez une opération mathématique qui aboutit à un nombre à virgule flottante ?
Le résultat est le nombre entier le plus proche. Remarquez que le calcul a été effectué dans le cadre de l’instruction echo. L’opération mathématique est effectuée avant la commande echo qui l’entoure en raison de l’ordre de préséance de Bash. Pour plus de détails, consultez la page de manuel Bash et recherchez « precedence. »
Opérateurs de contrôle
Les opérateurs de contrôle shell sont l’un des opérateurs syntaxiques permettant de créer facilement des programmes en ligne de commande intéressants. La forme la plus simple de programme CLI consiste simplement à enchaîner plusieurs commandes dans une séquence sur la ligne de commande :
command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;
Ces commandes s’exécutent toutes sans problème tant qu’aucune erreur ne se produit. Mais que se passe-t-il lorsqu’une erreur se produit ? Vous pouvez anticiper et permettre les erreurs en utilisant les opérateurs de contrôle intégrés && et || Bash. Ces deux opérateurs de contrôle fournissent un certain contrôle du flux et vous permettent de modifier la séquence d’exécution du code. Le point-virgule est également considéré comme un opérateur de contrôle Bash, tout comme le caractère nouvelle ligne.
L’opérateur && dit simplement : « si la commande1 réussit, alors exécutez la commande2. Si la commande1 échoue pour une raison quelconque, alors la commande2 est sautée. » Cette syntaxe ressemble à ceci:
command1 && command2
Maintenant, regardez quelques commandes qui vont créer un nouveau répertoire et – si cela réussit – en faire le répertoire de travail actuel (PWD). Assurez-vous que votre répertoire personnel (~) est le PWD. Essayez d’abord ceci dans /root, un répertoire auquel vous n’avez pas accès:
L’erreur a été émise par la commande mkdir. Vous n’avez pas reçu d’erreur indiquant que le fichier n’a pas pu être créé car la création du répertoire a échoué. L’opérateur de contrôle && a détecté le code de retour non nul, donc la commande touch a été sautée. L’utilisation de l’opérateur de contrôle && empêche l’exécution de la commande touch parce qu’il y a eu une erreur dans la création du répertoire. Ce type de contrôle du flux des programmes en ligne de commande peut empêcher les erreurs de s’accumuler et de créer un véritable désordre. Mais il est temps de devenir un peu plus compliqué.
L’opérateur de contrôle || vous permet d’ajouter une autre instruction de programme qui s’exécute lorsque l’instruction de programme initiale renvoie un code supérieur à zéro. La syntaxe de base ressemble à ceci:
command1 || command2
Cette syntaxe se lit comme suit : « Si la commande1 échoue, exécutez la commande2. » Cela implique que si la commande1 réussit, la commande2 est ignorée. Essayez ceci en essayant de créer un nouveau répertoire :
C’est exactement ce à quoi vous vous attendez. Comme le nouveau répertoire n’a pas pu être créé, la première commande a échoué, ce qui a entraîné l’exécution de la deuxième commande.
La combinaison de ces deux opérateurs fournit le meilleur des deux. La syntaxe de l’opérateur de contrôle utilisant un certain contrôle de flux prend cette forme générale lorsque les opérateurs de contrôle && et || sont utilisés :
preceding commands ; command1 && command2 || command3 ; following commands
Cette syntaxe peut être énoncée comme suit : « Si la commande1 sort avec un code de retour de 0, alors exécutez la commande2, sinon exécutez la commande3. » Essayez-le:
Maintenant essayez à nouveau la dernière commande en utilisant votre répertoire personnel au lieu du répertoire /root. Vous aurez la permission de créer ce répertoire:
$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
$
La syntaxe de l’opérateur de contrôle, comme commande1 && commande2, fonctionne parce que chaque commande envoie un code de retour (RC) au shell qui indique si elle s’est terminée avec succès ou s’il y a eu un certain type d’échec pendant l’exécution. Par convention, un RC de zéro (0) indique un succès, et tout nombre positif indique un certain type d’échec. Certains des outils utilisés par les sysadmins renvoient juste un (1) pour indiquer un échec, mais beaucoup utilisent d’autres codes pour indiquer le type d’échec qui s’est produit.
La variable shell Bash $ ? contient le RC de la dernière commande. Ce RC peut être vérifié très facilement par un script, la commande suivante dans une liste de commandes, ou même le sysadmin directement. Commencez par exécuter une commande simple et vérifiez immédiatement le RC. Le RC sera toujours celui de la dernière commande exécutée avant que vous ne le regardiez.
Le RC, dans ce cas, est de zéro, ce qui signifie que la commande s’est terminée avec succès. Essayez maintenant la même commande sur le répertoire personnel de root, un répertoire pour lequel vous n’avez pas de permissions :
Dans ce cas, le RC est de deux ; cela signifie que la permission a été refusée à un utilisateur non root pour accéder à un répertoire auquel l’utilisateur n’est pas autorisé à accéder. Les opérateurs de contrôle utilisent ces RC pour vous permettre de modifier la séquence d’exécution du programme.
Résumé
Cet article s’est intéressé à Bash en tant que langage de programmation et a exploré sa syntaxe de base ainsi que certains outils de base. Il a montré comment imprimer des données sur STDOUT et comment utiliser des variables et des opérateurs de contrôle. Le prochain article de cette série s’intéresse à certains des nombreux opérateurs logiques de Bash qui contrôlent le flux d’exécution des instructions.