Les bases des scripts shell
DébutantUnité 4 sur 7 de la formation Formation : Linux : ligne de commande, scripts shell et administration
Ce que tu vas apprendre
- Transforme une suite de commandes que tu saisis sans cesse en fichier de script, commence-le par la ligne d’interpréteur adaptée et exécute-le depuis n’importe quel répertoire.
- Regroupe des commandes répétées dans un fichier de scriptÉcris des commandes dans l’ordre dans un fichier texte, ajoute des commentaires et commence le fichier par une ligne shebang qui désigne Bash comme interpréteur.
- Exécute un script et choisis son emplacementRends un script exécutable, lance-le par son chemin ou par un interpréteur, place-le dans un répertoire du PATH et sache quand un script peut modifier ton shell courant.
- Regroupe des commandes répétées dans un fichier de script
- Stocke du texte, des nombres et des sorties de commandes dans des variables, lis les saisies de l’utilisateur et protège les caractères pour que les espaces et les caractères spéciaux parviennent aux commandes sans modification.
- Crée, lis et exporte des variablesAffecte et utilise des variables du shell, choisis de bons noms, lis les saisies de l’utilisateur et transmets des variables aux programmes lancés par un script.
- Protège les mots, les variables et les caractères spéciauxChoisis entre guillemets simples, guillemets doubles et barres obliques inverses, et protège chaque développement de variable pour que les espaces et les caractères génériques des valeurs ne perturbent pas une commande.
- Récupère la sortie d’une commande et effectue des calculs sur des entiersStocke la sortie d’une commande avec la substitution de commande et effectue des calculs sur des entiers, par exemple pour créer des noms de fichiers datés et gérer des compteurs.
- Crée, lis et exporte des variables
- Lis et définis le code de retour des commandes et des scripts, enchaîne des commandes selon leur réussite ou leur échec, puis repère et arrête les erreurs avant qu’elles ne causent des dommages.
- Lis et définis les codes de retour, puis utilise-les pour enchaîner les commandesUtilise le code de retour renvoyé par chaque commande, termine un script avec un code qui a un sens et exécute des commandes uniquement lorsqu’une commande précédente a réussi ou échoué.
- Repère les erreurs et arrête un script en toute sécuritéVérifie et trace l’exécution d’un script pour trouver les erreurs, envoie les messages d’erreur sur la sortie d’erreur standard et fais arrêter le script en cas d’échec, de variable non définie ou d’échec d’un pipeline.
- Lis et définis les codes de retour, puis utilise-les pour enchaîner les commandes
- Teste des fichiers, du texte et des nombres, choisis les actions avec if et case, et répète des commandes sur des listes, des fichiers et des lignes avec les boucles for, while et until.
- Teste des fichiers, des chaînes et des nombresÉcris des conditions avec test, [ ] et [[ ]] pour vérifier l’existence de fichiers, comparer du texte et des nombres entiers, puis combine-les ou inverse-les.
- Choisis les actions avec if, elif, else et caseExécute différentes commandes selon une condition avec if, elif et else, et compare une valeur à plusieurs motifs avec case.
- Répète des commandes sur des listes et des fichiers avec forParcours une liste de mots, les fichiers correspondant à un motif, une suite de nombres ou les arguments d’un script, et traite les noms de fichiers contenant des espaces.
- Répète des commandes jusqu’au changement d’une condition avec while et untilExécute des commandes tant qu’une condition réussit ou jusqu’à ce qu’elle réussisse, lis un fichier ligne par ligne et contrôle les boucles avec break, continue et sleep.
- Teste des fichiers, des chaînes et des nombres
- Fournis ses données d’entrée à un script sur la ligne de commande, lis les arguments dans le script, vérifie-les et prévois des valeurs par défaut pour qu’un même script fonctionne dans de nombreux cas.
- Lis les paramètres positionnels et le nombre d’argumentsUtilise
$0,$1à$9,${10},$#et"$@"pour lire les mots donnés après le nom d’un script, et utiliseshiftpour les parcourir. - Vérifie les arguments, affiche le mode d’utilisation et définis les valeurs par défautValide le nombre et le type des arguments, affiche un message d’utilisation et quitte avec un code d’erreur, utilise des valeurs par défaut et traite des options simples.
- Lis les paramètres positionnels et le nombre d’arguments
- Exécute des scripts à des heures fixes ou à intervalles réguliers sans être connecté, avec cron ou les minuteries systemd, et vérifie que les exécutions planifiées ont lieu et réussissent.
- Planifie des tâches avec cronÉcris des entrées crontab avec les cinq champs temporels, modifie-les et liste-les avec crontab, et prépare les scripts pour l’environnement minimal de cron.
- Planifie des tâches avec les minuteries systemdAssocie une unité de service à une unité de minuterie, définis des horaires calendaires et des intervalles, active la minuterie et vérifie la prochaine exécution et les journaux.
- Planifie des tâches avec cron
Scripts shell : cours
1Écris et exécute tes premiers scripts Bash
Quelques commandes sont plus faciles à répéter lorsqu’elles figurent dans un même script. Tu vas attribuer un interpréteur Bash au fichier, garder ses instructions lisibles et choisir comment le lancer. Les droits sur les fichiers, les chemins de recherche des commandes et les shells fils expliquent plusieurs surprises courantes : pourquoi un script fonctionne avec bash mais échoue avec ./, pourquoi son nom est introuvable et pourquoi ses changements de répertoire ne déplacent pas ton terminal.
1.1 Regroupe des commandes répétées dans un fichier de script
Un script shell enregistre une suite de commandes dans un fichier texte. Bash lit les commandes dans l’ordre, comme celles que tu saisis à une invite de commande. Un script peut répéter une tâche sans que quelqu’un saisisse chaque étape et te donne un seul endroit où corriger ou améliorer cette tâche.
Place l’interpréteur sur la première ligne
Le shebang indique à Linux quel programme doit lire un script exécutable. Commence un script Bash par #!/bin/bash. Les caractères #! doivent être les deux premiers du fichier : aucune espace ni ligne vide ne doit les précéder. Bash signifie Bourne Again Shell. Il est largement utilisé comme shell interactif sous Linux et lit aussi les fichiers de script.
Un interpréteur est un programme qui lit et exécute un autre langage. Le même mécanisme permet à #!/usr/bin/python3 de sélectionner Python ou à #!/usr/bin/awk -f de sélectionner awk. Le reste d’un script Bash doit contenir des commandes shell que Bash comprend.
Crée backup-notes.sh dans un éditeur de texte brut comme nano ou vi :
#!/bin/bash
# Keep a copy of the notes and show the backup folder.
mkdir -p ~/backup
cp ~/notes.txt ~/backup/
ls -l ~/backup
Bash crée d’abord le répertoire de destination, puis copie les notes et liste enfin le contenu de la destination. mkdir -p réussit aussi lorsque le répertoire existe déjà, donc une exécution ultérieure peut le réutiliser. Le fichier source ~/notes.txt doit exister pour que la copie fonctionne. L’enregistrement des commandes ne crée pas ce fichier source.
Rends le fichier lisible pour les personnes
La deuxième ligne est un commentaire. Hors du texte protégé par des guillemets, # commence un commentaire lorsqu’il se trouve au début d’un mot ; Bash ignore le reste de cette ligne. Écris des commentaires sur le but d’une étape, par exemple pourquoi une sauvegarde doit être conservée. Les lignes vides et l’indentation rendent les groupes de commandes plus faciles à distinguer. Garde une indentation cohérente lorsque tu ajoutes des conditions et des boucles.
La terminaison .sh aide le lecteur à reconnaître un script shell. Linux ne l’exige pas, et l’ajouter ne sélectionne pas Bash ni n’accorde le droit d’exécution. Un fichier nommé backup-notes peut exécuter les mêmes commandes.
Adapte le shell au langage
| Première ligne | Comment l’interpréteur est choisi |
|---|---|
#!/bin/bash | Utilise Bash au chemin fixe /bin/bash. |
#!/usr/bin/env bash | Utilise env pour trouver Bash à l’aide de PATH. |
#!/bin/sh | Utilise le sh du système, qui peut être un autre shell. |
Sur Debian et Ubuntu, /bin/sh sélectionne normalement dash. Les fonctionnalités de Bash comme [[ ... ]] y échouent. Un script Bash a besoin d’un interpréteur Bash, même si des commandes simples fonctionnent par hasard dans les deux shells. Nommer un fichier something.sh ne corrige pas un shebang inadapté.
Reconnais un problème de fin de ligne
Les éditeurs Windows peuvent enregistrer un retour chariot avant chaque saut de ligne. Sous Linux, ce caractère invisible peut faire partie du chemin du shebang. Une erreur comme /bin/bash^M: bad interpreter: No such file or directory indique ce problème, même si /bin/bash existe.
Convertis le fichier aux fins de ligne Unix avec dos2unix backup-notes.sh, puis enregistre les futurs scripts avec des fins de ligne Unix dans l’éditeur. Les commandes du fichier peuvent être correctes alors que le caractère supplémentaire empêche Linux de lancer leur interpréteur.
Points clés
- Un script est un fichier texte contenant des commandes à exécuter dans l’ordre.
- Le shebang doit commencer au tout début du fichier et désigner le bon interpréteur.
- Utilise des commentaires et l’indentation pour rendre le but et la structure clairs.
- L’extension
.shest une convention ; elle ne sélectionne pas de shell. - Les fins de ligne Unix empêchent un retour chariot caché de perturber le shebang.
1.2 Exécute un script et choisis son emplacement
Un script peut être lu directement par Bash ou lancé comme un programme. Ces méthodes diffèrent par les droits nécessaires et la façon dont l’interpréteur est choisi. Le chemin que tu saisis détermine aussi si le shell recherche une commande ou utilise un fichier précis.
Deux façons de lancer le même fichier
bash backup-notes.sh
chmod u+x backup-notes.sh
./backup-notes.sh
La première commande lance Bash et lui demande de lire le fichier. Le script doit avoir le droit de lecture ; son propre bit d’exécution n’est pas nécessaire. Bash traite le shebang comme un commentaire puisque l’interpréteur a déjà été choisi.
La deuxième commande ajoute le droit d’exécution pour le propriétaire du fichier. Dans une chaîne de droits comme -rwxr--r--, le x du propriétaire signifie que le fichier est exécutable. La troisième commande exécute le fichier comme un programme et utilise son shebang. chmod +x est aussi courant ; sans catégorie de droits précisée, l’umask limite les catégories qui obtiennent le droit d’exécution. chmod u+x cible explicitement le propriétaire.
Si ./backup-notes.sh renvoie « Permission denied », vérifie le droit d’exécution et l’accès au chemin. Si bash backup-notes.sh fonctionne, cela ne prouve pas que l’exécution directe dispose des droits nécessaires.
Comprends la recherche des commandes
./ désigne le répertoire courant. Lorsqu’une commande contient une barre oblique, Bash suit ce chemin. Lorsque tu saisis un nom sans barre oblique, Bash recherche dans les répertoires de PATH. Le répertoire courant est normalement absent de cette liste, donc se trouver dans le répertoire d’un script ne suffit pas pour l’exécuter avec son seul nom.
echo "$PATH"
command -v backup-notes.sh
type backup-notes.sh
PATH est une liste dont les éléments sont séparés par des deux-points, comme /home/sam/.local/bin:/usr/local/bin:/usr/bin:/bin. Le premier exécutable correspondant est retenu. Les deux dernières commandes aident à identifier ce qu’un nom lancera, y compris une ancienne copie située ailleurs dans le PATH.
Pour rendre un script personnel accessible par son nom, place-le dans un répertoire de ton PATH. De nombreuses distributions ajoutent ~/bin ou ~/.local/bin à la connexion lorsque ce répertoire existe ; vérifie ton PATH effectif. /usr/local/bin est un emplacement courant pour les scripts partagés entre utilisateurs et nécessite des droits d’administration pour y écrire.
Choisis entre un shell fils et le shell courant
Exécuter ./settings.sh ou bash settings.sh lance un processus Bash fils. Ses variables et ses changements de répertoire appartiennent à ce processus fils. Un script contenant cd /var/log ne déplace pas le terminal qui l’a lancé. Lorsqu’il se termine, tu te trouves toujours dans le répertoire d’origine du terminal.
L’exécution dans le shell courant (sourcing) y lit les commandes :
source ./settings.sh
# Equivalent short form:
. ./settings.sh
Utilise cette méthode pour un fichier de paramètres destiné à modifier ta session. Elle nécessite le droit de lecture, pas le droit d’exécution, et un shebang ne lance pas d’interpréteur distinct. Exécuter ainsi un fichier de paramètres Bash suppose donc que le shell courant comprenne la syntaxe Bash.
Lis le résultat d’une exécution
Immédiatement après la fin d’un script, echo $? affiche son code de retour. À moins que le script n’utilise exit avec un code choisi, son code provient de sa dernière commande. Un affichage final réussi peut donc masquer l’échec d’une copie précédente ; les vérifications d’erreurs présentées plus loin permettront au script d’indiquer le résultat réel de la tâche.
Points clés
bash filelit un script avec Bash ;./filenécessite le droit d’exécution et utilise le shebang.- Le PATH n’est consulté que pour les noms de commandes sans barre oblique.
- Vérifie un nom de commande avec
command -voutype. - L’exécution lance un shell fils ; l’exécution dans le shell courant peut modifier ce dernier.
2Stocke des valeurs dans des variables et protège-les correctement
Les variables permettent aux mêmes commandes de fonctionner avec des chemins, des noms et des nombres qui changent. La protection des caractères garde ces valeurs intactes pendant que Bash construit une ligne de commande, pour qu’une espace dans un nom reste une partie de ce nom. Tu vas lire des saisies, transmettre des valeurs à des programmes fils, récupérer la sortie de commandes et calculer avec des entiers. Ces éléments fonctionnent ensemble lorsqu’un script construit un nom de fichier daté ou tient un compte à jour.
2.1 Crée, lis et exporte des variables
Une variable donne un nom à une valeur pour que le même script puisse la réutiliser. Les variables Bash contiennent normalement du texte, même lorsque ce texte ressemble à un nombre. Tu affectes la valeur une fois et développes le nom partout où une commande a besoin de cette valeur.
Affecte sans espaces
city=Lisbon
greeting="Good morning"
echo "$greeting from $city"
La sortie est « Good morning from Lisbon ». Il n’y a pas d’espaces autour du = d’affectation. Dans city = Lisbon, Bash traite city comme une commande et les autres mots comme des arguments. Les guillemets autour de "Good morning" maintiennent les deux mots dans une seule valeur.
Utilise des lettres, des chiffres et des caractères de soulignement dans les noms de variables, avec une lettre ou un caractère de soulignement en premier. Les noms sont sensibles à la casse : file, File et FILE sont différents. Choisis des noms en minuscules comme backup_dir pour les valeurs propres à ton script. Cela aide à éviter de remplacer des variables d’environnement comme PATH ou HOME. Définir PATH=/data modifie la résolution des commandes et peut empêcher de trouver des commandes ordinaires.
Marque la fin d’un nom
Un signe dollar introduit un développement. Les accolades indiquent la limite lorsque du texte suit immédiatement :
file=report
echo "${file}_old"
Cela affiche « report_old ». Avec "$file_old", Bash recherche une variable nommée file_old, et non file suivi de _old. Sans set -u, un nom non défini se développe en texte vide. Une faute de frappe peut donc produire un chemin ou un message vide sans erreur immédiate.
Une valeur comme count=5 stocke le texte « 5 ». Ajouter du texte à côté d’un développement n’effectue pas de calcul : echo "$count+1" affiche « 5+1 ». Le développement arithmétique donne un rôle différent aux nombres lorsque des calculs sont nécessaires.
Lis une ligne de saisie
read -r -p "Your name: " name
echo "Hello, $name"
read stocke la ligne saisie dans name. -p fournit l’invite et -r préserve les barres obliques inverses. Avec la saisie « Lee Kim », le message de bienvenue est « Hello, Lee Kim ». Un script exécuté sans personne présente doit recevoir ses données d’entrée par des arguments, des fichiers ou des valeurs par défaut ; une invite ne peut pas fournir une valeur manquante de façon fiable.
Exporte des valeurs pour les programmes fils
Une variable ordinaire du shell appartient au shell dans lequel elle est définie. L’exportation la marque pour qu’elle soit incluse dans l’environnement copié vers les programmes lancés par ce shell :
export BACKUP_DIR=/mnt/usb
bash backup-notes.sh
Le Bash fils peut maintenant lire BACKUP_DIR. Si ce processus fils lui affecte une autre valeur, le parent conserve la sienne. L’environnement est transmis du parent au fils ; les modifications ultérieures ne remontent pas vers le parent.
| Nom | Signification habituelle |
|---|---|
HOME | Répertoire personnel |
USER | Nom d’utilisateur |
PWD | Répertoire de travail courant |
PATH | Répertoires où rechercher les noms de commandes |
env ou printenv affiche les variables d’environnement. unset name supprime la variable nommée name ; cette commande ne lui affecte pas une chaîne vide. Lors d’un développement normal, les deux peuvent sembler vides, mais une vérification de variable non définie peut distinguer une variable absente d’une variable définie.
Points clés
- Les affectations utilisent
name=valuesans espaces autour de=. - Les noms de variables sont sensibles à la casse ; utilise des noms en minuscules pour tes propres valeurs.
${name}marque la fin d’un nom de variable avant le texte qui le suit directement.read -rlit une saisie tout en préservant les barres obliques inverses.- Les valeurs exportées sont copiées vers les processus fils, jamais en retour vers un parent.
unsetsupprime une variable.
2.2 Protège les mots, les variables et les caractères spéciaux
Bash lit une commande avant que le programme reçoive ses arguments. Les espaces séparent les mots et des caractères comme *, ?, $, ;, &, |, < et > ont des rôles particuliers. La protection des caractères détermine lesquels de ces rôles restent actifs.
Choisis ce qui doit être développé
| Forme | Ce que fait Bash |
|---|---|
'fixed text' | Conserve littéralement tout ce qui se trouve à l’intérieur. |
"text with $name" | Préserve les espaces et les caractères génériques, mais développe les variables, les sorties de commandes et les expressions arithmétiques. |
\* | Traite littéralement le caractère suivant hors des guillemets. |
Avec HOME=/home/sam, compare :
echo 'Home: $HOME *'
echo "Home: \$HOME *"
La première commande affiche « Home: $HOME * ». La deuxième affiche « Home: /home/sam * ». L’astérisque reste littéral dans les deux cas, mais seuls les guillemets doubles permettent le développement de la variable. Un guillemet simple ne peut pas être placé directement dans une chaîne entre guillemets simples.
Dans des guillemets doubles, les barres obliques inverses peuvent protéger un signe dollar, un accent grave, un guillemet double ou une barre oblique inverse. Par exemple, echo "Price: \$5" affiche « Price: $5 ». Hors des guillemets, echo 5 \* 3 affiche « 5 * 3 », et touch my\ file.txt crée un seul fichier dont le nom contient une espace.
Suis une valeur non protégée dans Bash
file="my report.txt"
cp $file backup/
Bash développe d’abord la variable. Puis le découpage en mots divise sa valeur aux espaces, tabulations et sauts de ligne. La commande reçoit my, report.txt et backup/ comme arguments distincts. Elle essaie de copier deux fichiers sources au lieu du seul fichier visé.
Si un mot obtenu contient des caractères génériques, le développement des noms de fichiers le remplace ensuite par les noms de fichiers correspondants. Une valeur stockée *.txt peut devenir plusieurs arguments de fichiers lorsqu’elle est développée sans guillemets. Ces étapes supplémentaires ont lieu avant le lancement de cp ; le programme ne peut pas retrouver le regroupement voulu.
cp "$file" backup/
La valeur développée reste maintenant un seul argument, « my report.txt ». Les caractères de guillemets eux-mêmes sont retirés par Bash ; ce sont des instructions d’analyse, pas une partie du chemin transmis à cp. Place des guillemets doubles autour des développements de variables et des substitutions de commande chaque fois que leur valeur entière doit rester groupée.
Conserve une valeur vide comme argument
La protection des caractères compte aussi lorsqu’une valeur est vide. Dans [ $answer = yes ], un answer vide disparaît, ce qui laisse un test invalide. [ "$answer" = yes ] transmet une chaîne vide comme un seul argument, donc le test est valide et faux.
La même règle de regroupement s’applique aux mots littéraux. mkdir new folder crée deux répertoires, tandis que mkdir "new folder" n’en crée qu’un. Protéger un chemin entier par des guillemets est utile, que son espace ait été saisie directement ou qu’elle provienne d’une variable.
Combine texte littéral et texte développé
Des parties entre guillemets adjacentes, sans espace entre elles, forment un seul mot. Avec price=8, echo 'Price: $'"$price" affiche « Price: $8 ». La partie fixe est entre guillemets simples et la partie qui change entre guillemets doubles. Un motif de recherche peut aussi être conservé tel quel : grep 'cost: \$[0-9]' prices.txt transmet son motif sans développement par le shell, laissant grep interpréter le motif.
Points clés
- Les guillemets simples conservent le texte littéralement ; les guillemets doubles permettent les développements tout en gardant les valeurs groupées.
- Les développements non protégés subissent un découpage en mots, puis un développement des noms de fichiers.
- Les guillemets conservent une valeur vide comme argument.
- Une barre oblique inverse peut rendre littéral un caractère spécial.
- Des parties entre guillemets adjacentes forment un seul mot lorsqu’aucune espace ne les sépare.
2.3 Récupère la sortie d’une commande et effectue des calculs sur des entiers
Les commandes produisent souvent une valeur dont une autre étape a besoin. Bash peut récupérer cette sortie, la placer dans du texte ou l’utiliser dans un calcul. La substitution de commande et le développement arithmétique ont une ponctuation similaire, mais remplissent des fonctions différentes.
Récupère la sortie standard
today=$(date +%F)
cp notes.txt "notes-${today}.txt"
$(...) exécute une commande et remplace la substitution par sa sortie standard. Le 22/10/2026, today contient « 2026-10-22 » et la copie est nommée notes-2026-10-22.txt. Une date dans l’ordre année-mois-jour permet de garder les noms de fichiers dans l’ordre des dates lorsqu’ils sont triés par nom. Tu peux aussi placer la substitution directement dans le nom : "notes-$(date +%F).txt".
Les caractères de saut de ligne en fin de sortie récupérée sont supprimés. L’ancienne forme avec accents graves récupère aussi la sortie, mais $(...) est plus facile à lire et à imbriquer. Place entre guillemets une substitution utilisée comme argument de commande, comme "$(date +%F)", pour garder son résultat groupé.
La substitution de commande ne récupère que la sortie standard. Les erreurs envoyées sur la sortie d’erreur standard continuent d’aller vers leur destination habituelle. result=$(some_command 2>&1) combine les deux flux dans la sortie récupérée lorsque le script en a besoin. Mélanger des erreurs à une valeur destinée à contenir un nombre ferait échouer les calculs ultérieurs.
Récupère un nombre sans nom de fichier
lines=$(wc -l < access.log)
echo "Lines: $lines"
Si le fichier contient 342 caractères de saut de ligne, wc fournit le nombre 342. Rediriger le fichier vers wc fait que sa sortie ne contient que le nombre ; wc -l access.log affiche aussi le nom du fichier. Un résultat qui ressemble à un nombre peut ensuite être réutilisé, à condition que la commande ait réussi.
Calcule avec des entiers
$(( ... )) effectue un développement arithmétique :
echo "$(( 17 / 5 ))"
echo "$(( 17 % 5 ))"
Les résultats sont 3 et 2. La division entière supprime le reste ; % le renvoie. L’addition, la soustraction et la multiplication utilisent +, - et *. Les noms de variables peuvent apparaître sans signe dollar dans l’expression : total=$(( price * qty )).
Avec a=5, echo "$a+3" affiche « 5+3 » comme du texte. echo "$(( a + 3 ))" calcule et affiche 8. Les parenthèses supplémentaires sélectionnent le calcul arithmétique ; $(a + 3) essaierait plutôt d’exécuter une commande nommée a.
Un compteur commence avec une valeur comme count=0 et se met à jour avec count=$(( count + 1 )). Bash propose aussi (( count++ )) ; c’est une commande arithmétique avec son propre code de retour, qui compte dans les scripts utilisant des options de gestion des erreurs.
Garde la précision nécessaire
Les calculs de Bash utilisent des entiers. 7 / 2 donne 3, et une valeur décimale comme 2.5 provoque une erreur de syntaxe arithmétique. Un outil distinct peut calculer avec des décimaux :
echo "scale=2; 7 / 2" | bc
Cela produit 3.50. En calcul entier, multiplie avant de diviser lorsque le produit conserve une fraction dont tu as encore besoin. Pour 45 sur 60, $(( 45 * 100 / 60 )) donne 75. Diviser d’abord donne zéro pour 45 / 60, donc $(( 45 / 60 * 100 )) reste égal à zéro ; la fraction perdue ne peut pas être récupérée par une multiplication ultérieure.
Points clés
$(command)récupère la sortie standard et supprime les sauts de ligne finaux.$((expression))effectue des calculs sur des entiers.- Utilise
/pour la division entière et%pour son reste. - Un compteur stocke sa valeur mise à jour après chaque incrémentation.
- Multiplier avant de diviser peut éviter une perte prématurée de précision dans les calculs entiers.
- Utilise un outil comme
bclorsqu’un résultat décimal est nécessaire.
3Indique la réussite ou l’échec avec des codes de retour
Un script a besoin d’un résultat compréhensible à la fois par les personnes et par les programmes. La sortie affichée explique ce qui s’est passé, tandis qu’un code de retour permet à une autre commande de décider si elle doit continuer. Tu vas enregistrer ce code, vérifier les étapes dont dépendent les suivantes et garder visibles les échecs des pipelines. Les vérifications syntaxiques, les traces d’exécution et les options de gestion des erreurs aident à trouver la cause d’une exécution échouée avant que les commandes suivantes n’en rendent les effets plus difficiles à voir.
3.1 Lis et définis les codes de retour, puis utilise-les pour enchaîner les commandes
Une commande indique son résultat de deux façons : elle peut afficher du texte et elle renvoie un code de retour. Les programmes utilisent ce code pour décider de la suite. Un script peut afficher un message rassurant et avoir pourtant échoué, ou ne rien afficher et réussir.
Lis un code avant qu’il change
Un code de retour est un entier de 0 à 255. Zéro signifie une réussite. Une valeur non nulle indique un échec ou un autre résultat documenté. grep, par exemple, utilise 0 pour une correspondance, 1 en l’absence de correspondance et 2 pour une erreur. Une recherche qui ne trouve aucune correspondance peut être un résultat normal pour ta tâche, même si son code de retour est non nul.
$? contient le code de retour de la commande la plus récente :
grep -q root /etc/passwd
status=$?
echo "Search status: $status"
L’affectation enregistre le résultat avant qu’une autre commande ne le remplace. Dans ls /missing; echo $?; echo $?, GNU ls renvoie 2 pour le chemin inaccessible fourni en ligne de commande. Le premier echo affiche 2, puis réussit. Le second affiche 0, le code de retour de cet echo, et non celui de l’affichage initial.
Termine avec un résultat utile
exit 1 termine immédiatement un script et renvoie 1 au programme appelant. exit 0 indique une réussite. Un exit sans nombre utilise le code de retour de la commande précédente ; une fin normale utilise celui de la dernière commande. Choisis des codes entre 0 et 255 : exit 256 revient à 0 et indiquerait à tort une réussite.
Certains codes de retour viennent de Bash lui-même :
| Code | Signification |
|---|---|
| 127 | La commande est introuvable. |
| 126 | La commande a été trouvée mais n’a pas pu être exécutée. |
128 + n | La commande s’est terminée à cause du signal numéro n. |
Ctrl+C envoie le signal 2, donc une commande arrêtée ainsi renvoie généralement 130. Les programmes ordinaires documentent aussi leurs propres codes ; 1 et 2 n’ont pas une signification universelle commune à tous les outils.
Enchaîne des commandes dépendantes
mkdir -p ~/backup && cp notes.txt ~/backup/
cd /data/reports || exit 1
&& n’exécute la commande suivante qu’après une réussite. Ici, la copie dépend de la création ou de la présence du répertoire de sauvegarde. || n’exécute la commande suivante qu’après un échec. Ici, un échec du changement de répertoire arrête le script avant que les commandes suivantes n’utilisent le mauvais répertoire de travail.
true renvoie 0 ; false renvoie 1. Un ! placé en début de commande inverse sa réussite ou son échec. ! grep -q ERROR app.log réussit lorsque la recherche ne trouve aucune ligne correspondante, mais aussi si grep échoue avec une erreur ; utilise des vérifications explicites du code de retour lorsque ces résultats doivent être distingués.
Vérifie un pipeline entier
grep ERROR missing.log | wc -l
Par défaut, un pipeline a le code de retour de sa dernière commande. grep échoue à cause du fichier absent, mais wc lit un flux vide, affiche 0 et réussit. Le code de retour du pipeline est donc 0.
set -o pipefail fait échouer un pipeline si l’un de ses éléments échoue. Il renvoie le code non nul le plus à droite, ou 0 si toutes les commandes réussissent. Cela rend les erreurs en amont visibles pour if, &&, || et le programme appelant. Un planificateur peut alors distinguer un compte rendu réussi d’un compte rendu qui n’a jamais lu ses données d’entrée.
Points clés
- Le code de retour 0 signifie une réussite ; les résultats non nuls ont des significations documentées par chaque programme.
- Enregistre immédiatement
$?si tu dois l’utiliser après une autre commande. exitfournit un résultat au programme qui appelle le script.&&poursuit après une réussite et||poursuit après un échec.- Sans
pipefail, un pipeline ne renvoie que le code de retour de sa dernière commande.
3.2 Repère les erreurs et arrête un script en toute sécurité
Bash continue normalement après l’échec d’une commande. Si la commande suivante dépend de ce travail, continuer peut transformer un petit échec en problème plus grave. Vérifie explicitement les étapes dont dépendent les suivantes, puis utilise la vérification syntaxique et le traçage de l’exécution pour comprendre pourquoi une exécution se déroule autrement que prévu.
Arrête-toi avant qu’un échec ait d’autres conséquences
cd /backups || exit 1
Les commandes suivantes ne peuvent désormais s’exécuter que si le changement de répertoire a réussi. C’est important avant les opérations sur les fichiers : si un changement de répertoire échoue et que le script continue, les chemins relatifs désignent toujours l’ancien répertoire. Vérifie la destination avant d’exécuter des commandes qui modifient ou suppriment des fichiers.
Un message d’erreur et un code d’échec servent à des lecteurs différents :
echo "Error: $file not found" >&2
exit 1
Le message va sur la sortie d’erreur standard, ce qui laisse la sortie standard disponible pour les données. Avec ./report.sh > report.txt, le message reste visible dans le terminal tandis que la sortie normale va dans le fichier. Le code non nul permet à un autre programme de détecter l’erreur sans lire la phrase.
Vérifie la syntaxe, puis trace l’exécution
| Commande | Effet |
|---|---|
bash -n script.sh | Lit la syntaxe sans exécuter les commandes. |
bash -x script.sh | Exécute le script et affiche les commandes développées avant de les exécuter. |
L’absence de fi, de done ou d’un guillemet fermant est un problème de syntaxe. bash -n peut le localiser, souvent au moyen d’un message « unexpected end of file ». Un chemin de fichier dont la syntaxe est valide mais qui contient une faute de frappe nécessite une vérification à l’exécution.
Le traçage fait précéder les commandes de +. Une ligne comme cp "$src" "$dest" révèle les chemins effectivement reçus. set -x et set +x activent et désactivent le traçage autour d’une section.
Comprends les options de gestion des erreurs
set -euo pipefail combine trois contrôles :
-equitte après l’échec non traité d’une commande.-usignale une variable non définie comme une erreur.pipefailfait en sorte que les échecs des éléments d’un pipeline influent sur son code de retour.
-e laisse une place aux échecs attendus dans les conditions if, while et until, les commandes inversées et les commandes non finales des listes && ou ||. Sans pipefail, un échec avant la dernière commande du pipeline ne déclenche pas de sortie. Les vérifications explicites restent utiles parce qu’elles indiquent ce que le script doit faire lorsqu’une étape précise échoue.
Une commande arithmétique indique aussi vrai ou faux. (( count++ )) renvoie le code 1 lorsque l’ancienne valeur est 0, donc une utilisation non traitée sous -e peut arrêter le script même si l’incrémentation a eu lieu. L’affectation count=$(( count + 1 )) évite ce code de retour de commande arithmétique.
-u détecte une faute de frappe comme $filname lorsque seule filename a été définie. Il ne rejette pas une variable qui existe mais qui est vide. ${dir:?not set} vérifie si dir est absente ou vide lors de ce développement. Une absence de correspondance attendue peut être traitée avec un test ; command || true masque tous les échecs de cette commande, donc ne l’utilise que si tous ces échecs sont acceptables.
Lis les messages et effectue le nettoyage
« Command not found » indique un problème de nom, de programme installé ou de PATH. « Permission denied » indique un problème d’exécution ou d’accès à un fichier. « Unary operator expected » provient souvent d’une valeur vide non protégée dans [ ] ; « integer expression expected » signifie qu’un test numérique a reçu du texte.
Un gestionnaire de signal (trap) sur EXIT met en place un nettoyage, comme trap 'rm -f "$tmpfile"' EXIT, après l’affectation de tmpfile. La commande entre guillemets s’exécute lorsque Bash se termine, notamment avec un exit explicite ou à la suite d’une erreur sous -e. ShellCheck peut aussi examiner les scripts avant leur exécution pour y détecter des erreurs courantes de protection des caractères et de logique.
Points clés
- Vérifie une étape avant d’exécuter les commandes qui en dépendent.
- Écris les messages de diagnostic sur la sortie d’erreur standard et indique un échec par un code de retour non nul.
bash -nvérifie la syntaxe ;bash -xexécute et trace.set -eprévoit des exceptions pour les échecs soumis à un test.set -udétecte les variables non définies, tandis que${name:?message}rejette aussi les valeurs vides.- Un gestionnaire de signal sur EXIT peut supprimer un fichier temporaire à la fin du script.
4Choisis les actions à exécuter et répète des tâches
Un script utile choisit des actions et les répète sur des données d’entrée qui changent. Les tests transforment des questions sur les fichiers, le texte et les nombres en réussite ou en échec. Les branches sélectionnent une action, tandis que les boucles appliquent des commandes à des listes ou continuent jusqu’au changement d’une condition. Tu vas suivre la valeur utilisée à chaque passage et préserver les espaces, les enregistrements et les compteurs pendant que les données circulent dans le script.
4.1 Teste des fichiers, des chaînes et des nombres
Une condition dans Bash est une commande dont le code de retour signifie vrai ou faux. Les tests permettent de poser des questions sur les chemins, le texte et les nombres. Choisis un opérateur adapté au type de valeur ; les mêmes caractères affichés peuvent avoir des significations différentes selon qu’il s’agit de texte ou d’un nombre.
Sépare les éléments du test
test -f notes.txt et [ -f notes.txt ] vérifient si un chemin désigne un fichier ordinaire existant. [ est une commande dont le dernier argument doit être ]. Des espaces séparent ses arguments :
[ -f "$file" ]
Sans espace après [, Bash peut chercher une commande nommée [-f. Dans [ "$a"="$b" ], l’absence d’espaces autour de = forme un seul mot non vide, que le test considère comme vrai même si les valeurs diffèrent. Les opérateurs doivent être des arguments distincts.
Choisis un test sur un fichier
| Opérateur | Vrai lorsque le chemin… |
|---|---|
-e | Existe. |
-f | Désigne un fichier ordinaire existant. |
-d | Désigne un répertoire existant. |
-r, -w, -x | Est respectivement lisible, modifiable ou exécutable par l’utilisateur courant. |
-s | Existe et a une taille supérieure à zéro. |
-L | Est un lien symbolique. |
Pour un répertoire nommé logs, -e et -d réussissent tandis que -f échoue. Les tests sur les fichiers suivent normalement un lien symbolique jusqu’à sa cible ; -L vérifie le lien lui-même. Un lien cassé peut donc satisfaire -L et faire échouer -e.
Compare du texte ou des nombres entiers
Les tests sur les chaînes utilisent = et != pour l’égalité et l’inégalité. -z vérifie si la longueur est nulle et -n si elle est non nulle. [ "$answer" = yes ] correspond exactement à « yes » ; « Yes » et « yes » sont des textes différents. Les guillemets doubles maintiennent une valeur vide dans le test.
Les comparaisons d’entiers utilisent -eq, -ne, -lt, -le, -gt et -ge : égal, différent, inférieur, inférieur ou égal, supérieur et supérieur ou égal. [ "$count" -gt 100 ] vérifie si le nombre dépasse 100.
[ 07 -eq 7 ]
[ 07 = 7 ]
La comparaison numérique réussit car les valeurs sont égales. La comparaison de chaînes échoue car l’un des textes commence par un zéro supplémentaire.
N’utilise pas > seul pour un test numérique dans [ ]. Dans [ 10 > 9 ], Bash redirige la sortie vers un fichier nommé 9 et teste le mot non vide restant. Dans [[ 10 < 9 ]] de Bash, l’opérateur compare des chaînes, donc le caractère initial 1 se classe avant 9. Utilise -lt ou -gt pour les comparaisons numériques, ou le calcul arithmétique Bash comme (( count > 100 )).
Combine des conditions
[ ! -d "$dir" ] réussit lorsque le chemin ne désigne pas un répertoire existant ; il peut désigner un fichier ordinaire ou être absent. [ -f "$f" ] && [ -r "$f" ] ne réussit que si les deux tests réussissent. Des tests distincts reliés par || réussissent si au moins l’un d’eux réussit.
Bash possède aussi le mot-clé conditionnel [[ ... ]]. Il empêche le découpage en mots des développements de variables et autorise && et || à l’intérieur. Un motif non protégé à droite de == sert à rechercher une correspondance : [[ $file == *.log ]] correspond à « app.log ». Placer ce motif entre guillemets le rendrait littéral. Cette syntaxe nécessite Bash ; dash ne la prend pas en charge.
Points clés
- Un test indique vrai avec le code de retour 0 et faux avec le code 1.
- Place des espaces autour de
[et de ses opérateurs, et ferme avec]. - Les tests sur les fichiers distinguent l’existence, le type et l’accès.
- L’égalité de chaînes compare du texte ; les opérateurs numériques comparent des valeurs entières.
- Utilise
-gtet-ltpour les nombres, plutôt que des symboles de redirection seuls. - La négation inverse un test ;
&&exige que les deux conditions soient remplies. [[ ... ]]de Bash prend en charge les motifs et évite le découpage en mots.
4.2 Choisis les actions avec if, elif, else et case
Les conditions deviennent utiles lorsqu’elles sélectionnent des actions. Un bloc if choisit une branche à partir des résultats de commandes. Un bloc case sélectionne une branche en comparant une valeur à des motifs. Les deux rendent les actions possibles visibles dans le script.
Laisse une commande choisir une branche
if grep -q ERROR app.log; then
echo "Errors found"
else
echo "No successful match"
fi
if exécute la commande et entre dans la première branche lorsqu’elle renvoie 0. Sinon, il entre dans else. La recherche elle-même est la condition ; il n’est pas nécessaire de l’exécuter, d’afficher quelque chose, puis d’examiner $?. Une erreur de grep renvoie aussi un code non nul, donc cet exemple décrit la branche else comme une absence de correspondance trouvée, et non comme la preuve que le fichier ne contient aucune erreur.
then doit commencer une nouvelle commande : place-le sur la ligne suivante ou après un point-virgule. fi ferme le bloc. L’absence de fi produit souvent une erreur de syntaxe en fin de fichier, car Bash attend encore la fermeture du bloc.
Ordonne les conditions qui se recoupent
elif ajoute un test qui ne s’exécute que si les tests précédents ont échoué. Pour un pourcentage entier d’occupation du disque :
if [ "$usage" -ge 90 ]; then
echo "CRITICAL: disk ${usage}% full"
elif [ "$usage" -ge 75 ]; then
echo "WARNING: disk ${usage}% full"
else
echo "OK: disk ${usage}% full"
fi
Avec usage=82, le premier test échoue et le deuxième réussit, ce qui produit « WARNING: disk 82% full ». Avec 95, la première branche s’exécute et la branche d’avertissement est ignorée. Si le test à 75 venait en premier, 95 y correspondrait et n’atteindrait jamais le test critique. Ordonne les plages qui se recoupent pour que la condition la plus restrictive puisse être testée.
Seule la première branche dont le test réussit s’exécute. else ne nécessite aucune condition et traite les cas restants. elif ou else peuvent être omis lorsque la tâche n’en a pas besoin.
Compare une valeur avec case
case "$1" in
start) echo "Starting" ;;
stop) echo "Stopping" ;;
y|Y|yes) echo "Confirmed" ;;
*) echo "Usage: $0 start|stop|y|Y|yes" >&2; exit 2 ;;
esac
Chaque motif se termine par ), chaque branche par ;;, et esac ferme le bloc. Le | dans un motif propose des possibilités. Le * final est le motif universel et doit être placé en dernier, car il correspond à toute valeur.
case utilise des motifs de type nom de fichier, et non des expressions régulières. *.jpg correspond à une valeur se terminant par .jpg. [0-9]* correspond à une valeur dont le premier caractère est un chiffre ; le * peut ensuite correspondre à tout texte qui suit, donc il correspond aussi à « 7draft ». Cela ne prouve pas qu’une valeur entière ne contient que des chiffres.
Choisis la structure adaptée
Utilise case lorsqu’une donnée d’entrée, comme une sous-commande ou une réponse, possède plusieurs formes nommées. Utilise if lorsque les conditions examinent des éléments différents, comme l’existence d’un fichier et le dépassement d’une limite par un compteur. Une correspondance de motif porte sur les caractères d’une valeur ; un test sur un fichier porte sur le chemin sur le disque. Un nom se terminant par .log peut correspondre à un motif même si aucun fichier de ce nom n’existe.
Points clés
ifchoisit une branche selon le code de retour d’une commande ; toute commande peut être une condition.- Les tests
elifne s’exécutent qu’après l’échec des conditions précédentes. - Ordonne les seuils qui se recoupent du plus restrictif au plus large.
casesélectionne le premier motif correspondant et utilise;;pour terminer chaque branche.- Une correspondance avec un motif ne prouve pas qu’un fichier existe.
4.3 Répète des commandes sur des listes et des fichiers avec for
Une boucle for donne une nouvelle valeur au même corps de commandes à chaque passage. La liste peut contenir des mots littéraux, des noms de fichiers correspondants, une suite de nombres ou les arguments du script. Bash affecte un élément de la liste à la variable de boucle avant d’exécuter le corps.
Parcours une liste fixe
for host in web1 web2 db1; do
echo "Checking $host"
done
Au premier passage, host=web1, au deuxième host=web2 et au troisième host=db1. La boucle affiche trois lignes. do ouvre le corps et done le ferme. La variable reste disponible après la boucle et conserve la dernière valeur qui lui a été affectée.
Une boucle peut aussi accumuler un résultat :
total=0
for n in 4 8 15; do
total=$(( total + n ))
done
echo "$total"
Le total stocké passe de 0 à 4, puis à 12, puis à 27. Initialise le total avant la boucle pour que la première addition dispose d’une valeur de départ définie.
Parcours les fichiers correspondants
for f in *.log; do
[ -f "$f" ] || continue
gzip -- "$f"
done
Bash développe le motif de nom de fichier en noms correspondants avant l’exécution du corps de la boucle. Chaque nom de fichier correspondant reste un seul élément de la liste, même s’il contient des espaces. Protéger "$f" par des guillemets dans le corps conserve cet élément groupé lorsqu’il est transmis à gzip. Ici, le test de fichier ordinaire ignore aussi les répertoires dont le nom se termine par .log.
Avec les paramètres par défaut de Bash, un motif *.log sans correspondance reste littéral. Une boucle sans vérification s’exécuterait une fois sur les caractères *.log et la commande échouerait. [ -e "$f" ] || continue ignore les chemins inexistants ; utilise -f lorsque seuls les fichiers ordinaires sont souhaités.
Ne construis pas une boucle sur les noms de fichiers à partir de $(ls). Sa sortie est du texte, donc le découpage en mots peut transformer « my report.txt » en deux éléments de liste. Un motif de nom de fichier produit déjà les noms en conservant leurs limites.
Construis un nouveau nom à partir de chaque ancien nom
for f in *.jpeg; do
[ -f "$f" ] || continue
mv -- "$f" "${f%.jpeg}.jpg"
done
${f%.jpeg} retire la terminaison .jpeg de la valeur. Pour « beach day.jpeg », la destination devient « beach day.jpg ». Les deux arguments entre guillemets gardent les deux chemins intacts. -- indique à mv que les arguments suivants sont des noms, même si l’un d’eux commence par -. Utilise un dossier de destination sans noms en conflit lorsque tu essaies l’exemple, car mv peut remplacer une destination existante.
Parcours une suite de nombres
for i in {1..5} fournit les nombres de 1 à 5. Bash développe les accolades avant les variables, donc {1..$n} ne produit pas une suite de longueur variable. Pour une limite stockée, utilise la forme arithmétique :
for (( i = 1; i <= n; i++ )); do
echo "$i"
done
La première expression initialise le compteur, celle du milieu le teste avant chaque passage et la dernière le met à jour. for i in $(seq 1 "$n") produit aussi une liste de nombres pour une limite entière positive adaptée. La substitution volontairement non protégée fournit ici des nombres distincts.
Pour les arguments, for arg in "$@" fournit un élément par argument d’origine. La forme plus courte for arg; do signifie la même chose, y compris la conservation des espaces dans chaque argument.
Points clés
- Une boucle
forexécute son corps une fois par élément de la liste. - Les motifs fournissent des noms de fichiers entiers ; protège la variable de boucle par des guillemets dans le corps.
- Un motif sans correspondance reste littéral avec les paramètres par défaut de Bash ; prévois donc une vérification dans les boucles sur les fichiers.
- Évite les boucles sur les noms de fichiers construites à partir de
$(ls). - Les suites entre accolades sont fixées avant le développement des variables ; utilise une boucle arithmétique pour une limite variable.
"$@"préserve les limites des arguments d’origine.
4.4 Répète des commandes jusqu’au changement d’une condition avec while et until
Certaines répétitions prennent fin lorsqu’une condition change, et non lorsqu’une liste est épuisée. while et until testent la condition avant chaque passage. Le corps de while s’exécute tant que sa condition réussit ; celui de until s’exécute tant que sa condition échoue. Les deux boucles peuvent ne jamais s’exécuter.
Mets à jour ce dont dépend la condition
i=1
while [ "$i" -le 3 ]; do
echo "Attempt $i"
i=$(( i + 1 ))
done
La condition voit d’abord 1, puis 2, puis 3. Le corps affiche ces trois numéros de tentative et augmente le compteur chaque fois. Après la mise à jour à 4, le test suivant échoue et la boucle se termine. Si la mise à jour manquait, i resterait à 1 et la boucle continuerait à s’exécuter. Ctrl+C arrête une boucle en cours au premier plan.
Pour attendre un fichier :
until [ -f /tmp/export.done ]; do
sleep 5
done
Si le fichier existe déjà, le corps de la boucle ne s’exécute jamais. Sinon, sleep 5 marque une pause de cinq secondes avant la vérification suivante. Une pause évite que la boucle effectue des tests en continu et gaspille du temps processeur.
Lis les enregistrements sous forme de lignes
while IFS= read -r line; do
echo "Host: $line"
done < hosts.txt
read fournit une ligne à chaque passage et renvoie un code d’échec en fin de fichier. IFS= préserve les espaces au début et à la fin de la ligne ; -r conserve les barres obliques inverses. La redirection d’entrée après done alimente toute la boucle, pas seulement sa dernière commande.
Une ligne comme « web1 production » reste une seule valeur. for line in $(cat hosts.txt) découperait aux espaces, tabulations et sauts de ligne, en traitant ces deux mots comme des itérations distinctes. Cette forme ne peut pas préserver des enregistrements quelconques organisés par ligne.
Conserve les modifications après la boucle
Un tube vers une boucle, comme dans cat hosts.txt | while read -r line; do ...; done, exécute normalement la boucle dans un processus fils avec Bash. Un compteur modifié à cet endroit est perdu pour le parent lorsque le processus fils se termine. Redirige le fichier vers la boucle lorsque les commandes suivantes ont besoin des valeurs accumulées :
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < hosts.txt
echo "$count"
Cela traite les lignes terminées par un saut de ligne et conserve le compteur mis à jour dans le shell courant. Aucun pipeline ne crée de processus fils pour la boucle.
Traite le dernier enregistrement et les sorties anticipées
Un fichier peut se terminer par du texte sans saut de ligne final. read stocke ce dernier texte mais signale un échec, donc une boucle while read simple n’entre pas dans son corps pour cet enregistrement. Ajoute un deuxième test pour accepter le texte non vide stocké :
while IFS= read -r line || [ -n "$line" ]; do
echo "Host: $line"
done < hosts.txt
break quitte immédiatement la boucle. continue saute les commandes restantes du passage courant, puis revient à la vérification suivante de la condition. Une boucle while true a donc besoin d’un break, d’un exit ou d’un signal pour se terminer ; elle peut servir à un menu qui s’arrête lorsque la saisie est « q ». Dans une boucle avec compteur, place une mise à jour avant tout continue qui la sauterait autrement, faute de quoi ce passage pourrait se répéter indéfiniment.
Points clés
whilerépète après une réussite ;untilrépète après un échec.- Les deux boucles testent la condition avant d’entrer dans leur corps.
- Mets à jour un compteur ou marque une pause dans une boucle de vérification pour qu’elle progresse sans attente active.
IFS= read -rpréserve les espaces et les barres obliques inverses dans une lecture ligne par ligne.- Redirige un fichier vers la boucle pour conserver les variables modifiées dans le shell courant.
- Un test supplémentaire de chaîne non vide préserve un dernier enregistrement sans saut de ligne.
breakquitte une boucle ;continuepasse à son passage suivant.
5Transmets des arguments aux scripts
Les arguments de ligne de commande permettent à un même script de servir à de nombreuses tâches sans modifier son code. Tu vas lire des valeurs individuelles, préserver une liste complète d’arguments et traiter les options placées au début. Avant de commencer le travail, compte et valide les données d’entrée, explique comment appeler correctement le script et fournis des valeurs par défaut pour les valeurs facultatives. Le script obtenu peut s’exécuter à une invite de commande ou sans surveillance, avec des messages clairs et un code de retour lorsque les données d’entrée sont inutilisables.
5.1 Lis les paramètres positionnels et le nombre d’arguments
Les arguments transforment un script aux données d’entrée fixes en commande réutilisable. Bash place les mots qui suivent le nom du script dans des paramètres positionnels. Leurs limites sont définies par le shell appelant, donc les guillemets comptent à la fois lors de l’appel du script et lorsqu’il utilise ces valeurs.
Identifie les paramètres
./backup.sh /home/sam/docs /mnt/usb
Dans le script, $0 vaut ./backup.sh, $1 vaut /home/sam/docs et $2 vaut /mnt/usb. $# vaut 2, le nombre d’arguments. Le script peut utiliser cp -r "$1" "$2" pour copier le dossier source vers la destination sans inscrire en dur l’un ou l’autre chemin.
$0 indique le nom utilisé pour lancer le script ; il n’est pas compté dans $#. Avec ./greet.sh Ana "Lee Kim", le premier argument est « Ana » et le deuxième est « Lee Kim ». Sans les guillemets autour du deuxième nom, le script recevrait trois arguments.
Utilise des accolades après le neuvième argument
$1 à $9 désignent les neuf premiers paramètres positionnels. Le dixième nécessite ${10}, et les rangs suivants utilisent la même forme. $10 signifie le développement de $1 suivi du caractère littéral 0. Si le premier argument est « Ana », $10 devient « Ana0 » même lorsqu’un dixième argument existe.
Un paramètre omis se développe en texte vide avec les paramètres normaux. Avec deux arguments, $3 est absent ; sous set -u, son développement provoque une erreur de variable non définie. Vérifie le nombre avant de lire les rangs obligatoires ou utilise un développement qui fournit une valeur par défaut.
Préserve toutes les limites des arguments
Supposons qu’un script reçoive "a b" et c. Compare :
| Développement | Mots transmis |
|---|---|
"$@" | Deux : « a b » et « c ». |
"$*" | Un : « a b c », avec l’espace habituelle comme séparateur. |
$@ | Trois : « a », « b » et « c » avec le découpage normal. |
"$@" est le choix habituel pour transmettre les arguments :
for arg in "$@"; do
echo "Argument: $arg"
done
La boucle s’exécute deux fois pour cet appel, une fois par argument d’origine. Sans argument, elle ne s’exécute pas. Placer "$@" entre guillemets doubles a un sens particulier : chaque paramètre positionnel reste un mot distinct, donc les guillemets ne réunissent pas toute la liste en un seul mot.
"$*" réunit les valeurs en utilisant le premier caractère de IFS, qui est normalement une espace. Cela peut être utile pour une seule chaîne à afficher, mais les limites individuelles dont une commande ultérieure peut avoir besoin sont perdues.
Traite les paramètres avec shift
shift retire le premier paramètre positionnel, décale les suivants et diminue $#. Dans l’appel de sauvegarde, un décalage donne à $1 la valeur /mnt/usb et ramène le nombre à 1. shift 2 retire les deux premiers paramètres à la fois.
Cela permet de créer une boucle qui examine $1, le traite, puis décale les paramètres avant le passage suivant. Vérifie qu’il reste des arguments avec [ "$#" -gt 0 ] ; sinon, le script peut lire une valeur manquante ou tenter de décaler au-delà des arguments disponibles. Le décalage ne modifie pas $0 et ne peut pas modifier la liste d’arguments du shell parent qui a lancé le script.
Points clés
$0est le nom utilisé pour l’appel, tandis que$1et les paramètres suivants contiennent les arguments.$#compte les arguments, les espaces protégées par des guillemets restant dans un seul argument.- Utilise
${10}pour le dixième argument ;$10est$1suivi de0. "$@"préserve les arguments séparément, tandis que"$*"les réunit.shiftretire les premiers paramètres et modifie les rangs des paramètres restants.
5.2 Vérifie les arguments, affiche le mode d’utilisation et définis les valeurs par défaut
Un script devrait s’assurer que ses données d’entrée sont utilisables avant de commencer son travail. Vérifie le nombre d’arguments, puis leur signification. Les données facultatives peuvent avoir des valeurs par défaut ; les données obligatoires manquantes nécessitent un diagnostic clair et un code de retour non nul.
Explique l’appel attendu
if [ "$#" -ne 2 ]; then
echo "Usage: $0 SOURCE DEST" >&2
exit 2
fi
Cela vérifie le nombre avant de développer $1 ou $2, donc fonctionne aussi sous set -u. Le message d’utilisation va sur la sortie d’erreur standard. Les majuscules désignent les valeurs fournies par l’utilisateur, [DEST] désignerait une destination facultative et FILE... signifie un ou plusieurs arguments de fichiers. Une option d’aide comme -h affiche normalement le mode d’utilisation et quitte avec 0, car demander de l’aide est une utilisation réussie.
Le seul nombre d’arguments ne permet pas de savoir si une source est utilisable. [ -d "$1" ] vérifie l’existence d’un répertoire. Un test de fichier ordinaire peut sélectionner des fichiers, mais l’opération elle-même nécessite encore une vérification de son résultat : les droits ou d’autres erreurs peuvent empêcher une lecture.
Utilise une valeur par défaut ou exige une valeur
logdir=${1:-/var/log}
src=${1:?Usage: backup.sh SOURCE [DEST]}
La première forme utilise /var/log lorsque le premier paramètre est absent ou vide. La deuxième arrête un script non interactif dans les deux cas et affiche son message sur la sortie d’erreur standard. Les deux-points font partie des deux formes. Une valeur par défaut est utilisée pour ce développement ; ${1:-...} n’ajoute pas d’argument à la liste des paramètres positionnels.
Garde la trace d’un échec partiel
Un script qui compte les lignes de fichiers peut continuer après une donnée d’entrée incorrecte tout en indiquant que la tâche entière n’a pas été achevée :
#!/bin/bash
if [ "$#" -eq 0 ]; then
echo "Usage: $0 FILE..." >&2
exit 2
fi
status=0
for f in "$@"; do
if [ -f "$f" ]; then
if lines=$(wc -l < "$f"); then
echo "$f: $lines lines"
else
echo "$f: could not count lines" >&2
status=1
fi
else
echo "$f: not a regular file" >&2
status=1
fi
done
exit "$status"
Pour notes.txt missing.txt, le script affiche le nombre de lignes du fichier lisible et signale le fichier absent, puis quitte avec 1. L’affectation est testée directement, donc un échec de lecture ne devient pas un comptage vide considéré comme réussi. Une réussite ultérieure ne remet jamais l’indicateur d’échec stocké à 0.
Traite les options simples avant les noms de fichiers
verbose=0
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
-h) echo "Usage: $0 [-v] FILE..."; exit 0 ;;
--) shift; break ;;
-*) echo "Unknown option: $1" >&2; exit 2 ;;
*) break ;;
esac
done
Chaque option reconnue est consommée avec shift. Le premier argument ordinaire met fin à l’analyse des options ; -- y met aussi fin et est lui-même consommé. Le "$@" restant contient les noms de fichiers, y compris un nom commençant par - après --. getopts de Bash prend en charge une analyse plus complète des options courtes.
Un script sans surveillance doit recevoir toutes les données nécessaires par des arguments, des valeurs par défaut ou une configuration. read peut bloquer dans l’attente d’un terminal ou échouer immédiatement en fin de fichier. Remplacer un argument manquant par une invite laisserait une tâche planifiée sans moyen fiable de poursuivre.
Points clés
- Valide le nombre avant de développer les arguments obligatoires.
- Un message d’utilisation nomme les données obligatoires, facultatives et répétables.
${1:-value}fournit une valeur par défaut ;${1:?message}rejette une valeur absente ou vide.- Vérifie le résultat de l’opération même après avoir vérifié le type du fichier fourni.
- Conserve un code d’échec global lorsque tu poursuis le traitement de plusieurs données d’entrée.
- Consomme les options avec
shiftet respecte--comme marque de fin des options.
6Planifie l’exécution automatique de scripts
Un script sans surveillance a besoin d’une planification et d’un moyen d’examiner ses résultats. Cron exprime les heures correspondantes sur une seule ligne ; systemd associe un service à une minuterie. Tu vas lire les deux formes, fournir l’environnement nécessaire à la tâche et garder sa sortie disponible. Vérifier séparément la prochaine activation et le résultat de la dernière tâche aide à distinguer une planification active d’un travail qui a réellement réussi.
6.1 Planifie des tâches avec cron
Cron lance des commandes aux heures correspondantes. La crontab de chaque utilisateur stocke sa planification et les tâches s’exécutent sous son identité. Un script planifié nécessite à la fois une expression temporelle correcte et un environnement qui fournit ses chemins, ses données d’entrée et la destination de sa sortie.
Lis les cinq champs
Utilise crontab -e pour modifier ta table et crontab -l pour l’examiner. crontab -r supprime toute la table sans demander de confirmation ; utilise l’éditeur pour supprimer une seule tâche.
| Champ, dans l’ordre | Valeurs |
|---|---|
| Minute | 0–59 |
| Heure | 0–23 |
| Jour du mois | 1–31 |
| Mois | 1–12 |
| Jour de la semaine | 0–7 ; 0 et 7 désignent le dimanche |
30 2 * * * /home/sam/bin/backup.sh
Cette tâche s’exécute tous les jours à 02 h 30. Les astérisques acceptent toutes les valeurs d’un champ. 0 9 * * 1-5 sélectionne 09 h 00 en semaine, et 0 0 1 * * sélectionne minuit le premier jour de chaque mois. Les heures utilisent le fuseau horaire du système, sauf si la configuration de cron précise un autre fuseau pris en charge.
Combine plages, listes et pas d’incrémentation
Une virgule énumère des valeurs : 1,15 dans le champ du jour du mois sélectionne le premier et le quinzième. Un trait d’union indique une plage et / introduit un pas. */15 dans le champ des minutes sélectionne 0, 15, 30 et 45.
*/20 8-10 * * * sélectionne trois minutes dans chacune de trois heures : neuf exécutions quotidiennes, de 08 h 00 à 10 h 40. Les pas recommencent dans leur champ. */45 s’exécute à la minute 0 et à la minute 45 de chaque heure ; l’intervalle jusqu’à la minute 0 de l’heure suivante n’est que de 15 minutes.
Lorsque le jour du mois et le jour de la semaine sont tous deux restreints, la correspondance de l’un ou l’autre suffit. 0 12 13 * 5 sélectionne midi le 13 et les vendredis, pas seulement le vendredi 13. Les autres champs doivent toujours correspondre.
Des chaînes spéciales remplacent les cinq champs : @hourly, @daily, @weekly, @monthly, @yearly et @reboot. @daily signifie minuit, tandis que @reboot s’exécute une fois au démarrage.
Fournis les chemins et conserve la sortie
Cron utilise normalement /bin/sh pour sa ligne de commande, un PATH court et aucun paramètre de démarrage du shell interactif. Le shebang Bash d’un script exécutable sélectionne néanmoins Bash. Utilise des chemins absolus pour le script et ses fichiers, ou définis PATH en haut de la crontab.
30 2 * * * /home/sam/bin/backup.sh >> /home/sam/backup.log 2>&1
La tâche ajoute les deux flux de sortie au journal. Sans redirection, cron envoie la sortie par courriel lorsque la messagerie est configurée, notamment par MAILTO ; sinon, la sortie peut être perdue. Un signe pourcentage a un rôle particulier dans une commande de crontab : il commence une nouvelle ligne et les données d’entrée qui suivent. Échappe un format de date à cet endroit, comme dans date +\%F. Une commande de date dans un script distinct utilise %F normalement.
Distingue les planifications système et les tâches de rattrapage
/etc/crontab et les fichiers de /etc/cron.d/ ajoutent un champ utilisateur après les cinq champs temporels. Par exemple, 30 2 * * * root /usr/local/bin/backup.sh s’exécute sous l’identité de root. N’ajoute pas ce champ utilisateur à une crontab personnelle.
De nombreuses distributions exécutent aussi les fichiers exécutables admissibles dans /etc/cron.daily/, /etc/cron.weekly/ et /etc/cron.monthly/. Les règles de nommage par défaut de run-parts sur Debian ignorent les noms contenant des points ; utilise donc backup-notes, et non backup-notes.sh, à ces emplacements. Cron manque les heures qui passent lorsque l’ordinateur est éteint. Anacron peut rattraper les tâches périodiques quotidiennes, hebdomadaires ou mensuelles après le démarrage.
Points clés
- Une crontab personnelle comporte cinq champs temporels suivis directement d’une commande.
- Les listes, les plages et les pas sélectionnent des valeurs dans chaque champ.
- Lorsque les champs du jour du mois et du jour de la semaine sont restreints, la correspondance de l’un ou l’autre suffit.
- Utilise des chemins absolus et un journal de sortie pour les tâches sans surveillance.
- Échappe
%dans une commande de crontab, y compris dans les formats de date. - Les crontabs système ajoutent un champ utilisateur ; les dossiers périodiques appliquent aussi des règles d’admissibilité.
- Cron manque les exécutions lorsque la machine est éteinte ; anacron permet le rattrapage des tâches périodiques.
6.2 Planifie des tâches avec les minuteries systemd
Systemd sépare le travail de sa planification. Une unité de service décrit la commande à exécuter. Une unité de minuterie décrit quand la lancer. Par défaut, backup.timer active backup.service, en utilisant le nom de base commun pour relier les deux unités.
Écris le service et la planification calendaire
Place ces unités système dans /etc/systemd/system/ :
# backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Type=oneshot convient à un script qui s’exécute une fois et se termine. Utilise un chemin de commande absolu et rends le script exécutable avec un shebang Bash. La minuterie fournit la planification :
# backup.timer
[Unit]
Description=Run backup.service daily at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
OnCalendar fait correspondre des dates et des heures. Ici, le caractère générique dans la date accepte chaque jour. Persistent=true permet le rattrapage après une période d’inactivité de la minuterie : si au moins une exécution calendaire a été manquée, il lance le service une fois à la réactivation. Il ne rejoue pas chaque exécution manquée.
Charge et active la minuterie
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Recharge la configuration après avoir créé ou modifié des fichiers d’unité. enable --now démarre immédiatement la minuterie et l’active pour les prochains démarrages. Activer uniquement le service ne crée pas de planification. Teste le travail séparément avec sudo systemctl start backup.service.
Choisis entre l’heure et le temps écoulé
| Paramètre | Planification |
|---|---|
OnCalendar=Mon..Fri *-*-* 09:00:00 | En semaine à 09 h 00 |
OnCalendar=*:0/15 | Minutes 0, 15, 30 et 45 de chaque heure |
OnBootSec=10min | Dix minutes après le démarrage |
OnUnitActiveSec=1h | Une heure après la dernière activation du service |
Les expressions calendaires peuvent utiliser daily pour minuit chaque jour ou weekly pour le lundi à minuit. Vérifie une expression avec systemd-analyze calendar "Mon..Fri 09:00" pour voir son interprétation et sa prochaine occurrence.
Les deux derniers paramètres sont des minuteries monotones : elles mesurent le temps écoulé depuis un événement. Combine-les pour obtenir une première exécution après le démarrage, puis des activations toutes les heures. Persistent=true s’applique aux minuteries calendaires ; il n’ajoute pas de rattrapage calendaire aux minuteries monotones.
Examine séparément la planification et les résultats
systemctl list-timers affiche les prochaines et les dernières activations. systemctl status backup.service affiche le résultat du service et journalctl -u backup.service affiche sa sortie et ses erreurs. Une prochaine exécution affichée prouve qu’une planification est active, pas que la tâche précédente du script a réussi.
Les minuteries disposent d’une plage de déclenchement. AccuracySec vaut par défaut une minute ; AccuracySec=1s réduit la plage de regroupement. RandomizedDelaySec ajoute volontairement un délai aléatoire pour répartir le travail entre les machines. Ces paramètres ne garantissent pas une seconde de démarrage exacte lorsque le système est chargé.
Exécute la minuterie d’un utilisateur
Les fichiers d’unité utilisateur se trouvent dans ~/.config/systemd/user/, et les commandes utilisent systemctl --user, notamment daemon-reload, enable --now et list-timers. Un gestionnaire utilisateur fonctionne normalement pendant la session de cet utilisateur. Un administrateur peut activer sa persistance avec loginctl enable-linger username pour le garder disponible sans connexion.
Cron nécessite une ligne temporelle compacte et fonctionne sans systemd. Les minuteries ajoutent un résultat de service et un journal, le rattrapage calendaire et davantage de contrôle. Aucun des deux ne charge normalement ~/.bashrc ; les deux nécessitent des scripts qui fonctionnent avec des chemins explicites et sans invites interactives.
Points clés
- Le service indique quoi exécuter ; la minuterie indique quand.
- Recharge les unités modifiées et active le
.timeravec--now. - Les minuteries calendaires suivent l’heure ; les minuteries monotones mesurent le temps depuis des événements.
Persistent=truerattrape une fois les tâches calendaires manquées à la réactivation.- Vérifie à la fois la prochaine activation de la minuterie et l’état et le journal du service.
- Les minuteries utilisateur nécessitent un gestionnaire utilisateur actif, avec persistance pour les exécutions sans session.
Scripts shell : exemples
1Enregistre un compte rendu de dossier réutilisable
9 étapes
- 1IntroductionRassemble une tâche répétée au même endroit
Tu vérifies souvent où tu te trouves, listes le contenu d’un dossier et affiches un message de fin. Enregistrer les commandes permet de répéter leur ordre.
Un script est un fichier texte lu par un interpréteur. Tu vas créer un petit compte rendu, sélectionner Bash explicitement et l’exécuter dans un shell fils. Le nom, le droit d’exécution et l’emplacement du fichier répondent chacun à une question différente sur son lancement.
- 2ExempleÉcris les commandes dans l’ordre
Enregistre ceci sous le nom
folder-report.shdans un éditeur de texte brut :#!/bin/bash pwd ls echo "Report finished"Le shebang sélectionne Bash lorsque le fichier est exécuté directement. Le commentaire explique la tâche mais ne s’exécute pas. Bash exécute ensuite
pwd,lsetechodans cet ordre. La terminaison.shaide le lecteur à reconnaître le fichier ; elle ne sélectionne pas l’interpréteur. - 3DéfiVérifie ce qui sélectionne le langage
Un collègue remplace la première ligne par
#!/bin/shet ajoute ensuite[[ ... ]]. Le nom du fichier se termine toujours par.sh. Pourquoi peut-il échouer ?---reveal---
Le shebang sélectionne
sh, qui peut êtredashet ne pas comprendre le[[ ... ]]de Bash. L’extension ne choisit pas le langage. Rétablis un shebang Bash pour les fonctionnalités de Bash, avec#!au tout début de la première ligne. - 4ExplicationLis d’abord le fichier avec Bash
Exécute
bash folder-report.sh. Cette commande lance Bash et lui transmet le fichier de script lisible ; le droit d’exécution sur le script n’est pas nécessaire. L’interpréteur choisi est déjà Bash, donc le shebang ne fait pas ce choix.Tu devrais voir un chemin, une liste et le message « Report finished ». Les chemins relatifs utilisés par les commandes du script sont résolus à partir de son répertoire de travail, et non automatiquement à partir du dossier du fichier de script.
- 5ExempleAutorise l’exécution directe
Ajoute le droit d’exécution pour le propriétaire et exécute le chemin exact :
chmod u+x folder-report.sh ./folder-report.sh./désigne le répertoire courant. L’exécution directe utilise le shebang du fichier. Si le fichier est lisible mais pas exécutable, la commandebashprécédente peut fonctionner alors que cette commande échoue avec « Permission denied ». Les droits et la sélection de l’interpréteur sont deux aspects distincts du lancement. - 6ConseilTrouve le script par son nom
Saisir
folder-report.shsans barre oblique demande à Bash de rechercher dans le PATH. Le répertoire courant ne figure normalement pas dans cette liste.Un répertoire bin personnel te permet d’exécuter le script depuis d’autres dossiers lorsqu’il figure dans le PATH. Examine
echo "$PATH"et utilisecommand -v folder-report.shpour voir quel exécutable ce nom sélectionne. Si une ancienne copie apparaît en premier dans le PATH, modifier une copie plus récente ailleurs ne changera pas ce que ce nom exécute. - 7DéfiConserve un changement de répertoire dans le bon shell
Le script commence maintenant par
cd /var/log. Après la fin de./folder-report.sh, ton terminal s’est-il déplacé à cet endroit ? Comment un fichier de paramètres pourrait-il le déplacer ?---reveal---
Le script exécuté fonctionne dans un shell fils, donc son changement de répertoire ne déplace pas le terminal parent. Exécuter un fichier dans le shell courant avec
source ./settings.shy exécute ses commandes et peut changer le répertoire de cette session. Cette méthode utilise le langage du shell courant. - 8DéfiDiagnostique le lancement avant de modifier les commandes
Un compte rendu lisible fonctionne avec
bash folder-report.sh. L’exécution directe renvoie « Permission denied » et la saisie de son seul nom renvoie « command not found ». Quels sont les deux problèmes de lancement à vérifier ?---reveal---
Vérifie le droit d’exécution du script pour l’exécution directe. Puis vérifie le PATH ou utilise son chemin explicite avec
./pour le trouver. Un shebang Bash valide sélectionne l’interpréteur, mais ne peut pas accorder de droits ni placer le fichier dans le PATH. - 9RécapitulatifUn lancement comporte plusieurs choix distincts
Le fichier contient la suite de commandes. L’interpréteur lit son langage, les droits autorisent l’exécution directe et le PATH ou une barre oblique permet de localiser le fichier.
Un script exécuté fonctionne dans un shell fils. Un fichier de paramètres exécuté dans le shell courant fonctionne dans le shell déjà ouvert, donc ses affectations et ses changements de répertoire peuvent rester dans cette session.
2Construis un nom de compte rendu daté sans perdre les espaces
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionSuis une valeur jusqu’à une commande
- 2ExempleStocke une destination composée de plusieurs mots
- 3LienTransmets le paramètre à un processus fils
- 4DéfiSépare un nom de son suffixe
- 5ExemplePréserve le chemin stocké
- 6DéfiChoisis entre texte fixe et texte variable
- 7ExempleRécupère une date pour le nom
- 8ExempleCalcule avant d’insérer la valeur
- 9DéfiRepère où la fraction est perdue
- 10DéfiCombine le chemin et la valeur récupérée
- 11RécapitulatifDistingue les trois fonctions
3Empêche une recherche échouée de produire un compte rendu déclaré réussi
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionConsidère le résultat comme une partie de la tâche
- 2ExempleRepère l’échec masqué en amont
- 3Point cléFais en sorte que le pipeline indique son échec
- 4DéfiEnregistre le code de retour qui compte
- 5ExempleTraite explicitement le travail qui a échoué
- 6ExplicationChoisis entre vérification syntaxique et traçage de l’exécution
- 7ExplicationLis les options de gestion des erreurs comme des contrôles distincts
- 8DéfiExplique pourquoi ce script continue
- 9DéfiTiens le programme appelant informé
- 10RécapitulatifLis à la fois les données et le résultat
4Examine les fichiers entrants et lis leurs enregistrements
15 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLaisse chaque type de donnée choisir l’étape suivante
- 2ExempleChoisis un test pour le type du chemin
- 3ExplicationCompare les valeurs de la bonne façon
- 4DéfiInterprète la négation d’un test sur un fichier
- 5ExempleSélectionne une action avec le résultat d’une commande
- 6DéfiSuis des seuils qui se recoupent
- 7ExplicationFais correspondre un mot d’action avec case
- 8ExempleTraite un fichier par passage dans une boucle sur un motif
- 9DéfiExplique le cas d’un dossier vide
- 10ConseilChoisis une limite numérique variable
- 11ExempleLis un enregistrement sans découper ses espaces
- 12DéfiConserve le dernier enregistrement sans saut de ligne
- 13LienAttends sans vérifier en continu
- 14DéfiDiagnostique un total qui reste à zéro
- 15RécapitulatifAdapte la structure aux données
5Accepte des fichiers en entrée et signale un échec partiel
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionInclus les données d’entrée dans l’appel de la commande
- 2ExempleExamine les limites des arguments de l’appel
- 3ExplicationConsomme l’option initiale
- 4DéfiConserve un argument vide dans le nombre
- 5ExempleRejette un appel sans fichier en entrée
- 6ExplicationChoisis une valeur par défaut seulement pour une donnée facultative
- 7ExempleVérifie l’opération de lecture elle-même
- 8DéfiGarde la trace de l’échec précédent
- 9DéfiArrête l’analyse avant un nom de fichier commençant par un trait d’union
- 10RécapitulatifDonne aux commandes réutilisables un contrat fiable
6Planifie un compte rendu et vérifie sa dernière exécution
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionNe planifie que le travail disposant de toutes ses données d’entrée
- 2ExempleLis une entrée de crontab personnelle
- 3DéfiSuis un pas en minutes au changement d’heure
- 4ConseilDonne une destination de sortie à la tâche
- 5LienDistingue une exécution manquée d’une exécution échouée
- 6ExemplePlace le travail dans un service
- 7ExemplePlace l’heure dans la minuterie correspondante
- 8ExplicationCharge les modifications et active la planification
- 9DéfiVérifie le résultat ainsi que la prochaine heure
- 10ExplicationCompte le temps depuis un événement si nécessaire
- 11DéfiChoisis le rattrapage après une période d’arrêt
- 12RécapitulatifExamine séparément la planification et la tâche
Scripts shell : QCM
Série 1 : Lis et exécute de petits scripts Bash10 Questions Pratiques
Question 1 sur 10
[[ ... ]] de Bash, mais sa première ligne est #!/bin/sh. Sur cette machine, sh est dash. Quelle première ligne sélectionne l’interpréteur voulu ?Afficher la réponseMasquer la réponse
#!/bin/bash indique à Linux d’utiliser Bash lorsqu’il exécute le fichier. Le shebang actuel sélectionne dash, qui ne prend pas en charge [[ ... ]]. Ajouter le mot « bash » après /bin/sh lancerait toujours sh.Question 2 sur 10
Afficher la réponseMasquer la réponse
bash audit.sh lance l’interpréteur et lui demande de lire le fichier, donc le droit d’exécution sur le script n’est pas nécessaire. ./audit.sh tente d’exécuter directement le fichier et nécessite donc ce droit. Exécuter un fichier dans le shell courant y lancerait ses commandes, mais source bash audit.sh désigne le mauvais fichier.Question 3 sur 10
label="west side", quels arguments printf '<%s>\n' "$label" met-il en forme ?Afficher la réponseMasquer la réponse
printf reçoive la valeur. Un développement sans guillemets produirait deux mots ; des guillemets simples autour du développement produiraient le littéral $label.Question 4 sur 10
file="shift notes.txt". Comment doit-il copier ce seul fichier dans le répertoire existant saved ?Afficher la réponseMasquer la réponse
$file est découpé en « shift » et « notes.txt », donc cp reçoit deux noms sources. Les guillemets simples conservent littéralement les caractères $file et ne substituent pas le chemin stocké.Question 5 sur 10
Afficher la réponseMasquer la réponse
$? contient le code de retour de la commande la plus récente, donc l’affectation immédiate stocke 7. $# compte au contraire les arguments positionnels et ne peut pas décrire la commande qui a échoué. N’exécute aucune commande entre-temps avant d’enregistrer le résultat, car une nouvelle commande remplacerait le code que tu veux préserver.Question 6 sur 10
archive existe et désigne un répertoire. Quels sont les résultats de [ -f archive ] et [ -d archive ], dans cet ordre ?Afficher la réponseMasquer la réponse
-f exige un fichier ordinaire existant, tandis que -d exige un répertoire existant. Le répertoire échoue donc au premier test et réussit le second. L’existence seule ne rend pas les deux tests vrais : -e testerait l’existence générale sans exiger l’un de ces types particuliers.Question 7 sur 10
Qu’affiche ce code ?
used=14
limit=20
percent=$(( used * 100 / limit ))
if [ "$percent" -ge 60 ]; then
used=$(( used + 2 ))
elif [ "$percent" -ge 70 ]; then
used=$(( used + 5 ))
fi
echo "$used"
Afficher la réponseMasquer la réponse
used, ce qui donne 16. Bash ignore ensuite la branche elif même si son seuil correspondrait aussi. Ajouter 5 ou appliquer les deux mises à jour revient à oublier qu’une chaîne if ne sélectionne que la première branche dont le test réussit.Question 8 sur 10
./label.sh "East Wing" report.txt. Que valent $# et $2 ?Afficher la réponseMasquer la réponse
report.txt est le deuxième. $# vaut donc 2 et $2 vaut report.txt. Le nom du script appartient à $0 et est exclu du nombre ; compter les deux mots du nom entre guillemets donnerait à tort trois arguments.Question 9 sur 10
dir=${1:-/srv/logs}. Il est appelé avec un argument qui est une chaîne vide entre guillemets. Quelle valeur est affectée ?Afficher la réponseMasquer la réponse
:- choisit la valeur par défaut lorsque le paramètre est non défini ou vide, donc un premier argument explicitement vide utilise /srv/logs. L’argument existe toujours dans la liste positionnelle, mais sa valeur vide satisfait la condition de la valeur par défaut. La forme :? signalerait au contraire une erreur pour cette donnée.Question 10 sur 10
25 4 * * * /home/rae/bin/audit.sh ?Afficher la réponseMasquer la réponse
Série 2 : Suis les valeurs, les enregistrements et les planifications10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
/bin/bash^M: bad interpreter, mais /bin/bash existe. Quelle modification du fichier corrige le problème indiqué ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
site ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
left=$(( 29 % 6 )) affecte-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
done de fermeture dans un script. Quelle commande peut détecter ce problème de syntaxe sans exécuter le script ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
[ 06 = 6 ] et [ 06 -eq 6 ], dans cet ordre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
a.csv et late batch.csv, tous deux des fichiers ordinaires. Quelles valeurs sont utilisées dans for f in *.csv; do echo "$f"; done ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Un fichier contient oak, un saut de ligne, puis elm sans saut de ligne final. Quel nombre est affiché ?
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < trees.txt
echo "$count"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
./task.sh -v "blue room" output.txt, le script exécute shift. Que valent maintenant $1 et $# ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
*/25 10-12 * * * s’exécute-t-il et quand a lieu sa dernière exécution ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
inventory.timer ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Suis les données dans un script complet10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
zone=west. Le fichier settings.sh ne contient que zone=east. Le terminal exécute bash settings.sh, puis source ./settings.sh, puis bash -c 'echo "${zone:-unset}"'. La variable n’a jamais été exportée. Qu’affiche la dernière commande ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
name=archive, qu’affiche echo "${name}_ready" ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
completed=18 et total=32. Quel résultat entier produit $(( completed * 100 / total )) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Le fichier absent.log n’existe pas. Quel code de retour parvient au programme appelant ?
#!/bin/bash
set -o pipefail
grep NOTICE absent.log | wc -l
status=$?
echo "Count ended"
exit "$status"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Qu’affiche ce script ?
set -e
false || echo "Handled"
echo "Next"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
*) doit-il suivre les motifs d’action nommés ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Le répertoire courant ne contient que les fichiers ordinaires draft one.jpeg, final.jpeg et notes.txt. Quelle est la sortie ?
count=0
for f in *.jpeg; do
[ "$f" = final.jpeg ] && continue
echo "${f%.jpeg}.jpg"
count=$(( count + 1 ))
done
echo "$count"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
until [ -f /tmp/upload.ready ]; do sleep 3; done. Le fichier ordinaire existe déjà avant le début de la boucle. Combien de fois le corps s’exécute-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
status=0. Une donnée incorrecte définit status=1, puis une donnée ultérieure est traitée avec succès. Quelle fin indique que la demande est incomplète ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Diagnostique les données d’entrée, le déroulement et les périodes d’arrêt10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
weekly.sh en weekly, sans modification de son contenu ni de ses droits. Quel effet la perte de l’extension a-t-elle sur le choix de l’interpréteur par Linux à partir du shebang ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
export REGION=north, puis lance un script qui affecte REGION=south et se termine. Quelle valeur reste dans le parent ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
pattern="*.txt". Quel argument touch "$pattern" reçoit-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Que se passe-t-il dans ce script non interactif ?
set -eu
dest=
if [ -z "$dest" ]; then
dest=${2:-/srv/archive}
fi
echo "$dest"
Le script ne reçoit qu’un argument, input.txt.
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
La variable count contient 10 et le répertoire courant est accessible en écriture et ne contient aucun fichier nommé 4. Que se passe-t-il ?
if [ "$count" > 4 ]; then
echo "High"
else
echo "Low"
fi
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
case "$value" in [0-9]*) echo "Match" ;; *) echo "No" ;; esac. Que se passe-t-il pour value=8draft ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Qu’est-ce qui s’affiche ?
i=0
total=0
while [ "$i" -lt 4 ]; do
i=$(( i + 1 ))
[ "$i" -eq 2 ] && continue
total=$(( total + i ))
[ "$total" -gt 5 ] && break
done
echo "$i:$total"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
-v, une chaîne vide entre guillemets et "red room", dans cet ordre. Il exécute shift, puis for arg in "$@"; do echo "<$arg>"; done. Qu’est-ce qui s’affiche ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
0 11 9 * 2 /home/rae/bin/check.sh sélectionne-t-il dans cron ordinaire ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Persistent=true. Trois activations quotidiennes passent pendant que l’ordinateur est éteint. Quel rattrapage prévoit-elle lors de sa réactivation ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 5 : Combine protection des caractères, vérifications des échecs et données réutilisables10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Un terminal Bash se trouve dans /home/rae, avec le PATH /home/rae/bin:/usr/local/bin:/usr/bin:/bin. Des scripts Bash exécutables nommés scan existent dans les deux dossiers bin et dans le répertoire courant. Chacun ne contient qu’un shebang Bash et cd /srv/cache ; ce répertoire existe et est accessible. Quel fichier la première commande exécute-t-elle et quels chemins sont affichés ?
scan
pwd
source ./scan
pwd
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
a.txt et b.txt. Avec les paramètres par défaut de Bash pour le découpage et le développement des noms de fichiers, combien d’arguments de données printf '<%s>\n' $value met-il en forme après value="*.txt spare" ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
ready sur la sortie standard et warning sur la sortie d’erreur standard, puis réussit. Que stocke message=$(the_command) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Quel code de retour parvient au programme appelant ?
#!/bin/bash
false
saved=$?
true && echo "Handled"
exit $(( saved + 2 ))
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
set -u et a déjà affecté folder="". Il doit s’arrêter avec un diagnostic utile avant d’utiliser un dossier absent ou vide. Quel développement fournit cette vérification ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
"$text" a une longueur non nulle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
limit=3, quelles valeurs sont affichées par for i in {1..$limit}; do echo "$i"; done avec le développement ordinaire de Bash ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Quel nombre est affiché avec le comportement par défaut des pipelines Bash ? Le fichier contient trois lignes terminées par un saut de ligne.
count=5
cat tasks.txt | while IFS= read -r line; do
count=$(( count + 1 ))
done
count=$(( count + 2 ))
echo "$count"
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Un script analyse ses données d’entrée avec ce code, puis exige exactement deux arguments de fichiers. Après l’appel ./copy.sh -v -- "early notes.txt" -final.txt, combien d’arguments restent et que doit-il se passer ensuite ?
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
--) shift; break ;;
-*) echo "Unknown option" >&2; exit 2 ;;
*) break ;;
esac
done
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
/home/rae/.local/bin. Quelle modification corrige la différence probable ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Affectation
name=value, sans espaces autour du signe égal.name="Lee Kim" garde les deux mots ensemble comme une seule valeur stockée.Anacron
B
Bash
[[ ... ]] sélectionne Bash dans son shebang pour que sa syntaxe conditionnelle soit comprise.Boucle for
web1 web2 db1 exécute son corps une fois pour chacun des trois noms d’hôtes.Boucle until
Boucle while
read atteint la fin de fichier et signale un échec.Branche conditionnelle
break
C
case
Code de retour
grep -q distingue une correspondance, une absence de correspondance et un problème de lecture des données d’entrée.Code de retour du pipeline
pipefail modifie cette règle.grep échoue mais que le wc suivant compte avec succès une entrée vide.Commentaire
# au début d’un mot hors du texte entre guillemets.# Keep a copy for recovery explique pourquoi la copie de fichier qui suit est nécessaire.Comparaison de chaînes
Comparaison numérique
-eq et -gt, indépendamment de la longueur de leur texte.[ "$count" -ge 8 ] réussit pour un nombre stocké égal à 12.Compteur
count=0 peut augmenter une fois pour chaque ligne lue par une boucle.continue
cron
Crontab
crontab -l affiche la crontab de l’utilisateur courant pour permettre l’examen de ses planifications.D
Découpage en mots
cp.Développement arithmétique
$(( ... )) et insère la valeur calculée dans la commande."$(( count + 1 ))" en valeur entière suivante du compteur.Développement des accolades
{1..5} avant que Bash ne développe les variables de la commande.{1..$n} en une suite fondée sur la valeur stockée dans n.Développement des noms de fichiers
*.log en noms de fichiers correspondants distincts avant le début d’une boucle for.Développement des variables
"${file}_old" en « report_old » lorsque file contient « report ».Division entière
$(( 7 / 2 )) produit 3 alors que le quotient exact est de 3,5.Droit d’exécution
chmod u+x job.sh permet au propriétaire d’essayer d’exécuter ./job.sh.E
elif
Environnement minimal
errexit
set -e de Bash, qui quitte sur les échecs non traités tout en autorisant certains contextes qui testent le code de retour d’une commande.if qui échoue de sélectionner sa branche else au lieu de terminer le script.Exécution dans le shell courant
./settings.sh dans le shell courant charge ses affectations de variables directement dans la session Bash ouverte.Exécution en court-circuit
&& ou || s’exécute.cd /data || exit 1 arrête les commandes dépendantes après l’échec d’un changement de répertoire.exit
exit 2 après une erreur d’utilisation pour que le programme appelant reçoive un résultat d’échec.Exportation
F
Fin de fichier
read de Bash signale un échec lorsqu’il rencontre cette situation.read signale un échec.Fin de ligne
^M.G
Gestionnaire de signal
Guillemets doubles
echo "Home: $HOME *" permettent le développement du chemin personnel tout en conservant l’astérisque.Guillemets simples
echo '$HOME' affiche les caractères « $HOME » au lieu d’un chemin de répertoire personnel.I
IFS
read préserve les espaces en début et en fin de ligne.IFS= read -r line conserve les espaces aux extrémités de chaque enregistrement lu dans le fichier d’entrée.Indicateur d’échec
Interpréteur
#!/usr/bin/python3 lit du code Python au lieu de commandes Bash.Itération
J
Journal
journalctl -u backup.service affiche les messages de la tâche de sauvegarde.M
Message d’utilisation
Minuterie calendaire
OnCalendar=Mon..Fri 09:00 sélectionne les matins de semaine à 09 h 00.Minuterie monotone
Mot-clé conditionnel
[[ de Bash commence une construction de test du shell avec ses propres règles d’analyse et de correspondance de motifs.[[ permet d’utiliser [[ $name == *.log ]] sans découpage du nom en mots.Motif universel
* à la fin d’un bloc case Bash.*) signale les commandes inconnues après la vérification des sous-commandes nommées.N
Négation
[ ! -d "$p" ] accepte aussi bien un fichier ordinaire qu’un chemin inexistant.Nombre d’arguments
$#, sans compter le nom utilisé pour l’appel../greet.sh Ana "Lee Kim", car le nom entre guillemets est un seul argument.nounset
set -u de Bash, qui traite le développement d’une variable non définie comme une erreur dans un script non interactif.O
Option
-v peut activer des messages supplémentaires avant que le script traite les noms de fichiers restants.P
Paramètre positionnel
$1 et les rangs après neuf nécessitent des accolades.${10} récupère le dixième argument sans ajouter un zéro à $1.Pas d’incrémentation cron
*/45 dans les minutes sélectionne 0 et 45, puis repart à 0 à l’heure suivante.PATH
job.sh dans le PATH, mais suit le chemin explicite du répertoire courant dans ./job.sh.Persistance du gestionnaire utilisateur
pipefail
grep peut faire échouer tout le pipeline.Processus fils
Protection des caractères
"$file" préserve « monthly report.txt » comme un seul argument lors de la copie du fichier.R
read
read -r -p "Name: " name demande un nom et conserve les barres obliques inverses dans le texte saisi.Reste
%.$(( 17 % 5 )) est 2 parce que trois groupes complets de cinq utilisent 15.S
Script shell
Shebang
#! qui désigne l’interpréteur que Linux doit utiliser pour exécuter un script.#!/bin/bash commence dès le premier caractère, avant tout commentaire ou toute ligne vide.shift
-v, le mot suivant de la ligne de commande devient $1 pour l’analyseur d’options.Sortie d’erreur standard
>&2 reste visible lorsque la sortie standard va dans un fichier.Substitution de commande
$(command).today=$(date +%F) récupère une date à utiliser dans un nom de fichier de sauvegarde.Suppression de suffixe
${f%.jpeg}.T
Test sur un fichier
[ -d "$src" ] accepte un répertoire source mais rejette un fichier ordinaire.Traçage de l’exécution
bash -x révèle un argument source vide transmis à une commande de copie de fichier.Transmission des arguments
"$@" pour préserver les limites de chaque argument."$@" garde une donnée vide et un nom composé de plusieurs mots comme arguments distincts.U
Unité de minuterie
backup.timer établit la planification du service de sauvegarde.Unité de service
backup.service définit le script activé par la minuterie de sauvegarde correspondante.V
Valeur par défaut
${1:-/var/log} pour un argument absent ou vide.Validation
Variable
city stocke « Lisbon » après city=Lisbon, donc echo "$city" peut l’afficher.Variable d’environnement
Vérification syntaxique
bash -n détecte un done manquant avant que la boucle puisse exécuter des commandes.À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.