Aucun langage de programmation n'est parfait. Il n'existe même pas un langage meilleur que d'autre ; il n'y a que des langages en adéquation ou peu conseillés pour des buts particuliers.
-- Herbert Mayer
Une connaissance fonctionnelle de la programmation shell est essentielle à quiconque souhaite devenir efficace en administration de système, même pour ceux qui ne pensent pas avoir à écrire un script un jour. Pensez qu'au démarrage de la machine Linux, des scripts shell du répertoire /etc/rc.d sont exécutés pour restaurer la configuration du système et permettre la mise en fonctionnement des services. Une compréhension détaillée de ces scripts de démarrage est importante pour analyser le comportement d'un système, et éventuellement le modifier.
Écrire des scripts shell n'est pas difficile à apprendre car, d'une part, les scripts peuvent être construits par petites sections et, d'autre part, il n'y a qu'un assez petit nombre d'opérateurs et d'options [1] spécifiques au shell à connaître. La syntaxe est simple et directe, similaire à une suite d'appels de différents utilitaires en ligne de commande et il n'existe que peu de « règles » à apprendre. La plupart des petits scripts fonctionnent du premier coup et le débogage, même des plus longs, est assez simple.
Un script shell est une méthode « rapide et sale » pour prototyper une application complexe. Avoir même un sous-ensemble limité de fonctionnalités dans un script shell est souvent une première étape utile lors d'un projet de développement. De cette façon, la structure de l'application peut être testée et les problèmes majeurs trouvés avant d'effectuer le codage final en C, C++, Java ou Perl.
La programmation shell ramène à la philosophie classique des UNIX, c'est à dire, casser des projets complexes en sous-tâches plus simples et assembler des composants et des utilitaires. Beaucoup considèrent que cette approche de la résolution de problème est meilleure ou, du moins, plus abordable que l'utilisation de langages de nouvelle génération puissamment intégré comme Perl, qui essaient de tout faire pour tout le monde mais au prix de vous forcer à changer votre processus de réflexion pour vous adapter à l'outil.
D'après Herbert Mayer, « un langage utile doit comprendre des tableaux, des pointeurs et un mécanisme générique pour construire des structures de données. » Suivant ces critères, les langages des scripts shell ne sont pas « utiles ». Peut-être que si.
Quand ne pas utiliser les scripts shell
pour des tâches demandant beaucoup de ressources et particulièrement lorsque la rapidité est un facteur (tri, hachage, récursion [2] ...) ;
pour des procédures impliquant des opérations mathématiques nombreuses et complexes, spécialement pour de l'arithmétique à virgule flottante, des calculs à précision arbitraire ou des nombres complexes (optez plutôt pour le C++ ou le FORTRAN dans ce cas) ;
pour une portabilité inter-plateformes (utilisez le C ou Java à la place) ;
pour des applications complexes où une programmation structurée est nécessaire (typage de variables, prototypage de fonctions, etc.) ;
pour des applications critiques sur lesquelles vous misez votre avenir ou celui de la société ;
pour des situations où la sécurité est importante, où vous avez besoin de garantir l'intégrité de votre système et de vous protéger contre les intrusions et le vandalisme ;
pour des projets consistant en de nombreux composants avec des dépendances inter-verrouillées ;
lorsque des opérations importantes sur des fichiers sont requises (Bash est limité à un accès fichier en série, ligne par ligne, ce qui est particulièrement maladroit et inefficace) ;
si le support natif des tableaux multidimensionnels est nécessaire ;
si vous avez besoin de structures de données, telles que des listes chaînées ou des arbres ;
si vous avez besoin de générer ou de manipuler des graphiques ou une interface utilisateur (GUI) ;
lorsqu'un accès direct au matériel est nécessaire ;
lorsque vous avez besoin d'accéder à un port, à un socket d'entrée/sortie ;
si vous avez besoin d'utiliser des bibliothèques ou une interface propriétaire ;
pour des applications propriétaires, à sources fermées (les sources des shells sont forcément visibles par tout le monde).
Dans l'un des cas ci-dessus, considérez l'utilisation d'un langage de scripts plus puissant, peut-être Perl, Tcl, Python, Ruby, voire un langage compilé de haut niveau tel que C, C++ ou Java. Même dans ce cas, prototyper l'application avec un script shell peut toujours être une étape utile au développement.
Nous utiliserons Bash, un acronyme pour « Bourne-Again shell » et un calembour sur le désormais classique Bourne shell de Stephen Bourne. Bash est devenu un standard de facto pour la programmation de scripts sur tous les types d'UNIX. La plupart des principes discutés dans ce livre s'appliquent également à l'écriture de scripts avec d'autres shells tels que le Korn Shell, duquel dérivent certaines des fonctionnalités de Bash, [3] , le shell C et ses variantes (notez que la programmation en shell C n'est pas recommandée à cause de certains problèmes inhérents, comme indiqué en octobre 1993 sur un message Usenet par Tom Christiansen).
Ce qui suit est un tutoriel sur l'écriture de scripts shell. Il est en grande partie composé d'exemples illustrant différentes fonctionnalités du shell. Les scripts en exemple ont été testés, autant que possible, et certains d'entre eux peuvent même être utiles dans la vraie vie. Le lecteur peut jouer avec le code des exemples dans l'archive des sources (nom_script.sh ou nom_script.bash), [4] leur donner le droit d'exécution (chmod u+rx nom_du_script) et les exécuter pour voir ce qu'il se passe. Si les sources de l'archive ne sont pas disponibles, alors copier/coller à partir de la version HTML ou pdf (la version originale dispose d'une version texte, disponible à cette adresse) contrairement à la traduction française). Sachez que certains scripts présentés ici introduisent des fonctionnalités avant qu'elle ne soient expliquées et que ceci pourrait réclamer du lecteur de lire temporairement plus avant pour des éclaircissements.
Sauf mention contraire, l'auteur de ce livre a écrit les scripts d'exemples qui suivent.
[1] Ils sont connus sous le nom de commandes intégrées, c'est-à-dire des fonctionnalités internes au shell.
[2] Bien que la récursion est possible dans un script shell, elle tend à être lente et son implémentation est souvent le résultat d'un code sale.
[3] Beaucoup de fonctionnalités de ksh88, et même quelques unes de la version mise à jour ksh93, ont été intégrées à Bash.
[4] Par convention, les scripts shell écrits par l'utilisateur, compatibles avec le shell Bourne, sont nommés avec l'extension .sh. Les scripts système, tels que ceux trouvés dans /etc/rc.d, ne suivent pas cette nomenclature.