Développer des scripts shell
Mise à jour :
Le développement de scripts shell, également connu sous le nom de scripting shell, consiste à écrire des programmes ou des scripts dans un langage de script de shell pour automatiser des tâches ou effectuer des opérations sur un système d’exploitation Linux.
Le scripting Shell pour les DevOps
Ceci n’est que l’avis de l’auteur : Il est important pour un consultant DevOps d’apprendre le scripting shell !
Pourquoi ? : Car vous le rencontrerez très souvent. Il est encore couramment utilisé.
Vous serez amené à :
- Porter des script bash dans un langage plus évolué, du python par exemple
- À devoir écrire ou modifier des scripts
- À écrire quelques scripts bash pour résoudre des problèmes ou des petites taches d’administration.
Si j’ai trois conseils à vous donner :
- Apprenez à écrire des scripts simples pour apprendre au minimum à lire et comprendre du code existant
- Apprenez un autre langage, le python par exemple, qui est un langage structuré qui possède une large librairie et une communauté importante. Les résultats seront plus idempotents que ceux d’un script shell.
- Si je devais démarrer un nouveau projet, je ne le ferais pas avec du bash !
Qu’est-ce que le Shell Bash
Le Shell Bash
(Bourne-Again Shell), souvent simplement appelé Bash
, est un
interpréteur de commandes largement utilisé dans les systèmes Linux. Il offre un
moyen puissant d’interagir avec votre système d’exploitation via une interface
en ligne de commande.
Installation du shell Bash
La première étape pour travailler avec le Shell Bash
est de s’assurer qu’il
est installé sur votre système. Dans la plupart des distributions Linux, il est
préinstallé. Pour vérifier si Bash
est déjà installé sur votre système, ouvrez
un terminal et saisissez la commande suivante :
Si vous obtenez une erreur alors, du genre command not found: bash
, il faut
l’installer :
Syntaxe et variables des scripts Bash
Pour bien comprendre le développement de scripts shell Bash, il est essentiel de maîtriser la syntaxe de base du langage et de comprendre comment utiliser les variables.
Syntaxe
Les scripts Bash sont essentiellement des fichiers texte contenant une séquence d’instructions Bash. Voici quelques éléments de base de la syntaxe des scripts Bash :
-
Commentaires : Vous pouvez ajouter des commentaires dans vos scripts en utilisant le caractère
#
. Tout ce qui suit un#
sur une ligne est considéré comme un commentaire et est ignoré lors de l’exécution du script.Exemple de commentaire :
-
Commandes : Les commandes Bash sont exécutées en tant que lignes de texte dans le script. Chaque commande est séparée par un retour à la ligne. Par exemple, pour afficher du texte à l’écran, vous pouvez utiliser la commande
echo
!Exemple de commande :
-
Séparateurs : Le point-virgule (
;
) est utilisé pour séparer plusieurs commandes sur une seule ligne, mais cela n’est pas couramment pratiqué sauf dans des situations spécifiques. -
Structure d’un script : Un script Bash commence généralement par une ligne appelée “shebang” (
#!
) qui indique le chemin de l’interpréteur à utiliser pour exécuter le script. Par exemple, pour utiliserBash
, la première ligne du script est généralement : -
Indentation : Bien que l’indentation ne soit pas aussi importante en
Bash
que dans certains autres langages, il est recommandé d’indenter votre code afin d’en améliorer la lisibilité.
Les variables en Bash
Les variables sont essentielles pour stocker des données dans un script Bash
.
Voici comment déclarer, assigner et utiliser des variables en Bash
.
Les noms de variables sont sensibles à la casse, ce qui signifie que nom
et
Nom
sont des variables différentes. Je vous recommande d’utiliser des noms de
variables en minuscules pour éviter toute confusion avec les variables
d’environnement système, qui sont généralement en majuscules.
Typer les variables, déclarer des constantes
Contrairement à de nombreux autres langages de programmation, le Bash ne type
pas ses variable. Mais Il peut être intéressant de typer une variable. Pour ce
faire, il faut utiliser des commandes internes à bash qui permettent de déclarer
une variable typée. Pour cela on fait appel aux fonctions declare
ou typeset
(ce sont des synonymes)
Les principales options :
-r
: Créé une variable en lecture seule, une constante-i
: Un entier-a
: Un tableau-f
: Une fonction-x
: Ceci déclare la disponibilité d’une variable pour une exportation en dehors de l’environnement du script lui-même.-x var=value
: Assigne une valeur à une variable lors de sa déclaration.
Exemple :
Déclaration de variables
Vous pouvez déclarer une variable en utilisant le signe égal (=
) sans espaces
autour du signe, suivi du nom de la variable.
Exemple de déclaration de variable :
Utilisation de variables
Vous pouvez accéder aux valeurs stockées dans une variable en plaçant le nom de
la variable précédé du caractère $
et utilisant la fonction echo
.
Exemple d’utilisation de variables :
Les variables d’environnement
Les variables d’environnement sont des variables système utilisées par le système d’exploitation et les applications pour stocker des informations importantes sur l’environnement de travail du système. Elles sont utilisées pour influencer le comportement global du système, des programmes et des processus. Les variables d’environnement peuvent contenir divers types d’informations, telles que des chemins de recherche, des paramètres de configuration, des informations de localisation, des informations d’identification, etc.
Les variables d’environnement sont disponibles pour tous les processus et applications en cours d’exécution sur le système. Elles sont généralement utilisées pour partager des informations importantes entre différents programmes.
Vous pouvez définir, modifier et supprimer des variables d’environnement en utilisant des commandes spécifiques dans le Shell. Par exemple, en Shell Bash, vous pouvez utiliser la commande export pour définir une variable d’environnement.
Pour distinguer les variables d’environnements des autres variables, on les mets en majuscule.
Les variables d’environnement courantes
Il existe de nombreuses variables d’environnement couramment utilisées. En voici quelques exemples :
- PATH : Contient une liste de répertoires où le système recherche les exécutables des commandes.
- HOME : Le répertoire personnel de l’utilisateur.
- USER : Le nom de l’utilisateur actuel.
- LANG : La configuration de la langue et de la localisation.
- SHELL : Le chemin du Shell par défaut de l’utilisateur.
- PWD : Le répertoire actuel
Les variables intégrées
En Shell Bash, les “builtin variables” (variables intégrées) font référence à un ensemble de variables spéciales qui sont automatiquement définies par l’interpréteur de commandes Bash. Ces variables sont largement utilisées dans les scripts pour accéder à des informations importantes. Voici quelques-unes des variables intégrées les plus couramment utilisées :
$?
: Contient le code de retour de la dernière commande exécutée. Une valeur de 0 indique que la commande s’est exécutée avec succès, tandis qu’une valeur différente de 0 indique une erreur.$$
: Contient le PID (Process ID) du shell en cours d’exécution. Cette valeur est unique pour chaque instance du shell.$0
,$1
,$2
, … : Ces variables sont utilisées pour accéder aux arguments de ligne de commande passés à un script ou à une commande.$0
représente le nom du script lui-même, tandis que$1,
$2
, etc., représentent les arguments individuels.$#
: Contient le nombre total d’arguments de ligne de commande passés à un script ou à une commande.$@
: Contient tous les arguments de ligne de commande passés à un script ou à une commande sous forme de liste.$*
: Contient tous les arguments de ligne de commande passés à un script ou à une commande sous forme d’une seule chaîne de caractères.
Lire l’entrée de l’utilisateur
Pour demander à utilisateur de saisir une variable, on utilise la commande
read
:
Les Opérations de contrôle
Pour créer des scripts Bash puissants et flexibles, vous devez comprendre
comment utiliser les opérations de contrôle. Cela inclut les structures
conditionnelles telles que if
, else
, elif
et les boucles comme for
et
while
.
Structures conditionnelles
Les structures conditionnelles vous permettent d’exécuter des blocs de code en fonction de conditions spécifiques. Voici comment elles fonctionnent en Bash :
Structure if
… then
… else
… fi
La structure if
permet d’exécuter un bloc de code si une condition est vraie
(true). Voici un exemple :
Dans cet exemple, le script vérifie si la variable age
est inférieure à 18. Si
c’est le cas, il affiche “Vous êtes mineur.” Sinon, il affiche “Vous êtes
majeur.”
L’utilisation de elif
permet de gérer plusieurs conditions de manière
séquentielle. Voici un exemple :
Ce script attribue une note en fonction de la valeur de la variable note
. Il
utilise elif
pour gérer plusieurs conditions en séquence.
Les boucles
Les boucles permettent de répéter des blocs de code plusieurs fois. Voici deux types de boucles couramment utilisés en Bash :
Boucle for
La boucle for
est utilisée pour itérer sur une liste de valeurs ou d’éléments.
Par exemple, voici comment vous pouvez utiliser une boucle for
pour parcourir
une liste de fichiers :
Ce script liste tous les fichiers du répertoire courant en utilisant la commande
ls
et les affiche un par un.
Boucle while
La boucle while
permet d’exécuter un bloc de code tant qu’une condition
spécifiée est vraie. Voici un exemple :
Ce script affiche les valeurs de compteur
de 1 à 5 en utilisant une boucle
while
.
Les tests
En Shell Bash, vous pouvez utiliser des tests conditionnels avec la commande
if
pour vérifier diverses conditions, y compris des tests sur les fichiers et
des tests sur les entiers, sur les chaines de caractères…
Pour effectuer ces test on utilise les opérateurs de test.
Opérateurs de comparaison pour les entiers
Les tests sur les entiers vous permettent de comparer des valeurs numériques. Voici quelques exemples :
Vérifier si un nombre est égal à un autre nombre
On utilise dans ce cas l’opérateur de test -eq
:
Vérifier si un nombre est inférieur à un autre nombre
On utilise dans ce cas l’opérateur de test -lt
:
Vérifier si un nombre est supérieur à un autre nombre
On utilise dans ce cas l’opérateur de test -gt
:
Vérifier si un nombre est non nul
Opérateurs de comparaison pour les chaînes de caractères
Ces tests vous permettent de vérifier des conditions liées aux chaînes de caractères, comme leur égalité, leur longueur, leur présence dans une autre chaîne, etc
Vérifier si deux chaînes de caractères sont égales
On utilise dans ce cas l’opérateur de test =
:
Vous pouvez également utiliser ==
pour la comparaison de chaînes, bien que =
soit plus couramment utilisé.
Vérifier si deux chaînes de caractères sont différentes
On remplace l’opérateur ==
par !=
:
Vérifier si une chaîne de caractères est vide
On utilise dans ce cas l’opérateur de test -z
:
Vérifier si une chaîne de caractères n’est pas vide
On utilise dans ce cas l’opérateur de test -n
:
Vérifier si une chaîne de caractères contient une sous-chaîne
On utilise dans ce cas l’opérateur de test ==
accompagné d’astérisques :
Dans cet exemple, *
est utilisé pour faire correspondre n’importe quel nombre
de caractères avant et après “tout”.
Vérifier si une chaîne de caractères commence ou se termine par une certaine sous-chaîne
Il suffit de reprendre le test précédent en enlevant l’astérisque au début ou à la fin de la chaine de comparaison.
Vérifier la longueur d’une chaîne de caractères
${#chaine}
renvoie la longueur de la chaîne de caractères.
Les Opérateurs de tests sur les fichiers
Les tests sur les fichiers vous permettent de vérifier si un fichier existe, s’il est vide, s’il s’agit d’un répertoire, etc.
Vérifier si un fichier existe
On utilise dans ce cas l’opérateur de test -e
:
Vérifier si un fichier est un répertoire
On utilise dans ce cas l’opérateur de test -d
:
Vérifier si un fichier est vide
On utilise dans ce cas l’opérateur de test -s
:
Vérifier si un fichier est exécutable
On utilise dans ce cas l’opérateur de test -x
:
Les Opérateurs de test logique
Ces opérateurs de test logique sont utilisés pour comibner plusieurs conditions.
-a : ET logique (e.g., [ condition1 -a condition2 ]) -o : OU logique (e.g., [ condition1 -o condition2 ]) ! : NON logique (e.g., !condition)
Utilisation des fonctions
En Shell Bash, les fonctions sont des blocs de code réutilisables qui effectuent une série d’instructions ou de commandes. Elles permettent de structurer et d’organiser un script Bash en regroupant des tâches spécifiques en fonctionnalités modulaires. Les fonctions en Bash peuvent recevoir des arguments, exécuter des opérations et renvoyer des valeurs. Voici comment créer et utiliser des fonctions en Shell Bash :
Voici un exemple simple de fonction Bash qui affiche un message :
Appel de fonctions
Pour appeler une fonction, utilisez simplement son nom suivi de parenthèses :
Lorsque vous appelez la fonction, le code à l’intérieur des accolades est exécuté.
Passage d’arguments
Vous pouvez passer des arguments à une fonction en les spécifiant entre les
parenthèses lors de son appel. Les arguments sont accessibles à l’intérieur de
la fonction via les variables spéciales $1
, $2
, etc., où $1
représente le
premier argument, $2
le deuxième et ainsi de suite.
Dans cet exemple, “Hello” est passé en tant que premier argument à la fonction
afficher_argument
.
Retour de valeurs
Pour renvoyer une valeur depuis une fonction, utilisez la commande return
. Par
exemple :
Dans cet exemple, la fonction additionner
prend deux arguments, effectue
l’addition et renvoie le résultat à l’aide de return
. Le résultat est ensuite
stocké dans la variable $resultat
à l’extérieur de la fonction.
Contrairement aux langages de programmation, les scripts bash ne permet de retourner qu’une seule valeur. Pour contourner ce manque, il est possible :
- d’utiliser les paramètres de fonctions.
- d’utiliser des varaibles globales.
- de retourner une liste.
Variables locales
Notez que les variables déclarées à l’intérieur d’une fonction sont locales par
défaut, ce qui signifie qu’elles ne sont accessibles qu’à l’intérieur de la
fonction. Utilisez local
pour déclarer des variables locales explicitement.
Utilisation d’arguments dans les Scripts Shell
Le passage d’arguments en Shell Bash fait référence à la capacité de passer des valeurs ou des données à un script ou à une fonction Bash lors de son exécution. Les arguments permettent de fournir des données dynamiques aux scripts ou aux fonctions, ce qui les rend plus flexibles et adaptables. Vous pouvez accéder à ces arguments à l’intérieur du script ou de la fonction et les utiliser pour effectuer des opérations spécifiques.
Les arguments passés à un script ou à une fonction Bash sont généralement représentés par des variables spéciales. Voici comment ils fonctionnent :
-
$0
: Il s’agit de la variable spéciale qui contient le nom du script lui-même ou le nom de la fonction s’il s’agit d’une fonction appelée depuis un script. -
$1
,$2
,$3
, …$n
: Ces variables spéciales contiennent les valeurs des arguments passés au script ou à la fonction.$1
correspond au premier argument,$2
au deuxième,$3
au troisième et ainsi de suite.
Voici un exemple simple pour illustrer le passage d’arguments dans un script Bash :
Si vous exécutez ce script avec la commande ./mon_script.sh argument1 argument2
, vous obtiendrez la sortie suivante :
Comme vous pouvez le voir, les arguments passés lors de l’exécution du script
sont accessibles en utilisant les variables spéciales $1
, $2
, etc.
Shift
La commande shift
en Shell Bash est utilisée pour décaler les arguments passés
à un script ou à une fonction. Elle permet de réorganiser les variables
spéciales $1
, $2
, $3
, etc., de manière à accéder aux arguments suivants.
Voici quelques exemples pour illustrer son utilisation :
- Décalage d’un argument :
Si vous exécutez ce script avec la commande ./mon_script.sh argument1 argument2
, vous obtiendrez la sortie suivante :
Comme vous pouvez le voir, la commande shift
a décalé les arguments, faisant
de l’ancien $2
le nouveau $1
.
- Utilisation d’une boucle pour parcourir tous les arguments
Ce script utilise une boucle while
pour parcourir tous les arguments passés au
script. La condition [ $# -gt 0 ]
vérifie si le nombre d’arguments restants
($#
) est supérieur à zéro. À chaque itération de la boucle, la commande
shift
décale les arguments, ce qui permet de traiter un argument à la fois.
Exit et les codes de sortie
Les codes de retour, également appelés codes de sortie, sont des valeurs numériques renvoyées par un programme ou un script lorsqu’il se termine. Ces codes sont utilisés pour indiquer le résultat de l’exécution du programme. En Shell Bash, vous pouvez définir des codes de sortie en utilisant la commande exit suivi du code numérique :
Quels codes de sorties utiliser ?
Il est courant d’utiliser 0
pour indiquer un succès (aucune erreur) et des
valeurs non nulles pour indiquer des erreurs ou des problèmes spécifiques.
Cependant, vous pouvez définir des codes de sortie personnalisés en fonction de
vos besoins. Les valeurs de code de sortie ne sont pas limitées à 0
et 1
:
vous pouvez utiliser n’importe quelle valeur numérique de 0
à 255
.
Accès au code de sortie
Une fois que votre script se termine avec un code de sortie, vous pouvez accéder
à ce code de sortie en utilisant la variable spéciale $?
.
Débogage de scripts shell
Le débogage d’un script Shell est essentiel pour identifier et corriger les erreurs, les bogues et les comportements inattendus dans votre code. Voici quelques techniques et outils que vous pouvez utiliser pour déboguer efficacement un script Bash :
Utilisation de l’option -x
L’une des méthodes les plus simples pour déboguer un script Bash consiste à
exécuter le script avec l’option -x
. Cela active le mode de débogage et
affiche chaque commande exécutée avec sa sortie sur la console.
Ajout de messages de débogage
Vous pouvez insérer des messages de débogage dans votre script en utilisant la
commande echo
. Ajoutez des messages à des points clés de votre code pour
afficher des informations sur les variables, les valeurs intermédiaires, les
conditions, etc. Par exemple :
Ces messages vous aident à comprendre ce qui se passe à chaque étape de l’exécution.
Utilisation de la commande set -e
Vous pouvez utiliser set -e
au début de votre script pour arrêter l’exécution
dès qu’une commande renvoie un code de retour différent de zéro (erreur). Cela
permet de détecter rapidement les erreurs et d’arrêter l’exécution du script en
cas de problème.
Utilisation de set -u
L’option set -u
provoque une erreur si une variable non définie est utilisée
dans votre script. Cela peut vous aider à éviter les erreurs causées par des
variables non initialisées.
Utilisation d’un débogueur Bash
Vous pouvez utiliser des débogueurs spécifiquement conçus pour Bash, tels que
bashdb
ou dbash
. Ces outils vous permettent d’exécuter votre script pas à
pas, de mettre en pause l’exécution à des points d’arrêt, de vérifier les
valeurs des variables, etc.
Améliorer votre syntaxe avec shellcheck
ShellCheck est un outil d’analyse statique de scripts Shell qui vous aide à repérer les erreurs de syntaxe, les problèmes de style et les vulnérabilités potentielles dans vos scripts Bash.
Installation de shellcheck
shellcheck
est disponible sur la plupart des distributions linux via le
gestionnaire de packages. Par exemple sur une Ubuntu :
Utilisation de shellcheck
Le fonctionnement est assez simple puisqu’il suffit de taper son nom suivi du nom du script à analyser :
ShellCheck parcourra votre script et signalera tout problème qu’il trouve, en indiquant la ligne et la colonne exactes du code problématique, ainsi qu’une description du problème.
Par exemple, si vous avez un script avec une erreur de syntaxe, ShellCheck pourrait afficher quelque chose comme :
Cela vous indique que sur la ligne 3, colonne 3, il y a une erreur de syntaxe
liée à la structure fi
.
Comprendre les messages d’erreur
Chaque message d’erreur généré par ShellCheck
est accompagné d’un code
d’erreur [SCxxxx] qui vous permet de rechercher des informations détaillées sur
le problème spécifique sur le site de ShellCheck ↗.
Conseil
Utilisez l’outil shellcheck
dès le démarrage de votre projet de script.
L’utiliser à la fin ou sur un script existant peut tourner au cauchemar !
Utiliser l’outil de formatage shfmt
shfmt
est un outil de formatage de fichiers Shell, dont le langage Bash.
shfmt
permet de reformater automatiquement le code source pour suivre une
convention de style particulière. Il aide à maintenir la cohérence du code, à
améliorer la lisibilité et à suivre des règles de formatage spécifiques.
Installation de shfmt
shfmt
est disponible sur la plupart des distributions linux via le
gestionnaire de packages. Par exemple sur une Ubuntu :
Utilisation de shfmt
Comme pour shellcheck
, il suffit de lancer la commande shfmt
suivi du nom de
votre fichier de scripts :
Bonnes pratiques pour vos scripts Bash
Pour rendre vos scripts Shell plus fiables, sûrs et faciles à maintenir, voici une série de bonnes pratiques indispensables, tirées des meilleurs conseils :
- Validez les entrées utilisateur : Toujours vérifier et nettoyer les données d’entrée pour éviter les injections de commande et les erreurs.
- Citez vos variables : Protégez vos variables avec des guillemets pour éviter des erreurs liées à la séparation des mots ou à l’expansion des globbing.
- Gérez les erreurs : Utilisez
set -euo pipefail
pour arrêter le script à la moindre erreur et ajoutez des vérifications des retours de commandes. - Utilisez des chemins absolus : Garantissez que les bonnes commandes sont
utilisées et non celles manipulées par une variable
PATH
. - Protégez les fichiers temporaires : Créez des fichiers temporaires de
manière sécurisée avec
mktemp
et nettoyez-les après utilisation.
Ces bonnes pratiques vous protégeront des erreurs courantes et des failles de sécurité. Pour une version complète et détaillée des pratiques sécurisées en Bash, consultez mon guide sur les scripts shell sécurisés.
Plus d’infos
Livres gratuits
- Programmation Bash ↗
- Guide avancé d’écriture des scripts Bash ↗
- Apprenez BASH ↗
- Introduction à la programmation en Bash ↗
Livres
MOOC
Sites
Vidéos
- xavki ↗ vidéos