« Script bash » : différence entre les versions
(Ajout d'un while en une seule ligne.) |
(Aération du code + numérotation des lignes de quelques balises de code + correction de la variable utilisée dans la structure case + corrections de syntaxe + ajout d'une méthode sur les opérations arithmétiques) |
||
(2 versions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 2 : | Ligne 2 : | ||
Le [[shell bash]] peut être utilisé pour exécuter des scripts qui peuvent servir à automatiser des tâches manuellement ou de [[cron|façon programmé]]. | Le [[shell bash]] peut être utilisé pour exécuter des scripts qui peuvent servir à automatiser des tâches manuellement ou de [[cron|façon programmé]]. | ||
{{info|Les concepts de programmation ne seront pas abordés dans cette documentation. Cette dernière a seulement pour but de rassembler de la syntaxe pour une réutilisation rapide de code | {{info|Les concepts de programmation ne seront pas abordés dans cette documentation. Cette dernière a seulement pour but de rassembler de la syntaxe pour une réutilisation rapide de code ''Bash''.}} | ||
=Commandes basiques= | =Commandes basiques= | ||
Afficher un message | Afficher un message | ||
<source lang="bash"> | <source lang="bash"> | ||
echo "Mon message" | echo "Mon message" | ||
</source> | </source> | ||
Afficher un message sans retour chariot" | Afficher un message sans retour chariot" | ||
<source lang="bash"> | <source lang="bash"> | ||
echo -n "Quel est votre âge ? : " | echo -n "Quel est votre âge ? : " | ||
</source> | </source> | ||
Affectation de variable | Affectation de variable | ||
<source lang="bash"> | <source lang="bash"> | ||
maVarable=maValeur | maVarable=maValeur | ||
</source> | </source> | ||
Appel de variable | Appel de variable | ||
<source lang="bash"> | <source lang="bash"> | ||
echo $maVariable | echo $maVariable | ||
</source> | </source> | ||
Lire une entrée clavier et remplir une variable avec | Lire une entrée clavier et remplir une variable avec | ||
<source lang="bash"> | <source lang="bash"> | ||
read maVariable | read maVariable | ||
</source> | </source> | ||
Mettre le résultat d'une commande bash dans une variable | Mettre le résultat d'une commande bash dans une variable | ||
<source lang="bash"> | <source lang="bash"> | ||
chercheFichiers=`find / -type f -iname "*.txt" | wc -l` | chercheFichiers=`find / -type f -iname "*.txt" | wc -l` | ||
</source> | </source> | ||
Mettre le résultat d'une commande bash dans une variable en la rendant silencieuse | Mettre le résultat d'une commande bash dans une variable en la rendant silencieuse | ||
<source lang="bash"> | <source lang="bash"> | ||
chercheFichiers=`find / -type f -iname "*.txt" | wc -l` 2>/dev/null | chercheFichiers=`find / -type f -iname "*.txt" | wc -l` 2>/dev/null | ||
Ligne 44 : | Ligne 56 : | ||
==Exemple== | ==Exemple== | ||
< | |||
<source lang="bash"> | |||
utilisateur@machine:/$ ls / | |||
bin etc initrd.img.old lost+found opt run sys var | |||
boot home lib media proc sbin tmp vmlinuz | |||
dev initrd.img lib64 mnt root srv usr vmlinuz.old | |||
utilisateur@machine:/$ echo $? | |||
0 | |||
utilisateur@machine:/$ ls /titi | |||
ls: impossible d'accéder à '/titi': Aucun fichier ou dossier de ce type | |||
utilisateur@machine:/$ echo $? | |||
</ | 2 | ||
</source> | |||
On peut également, lors d'une instruction qui est sensé terminer le script, renvoyer un code de retour via la commande: | On peut également, lors d'une instruction qui est sensé terminer le script, renvoyer un code de retour via la commande: | ||
Ligne 64 : | Ligne 77 : | ||
=Les tests= | =Les tests= | ||
Sous Linux, tout est fichier. Lors de l'exécution d'un script, il peut être utile de connaître le type ou l'existence d'un ficher (un dossier est un fichier) avant d'exécuter une action. Les tests seront donc appréciables en combinaison d'une structure conditionnelle ou d'une boucle. | Sous ''Linux'', tout est fichier. Lors de l'exécution d'un script, il peut être utile de connaître le type ou l'existence d'un ficher (un dossier est un fichier) avant d'exécuter une action. Les tests seront donc appréciables en combinaison d'une structure conditionnelle ou d'une boucle. | ||
Les tests s'effectuent via la commande <source lang="bash" inline>test</source>. Cette commande renvoi un code de retour en fonction de l'issue du test. Lorsque <source lang="bash" inline>test</source> est utilisé dans une structure conditionnelle ou une boucle, seul son argument est utilisé, l'appel à la commande étant implicite. | Les tests s'effectuent via la commande <source lang="bash" inline>test</source>. Cette commande renvoi un code de retour en fonction de l'issue du test. Lorsque <source lang="bash" inline>test</source> est utilisé dans une structure conditionnelle ou une boucle, seul son argument est utilisé, l'appel à la commande étant implicite. | ||
Ligne 137 : | Ligne 150 : | ||
=Structures conditionnelles= | =Structures conditionnelles= | ||
Les structures conditionnelles permettent d'effectuer des instruction en fonction de conditions. Combinés aux tests vus précédemment, elles vont | Les structures conditionnelles permettent d'effectuer des instruction en fonction de conditions. Combinés aux tests vus précédemment, elles vont permettre un comportement évolutif du script en fonction des événements qui lui seront présentés. | ||
Il existe deux grand type de structure conditionnelle en | Il existe deux grand type de structure conditionnelle en ''Bash''. | ||
==La structure IF, ELIF, ELSE== | ==La structure IF, ELIF, ELSE== | ||
Ligne 159 : | Ligne 172 : | ||
==La structure CASE== | ==La structure CASE== | ||
La syntaxe est similaire à un couple switch/case en PHP. Très utile lorsqu'elle est utilisé avec un <source lang="bash" inline>read</source>, elle est plus adapté qu'un enchaînement de <source lang="bash" inline>elif</source> lorsqu'il s'agit de contrôler une entré utilisateur en fonction d'un choix proposé. Elle se présente comme suit : | La syntaxe est similaire à un couple ''switch/case'' en ''PHP''. Très utile lorsqu'elle est utilisé avec un <source lang="bash" inline>read</source>, elle est plus adapté qu'un enchaînement de <source lang="bash" inline>elif</source> lorsqu'il s'agit de contrôler une entré utilisateur en fonction d'un choix proposé. Elle se présente comme suit : | ||
<source lang="bash" line> | <source lang="bash" line> | ||
case variableRead in | case $variableRead in | ||
OUI|Oui|oui|o|YES|Yes|yes|y) | OUI|Oui|oui|o|YES|Yes|yes|y) | ||
INSTRUCTION1 | INSTRUCTION1 | ||
Ligne 177 : | Ligne 191 : | ||
=Boucles= | =Boucles= | ||
Les boucles permettent d'exécuter un ensemble d'instruction de façon répété en fonction d'une condition. Il existe deux types de boucle en | Les boucles permettent d'exécuter un ensemble d'instruction de façon répété en fonction d'une condition. Il existe deux types de boucle en ''Bash''. | ||
==La boucle FOR== | ==La boucle FOR== | ||
Ligne 184 : | Ligne 198 : | ||
===Première syntaxe=== | ===Première syntaxe=== | ||
Avec cette syntaxe, <source lang="bash" inline>for</source> parcours le contenu d'une liste et se termine lorsque tout les éléments on été parcourus. | Avec cette syntaxe, <source lang="bash" inline>for</source> parcours le contenu d'une liste et se termine lorsque tout les éléments on été parcourus. | ||
<source lang="bash" line> | <source lang="bash" line> | ||
for variable in liste_valeurs; do | |||
instruction(s) | |||
done | |||
</source> | </source> | ||
====Exemple==== | ====Exemple==== | ||
On peut utiliser cette façon de faire pour obtenir un comportement similaire à la commande ls. | On peut utiliser cette façon de faire pour obtenir un comportement similaire à la commande <source lang="bash" inline>ls</source>. | ||
<source lang="bash" line> | <source lang="bash" line> | ||
for i in * | for i in * | ||
Ligne 198 : | Ligne 214 : | ||
done | done | ||
</source> | </source> | ||
Dans cet exemple, l'étoile est remplacée par tous les fichiers du répertoire courant, la boucle va donc donner successivement comme valeur à la variable i tous ces noms de fichier. Le corps de la boucle affichant la valeur de la variable i, le nom de tous les fichiers du répertoire courant sont affichés successivement. | |||
Dans cet exemple, l'étoile est remplacée par tous les fichiers du répertoire courant, la boucle va donc donner successivement comme valeur à la variable ''i'' tous ces noms de fichier. Le corps de la boucle affichant la valeur de la variable ''i'', le nom de tous les fichiers du répertoire courant sont affichés successivement. | |||
===Seconde syntaxe=== | ===Seconde syntaxe=== | ||
Cette façon de faire se rapproche plus du comportement standard de la boucle <source lang="bash" inline>for</source> dans d'autre langages. Ainsi, elle prend 3 arguments. Un compteur qui sera incrémenté à chaque itération; la condition à remplir; l'incrémentation en elle même sous forme d'une opération arithmétique. | Cette façon de faire se rapproche plus du comportement standard de la boucle <source lang="bash" inline>for</source> dans d'autre langages. Ainsi, elle prend 3 arguments. Un compteur qui sera incrémenté à chaque itération; la condition à remplir; l'incrémentation en elle même sous forme d'une opération arithmétique. | ||
<source lang="bash" line> | <source lang="bash" line> | ||
for ((i=0 ; 10 - $i ; i++)) | for ((i=0 ; 10 - $i ; i++)) | ||
Ligne 211 : | Ligne 229 : | ||
==La boucle WHILE et UNTIL== | ==La boucle WHILE et UNTIL== | ||
La boucle <source lang="bash" inline>while</source> exécute un bloc d'instructions tant qu'une certaine condition est satisfaite, lorsque cette condition devient fausse la boucle se termine. Cette boucle permet donc de faire un nombre indéterminé de tours de boucle, voire infini si la condition ne devient jamais fausse. | La boucle <source lang="bash" inline>while</source> exécute un bloc d'instructions tant qu'une certaine condition est satisfaite, lorsque cette condition devient fausse la boucle se termine. Cette boucle permet donc de faire un nombre indéterminé de tours de boucle, voire infini si la condition ne devient jamais fausse. | ||
<source lang="bash"> | |||
<source lang="bash" line> | |||
while [ $valeur1 -ne $valeur2 ] | while [ $valeur1 -ne $valeur2 ] | ||
do | do | ||
Ligne 218 : | Ligne 237 : | ||
done | done | ||
</source> | </source> | ||
La boucle <source lang="bash" inline>until</source> est identique à la boucle <source lang="bash" inline>while</source> sauf qu'elle est exécutée tant que la condition est fausse. | La boucle <source lang="bash" inline>until</source> est identique à la boucle <source lang="bash" inline>while</source> sauf qu'elle est exécutée tant que la condition est fausse. | ||
En dehors d'un script, cette boucle peut exécuter une tache [https://stackoverflow.com/questions/1289026/syntax-for-a-single-line-bash-infinite-while-loop directement dans le shell] pour aller à l'encontre du merdier ambiant sous Linux qui veux tout automatiser sans jamais médiatiser le nom des processus qui casses les couilles (donc bonne chance pour le tuer). Par exemple, sur ma Debian Testing, un adaptateur USB/Ethernet en ''eth0'' n'avait de cesse de se dé-configurer tout seul (et pour le coup ce n'était pas la faute de [[Network manager]]) alors que j'avais un réseau d'admin pour un Raspberry Pi dessus (c'était insupportable d'avoir la connexion SSH qui coupait toute les 10 secondes). Du coup, plutôt que de passer une heure à trouver l'origine de cette merde, un coup de ça: | En dehors d'un script, cette boucle peut exécuter une tache [https://stackoverflow.com/questions/1289026/syntax-for-a-single-line-bash-infinite-while-loop directement dans le shell] pour aller à l'encontre du merdier ambiant sous Linux qui veux tout automatiser sans jamais médiatiser le nom des processus qui casses les couilles (donc bonne chance pour le tuer). Par exemple, sur ma ''Debian Testing'', un adaptateur USB/Ethernet en ''eth0'' n'avait de cesse de se dé-configurer tout seul (et pour le coup ce n'était pas la faute de [[Network manager]]) alors que j'avais un réseau d'admin pour un Raspberry Pi dessus (c'était insupportable d'avoir la connexion ''SSH'' qui coupait toute les 10 secondes). Du coup, plutôt que de passer une heure à trouver l'origine de cette merde, un coup de ça : | ||
<source lang="bash"> | <source lang="bash"> | ||
while true; do ip a a 172.16.1.120/24 dev eth0 && ip l set eth0 up; sleep 1; done | while true; do ip a a 172.16.1.120/24 dev eth0 && ip l set eth0 up; sleep 1; done | ||
</source> | </source> | ||
et ta race le problème. | et ta race le problème. | ||
=Opérations arithmétiques= | |||
Comme dans tous langages, il est possible de réaliser des opérations mathématiques sur les nombres contenus dans les variables. Plusieurs syntaxes existes. | |||
Prenons une variable <source lang="bash" inline>cpt=1</source> et additionnons-là de un (cette valeur peut bien sûr être directement donnée ou sous forme d'une autre variable). | |||
<source lang="bash"> | |||
cpt=`expr $cpt + 1` | |||
</source> | |||
<source lang="bash"> | |||
cpt=$(expr $cpt + 1) | |||
</source> | |||
<source lang="bash"> | |||
cpt=$(($cpt + 1)) | |||
</source> | |||
==Source de la section== | |||
* https://tecadmin.net/bash-add-two-integers/ | |||
=Les fonctions= | =Les fonctions= | ||
<source lang="bash"> | |||
<source lang="bash" line> | |||
# déclaration dune fonction | # déclaration dune fonction | ||
maFonction() | maFonction() | ||
Ligne 241 : | Ligne 284 : | ||
</source> | </source> | ||
Ce qui donne le résultat suivant: | Ce qui donne le résultat suivant : | ||
<source lang="bash"> | <source lang="bash"> |
Dernière version du 26 novembre 2021 à 23:28
Le shell bash peut être utilisé pour exécuter des scripts qui peuvent servir à automatiser des tâches manuellement ou de façon programmé.
INFORMATION
Les concepts de programmation ne seront pas abordés dans cette documentation. Cette dernière a seulement pour but de rassembler de la syntaxe pour une réutilisation rapide de code Bash.Commandes basiques
Afficher un message
echo "Mon message"
Afficher un message sans retour chariot"
echo -n "Quel est votre âge ? : "
Affectation de variable
maVarable=maValeur
Appel de variable
echo $maVariable
Lire une entrée clavier et remplir une variable avec
read maVariable
Mettre le résultat d'une commande bash dans une variable
chercheFichiers=`find / -type f -iname "*.txt" | wc -l`
Mettre le résultat d'une commande bash dans une variable en la rendant silencieuse
chercheFichiers=`find / -type f -iname "*.txt" | wc -l` 2>/dev/null
Codes de retour
Toutes les commandes Linux retournent un code d'erreur compris entre 0 et 255.
Le code 0 retourne le drapeau vrai.
Les codes supérieurs à 0 sont des drapeaux faux. L'intérêt d'avoir plus de deux états est de pouvoir retourner un message d'erreur personnalisé en fonction de l'erreur du script.
Le code de retour de la dernière commande est stocké dans la variable $?
.
Exemple
utilisateur@machine:/$ ls /
bin etc initrd.img.old lost+found opt run sys var
boot home lib media proc sbin tmp vmlinuz
dev initrd.img lib64 mnt root srv usr vmlinuz.old
utilisateur@machine:/$ echo $?
0
utilisateur@machine:/$ ls /titi
ls: impossible d'accéder à '/titi': Aucun fichier ou dossier de ce type
utilisateur@machine:/$ echo $?
2
On peut également, lors d'une instruction qui est sensé terminer le script, renvoyer un code de retour via la commande:
exit NUM_CODE
Les tests
Sous Linux, tout est fichier. Lors de l'exécution d'un script, il peut être utile de connaître le type ou l'existence d'un ficher (un dossier est un fichier) avant d'exécuter une action. Les tests seront donc appréciables en combinaison d'une structure conditionnelle ou d'une boucle.
Les tests s'effectuent via la commande test
. Cette commande renvoi un code de retour en fonction de l'issue du test. Lorsque test
est utilisé dans une structure conditionnelle ou une boucle, seul son argument est utilisé, l'appel à la commande étant implicite.
Test sur des fichiers
Argument | Effet |
---|---|
FICHIER1 -nt FICHIER2 | Vérifie si FICHIER1 est plus récent que FICHIER2 (newer than) |
FICHIER1 -ot FICHIER2 | Vérifie si FICHIER1 est plus vieux que FICHIER2 (order than) |
-b | Vérifie si le fichier existe et si c'est un fichier spécial en mode bloc |
-c | Vérifie si le fichier existe et si c'est un fichier spécial en mode caractère |
-d | Vérifie si le fichier existe et si c'est un répertoire |
-e | Vérifie si le fichier existe (peu importe le type de fichier) |
-f | Vérifie si le fichier existe et si c'est un fichier ordinaire |
-g | Vérifie si le fichier existe et si son bit set-GID est positionné |
-G | Vérifie si le fichier existe et si il appartient au GID effectif de l'appelant |
-h ou -L | Vérifie si le fichier existe et si c'est un lien symolique |
-k | Vérifie si le fichier existe et si son bit collant (sticky) est positionné |
-O | Vérifie si le fichier existe et si il appartient à l'UID de l'appelant |
-p | Vérifie si le fichier existe et si c'est un tube nommé |
-r | Vérifie si le fichier existe et si il est lisible |
-s | Vérifie si le fichier existe et si il est de taille non nulle |
-S | Vérifie si le fichier existe et si c'est un socket |
-t | Vérifie si le descripteur de fichier FD est ouvert sur un terminal |
-u | Vérifie si le fichier existe et si son bit setuid est positionné |
-w | Vérifie si le fichier existe et si il est accessible en écriture |
-x | Vérifie si le fichier existe et si c'est exécutable (ou si il peut être parcouru dans le cas d'un répertoire) |
Test sur des valeurs
Argument | Équivalent PHP | Effet |
---|---|---|
-n | !empty() | La longueur de CHAÎNE est non nulle |
-z | empty() | La longueur de la CHAÎNE est nulle |
-eq | == | Test d'égalité |
-ne | != | Test d'inégalité |
-lt | < | Test d'infériorité absolut |
-le | <= | Test d'infériorité |
-gt | > | Test de supériorité absolut |
-ge | >= | Test de supériorité |
Structures conditionnelles
Les structures conditionnelles permettent d'effectuer des instruction en fonction de conditions. Combinés aux tests vus précédemment, elles vont permettre un comportement évolutif du script en fonction des événements qui lui seront présentés.
Il existe deux grand type de structure conditionnelle en Bash.
La structure IF, ELIF, ELSE
La syntaxe est similaire aux autres langages. Elle ce présente comme suit :
if [ OPTION_DE_TEST FICHIER_À_TESTER ]
then
INSTRUCTION1
INSTRUCTION2...
elif [ OPTION_DE_TEST FICHIER_À_TESTER ]
then
INSTRUCTION1
INSTRUCTION2
INSTRUCTION3...
else
INSTRUCTION1
fi
La structure CASE
La syntaxe est similaire à un couple switch/case en PHP. Très utile lorsqu'elle est utilisé avec un read
, elle est plus adapté qu'un enchaînement de elif
lorsqu'il s'agit de contrôler une entré utilisateur en fonction d'un choix proposé. Elle se présente comme suit :
case $variableRead in
OUI|Oui|oui|o|YES|Yes|yes|y)
INSTRUCTION1
INSTRUCTION2...
;;
NON|Non|non|n|NO|No|no)
INSTRUCTION1
INSTRUCTION2...
;;
*)
INSTRUCTION1...
;;
esac
Boucles
Les boucles permettent d'exécuter un ensemble d'instruction de façon répété en fonction d'une condition. Il existe deux types de boucle en Bash.
La boucle FOR
La boucle for permet de parcourir une liste de valeurs, elle effectue donc un nombre de tours de boucle qui est connu à l'avance. Elle supporte deux syntaxes.
Première syntaxe
Avec cette syntaxe, for
parcours le contenu d'une liste et se termine lorsque tout les éléments on été parcourus.
for variable in liste_valeurs; do
instruction(s)
done
Exemple
On peut utiliser cette façon de faire pour obtenir un comportement similaire à la commande ls
.
for i in *
do
echo $i
done
Dans cet exemple, l'étoile est remplacée par tous les fichiers du répertoire courant, la boucle va donc donner successivement comme valeur à la variable i tous ces noms de fichier. Le corps de la boucle affichant la valeur de la variable i, le nom de tous les fichiers du répertoire courant sont affichés successivement.
Seconde syntaxe
Cette façon de faire se rapproche plus du comportement standard de la boucle for
dans d'autre langages. Ainsi, elle prend 3 arguments. Un compteur qui sera incrémenté à chaque itération; la condition à remplir; l'incrémentation en elle même sous forme d'une opération arithmétique.
for ((i=0 ; 10 - $i ; i++))
do
echo $i
done
La boucle WHILE et UNTIL
La boucle while
exécute un bloc d'instructions tant qu'une certaine condition est satisfaite, lorsque cette condition devient fausse la boucle se termine. Cette boucle permet donc de faire un nombre indéterminé de tours de boucle, voire infini si la condition ne devient jamais fausse.
while [ $valeur1 -ne $valeur2 ]
do
INSTRUCTION1
INSTRUCTION2...
done
La boucle until
est identique à la boucle while
sauf qu'elle est exécutée tant que la condition est fausse.
En dehors d'un script, cette boucle peut exécuter une tache directement dans le shell pour aller à l'encontre du merdier ambiant sous Linux qui veux tout automatiser sans jamais médiatiser le nom des processus qui casses les couilles (donc bonne chance pour le tuer). Par exemple, sur ma Debian Testing, un adaptateur USB/Ethernet en eth0 n'avait de cesse de se dé-configurer tout seul (et pour le coup ce n'était pas la faute de Network manager) alors que j'avais un réseau d'admin pour un Raspberry Pi dessus (c'était insupportable d'avoir la connexion SSH qui coupait toute les 10 secondes). Du coup, plutôt que de passer une heure à trouver l'origine de cette merde, un coup de ça :
while true; do ip a a 172.16.1.120/24 dev eth0 && ip l set eth0 up; sleep 1; done
et ta race le problème.
Opérations arithmétiques
Comme dans tous langages, il est possible de réaliser des opérations mathématiques sur les nombres contenus dans les variables. Plusieurs syntaxes existes.
Prenons une variable cpt=1
et additionnons-là de un (cette valeur peut bien sûr être directement donnée ou sous forme d'une autre variable).
cpt=`expr $cpt + 1`
cpt=$(expr $cpt + 1)
cpt=$(($cpt + 1))
Source de la section
Les fonctions
# déclaration dune fonction
maFonction()
{ local varlocal="je suis la fonction"
echo "$varlocal"
echo "Nombres de paramètres : $#"
echo $1
echo $2
}
# appel de ma fonction
maFonction "Bonjour" "Monde!"
Ce qui donne le résultat suivant :
je suis la fonction
Nombres de paramètres : 2
Bonjour
Monde!
Source de la section
Sources
- https://www.gnu.org/software/bash/manual/bashref.html
- http://ss64.com/bash/test.html
- http://www.quennec.fr/trucs-astuces/syst%C3%A8mes/gnulinux/programmation-shell-sous-gnulinux/les-bases-de-la-programmation-shell/les-variables-r%C3%A9serv%C3%A9es-du-shell/code-de-retour-dune-commande
- https://fr.wikibooks.org/wiki/Programmation_Bash/Boucles