Projet

Général

Profil

Petit precis de shell » Historique » Version 20

Julien Enselme, 12/08/2013 18:46
La fonction test : syntaxe

1 1 Julien Enselme
Le shell est un langage assez particulier qu'on ne connait pas forcément en arrivant à centrale et qu'on a pas forcément l'occasion de beaucoup pratiquer. Le but de ce document est de rappeler les quelques bases du langage et de fournir quelques solutions standard à des problèmes courants afin que le nouveau membre du club Drupal ne soit pas désemparé et puisse comprendre les scripts. Il ne se veut en aucun cas un cours/tuto complet et exhaustif.
2 14 Julien Enselme
3
{{toc}}
4 1 Julien Enselme
5 3 Julien Enselme
h1. Quelques rappels d'Unix
6
7
Le langage shell est le langage de script qui vient par défaut avec _tous_ les Unix. En effet, même si désormais d'autres interpréteurs plus modernes sont désormais répandus (bash, csh, zsh, etc.), ils ont tous conservé la compatibilité avec le shell.
8
9
Comme pour la plupart des langages de script, il existe deux façons d'exécuter des instructions shell :
10
11
* directement dans l'interpréteur
12
* dans un script shell
13
14
Pour lancer un interpréteur shell, rien de plus simple : lancer un terminal (graphique ou tty). Et oui, le shell comprend toutes les commandes Unix que vous avez vues en début d'année (pwd, cd, cp). Vous pouvez donc les réutiliser _telles quelles_ dans vos scripts et utiliser son bon terminal pour faire des boucles, des conditions et j'en passe.
15
16 1 Julien Enselme
h1. Les bases du shell
17 3 Julien Enselme
18 4 Julien Enselme
Il est très important de comprendre et de garder à l'esprit qu'en shell tout est :
19
20
* chaîne de caractères (y compris les nombres) ! Entrez @echo 1 + 1@ dans le terminal pour vous en convaincre.
21
* commande et que donc elles peuvent prendre des arguments (cela s'éclaircira plus tard)
22
23
h2. Syntaxe de base
24
25
Les commandes s'écrivent soit :
26
27 6 Florent Torregrosa
* les unes à la suite des autres séparées par ; (peu recommandé)
28 4 Julien Enselme
* séparées les unes des autres par un saut de ligne
29
30
Chaque commande peut prendre des arguments de deux types :
31
32
* les arguments courts (l, r, h pour @ls@ par exemple) qui sont passés comme suit : @CMD -ARG@
33
* les arguments longs (recursive pour @rsync@ par exemple) qui se passent comme ceci : @CMD --ARGUMENT@
34
35
Il est évidement possible de passer plusieurs arguments à une même commande.
36
37 6 Florent Torregrosa
{{tip(Certains arguments existent sous une forme courte et une forme longue. Consulter le manuel de la commande pour plus de détails. Le manuel contient également la liste complète des arguments supportés par une commande.)}}
38 4 Julien Enselme
39
{{note(Certains commandes ne respectent pas la convention énoncée ce-dessus. Leurs arguments long se passent avec un seul - (find en est un exemple))}}
40
41 5 Julien Enselme
h2. Valeurs de retour des commandes et exception
42
43 6 Florent Torregrosa
Une fois qu'une commande s'est exécutée, elle renvoie une valeur de retour afin "d'informer" l'utilisateur. Cette valeur permet en effet de savoir si la commande s'est exécutée correctement. Voici les valeurs de retour possibles et leur signification :
44 5 Julien Enselme
45
* 0 : tout va bien
46
* 1 : erreur
47
* 2 : erreur grave
48
49 6 Florent Torregrosa
Vous pouvez vous aussi utiliser ces valeurs de retour. Par défaut, un script qui se complète correctement retourne 0. Mais vous pouvez (par exemple si un utilisateur tente d'exécuter un script qui nécessite un argument sans) retourner un autre code d'erreur avec la commande @exit@. Il suffit de lui passer le code qu'elle doit retourner. Votre script s'arrêtera alors avec le code d'erreur spécifié.
50 5 Julien Enselme
51 13 Julien Enselme
h2. Exécuter une commande
52
53
S’il est facile dans les cas simples d’exécuter une commande, dès lors qu’en shell tout est chaîne de caractères, si vous voulez affecter la sortie d’une commande à une variable, vous ne pouvez pas simplement faire @var=CMD@ car var va alors valoir la chaîne CMD.
54
55
Pour obtenir le résultat souhaité vous devez placer CMS entre backquote `` ou entre $(…). Par exemple : @var=`ls`@ ou @var=$(ls)@.
56
57
La syntaxe `` serait plus ancienne et supportée partout. La syntaxe $(…) serait plus récente et présente l’avantage de pouvoir imbriquer les commandes sans ambiguïté.
58
59 4 Julien Enselme
h2. Conditions et itérations
60 7 Julien Enselme
61 11 Julien Enselme
h3. Conditions if … else …
62 7 Julien Enselme
63
La structure générale d'une condition est la suivante :
64
65
<pre>
66
<code>
67
if QQC
68
then
69
    CMDS
70
else
71
    CMDS
72
fi
73
</code>
74
</pre>
75
76
Le @else@ est facultatif. Il est aussi possible de regrouper @if@ et @then@ en une seule ligne comme ceci : @if QQC ; then@.
77
78
La question que vous devriez avoir est que mettre à la place de @QQC@. Il y a deux possibilités :
79
80
* la fonction @test@
81
* une commande
82
83 11 Julien Enselme
h4. La fonction test
84 7 Julien Enselme
85
{{important(Dans toute la suite, il faudra faire très *attention aux espaces*)}}
86
87
La fonction @test@ s'utilise en général comme suit : @if [ ARGS ]@
88
89
*IMPORTANT* : La syntaxe *@if [[ ARGS ]]@* n'est valide qu'avec *bash*. Voir [[Petit_precis_de_shell#Différences notables avec bash|Différences notables avec bash]]
90
91 10 Julien Enselme
Pour faire un test, il suffit ensuite de passer les bons arguments à la commande. Par exemple, pour tester si une chaîne est vide : @if [ -z $chaine ]. Si l’argument a besoin de deux paramètres pour fonctionner, mettre un paramètre de chaque côté de celui-ci. Par exemple, pour faire un test d’égalité de chaîne de caractères : @CHAINE1 = CHAINE2@.
92
93
On peut aussi combiner les arguments avec des ET et des OU avec les options @-a@ et @-o@. Le caractère "!" permet de faire une négation.
94
95
Voir ci-dessous pour la liste complète.
96
97
{{important(En shell, tout est chaîne de caractère. Bien faire attention au type que l’on veut tester (chaîne ou nombre))}}
98
99 20 Julien Enselme
#Tests sur les chaînes de caractères
100 10 Julien Enselme
|_. Argument |_. Signification |
101
| = | égalité |
102 1 Julien Enselme
| -z | chaîne vide |
103 10 Julien Enselme
| -n | chaîne non vide |
104 20 Julien Enselme
#Tests sur les nombres
105 10 Julien Enselme
|_. Argument |_. Signification |
106
| -eq | égalité |
107
| -ne | non égalité |
108
| -lt | strictement plus petit |
109
| -gt | strictement plus grand |
110
| -ge | plus grand ou égal |
111
| -le | plus petit ou égal |
112
113 7 Julien Enselme
h4. Test avec une commande
114 1 Julien Enselme
115 10 Julien Enselme
Comme indiqué précédemment, une commande qui s’exécute correctement est considérée comme vrai. Ainsi, il est tout a fait possible, par exemple, pour savoir si on arrive à se connecter à un serveur mysql de faire simplement : @if mysql -h HOST -u asso -pTATA@.
116
117
{{tip(Parfois vous pourrez rencontrer des problèmes. Pensez alors à donner cette commande en argument à la fonction test)}}
118 7 Julien Enselme
119 12 Julien Enselme
h3. Boucles while/until
120
121
La structure générale est la suivante :
122
<pre>
123
while QQC
124
do
125
    CMD
126
done
127
</pre>
128
129
Il est possible de regrouper @while QQC@ et le @do@ en @while QQC ; do@. Le QQC peut être remplacer par exactement les mêmes choses que pour la condition. Se référer à cette section pour les précisions.
130
131
Le shell propose également le mot clé @until QQC@ qui fait une action jusqu’à ce que QQC soit réalisé.
132
133
h3. Boucle for
134
135
L’utilisation de la boucle for en shell ressemble à celle de python. La structure générale est la suivante :
136
<pre>
137
for var in `CMD`
138
do
139
   CMD
140
done
141
</pre>
142
143
La variable _var_ va alors prendre une à une les valeurs données par CMD. Par exemple, @for file in `ls`@ la variable var va prendre tour à tour le nom de tous les fichiers et dossiers donnés par la commande @ls@.
144
145
Vous pouvez également utiliser for pour boucler d’un nombre à un autre avec la syntaxe : @for i in {2..9}@
146
147 16 Julien Enselme
{{warning(2..9 semble être du bash. à revoir)}}
148
149 18 Julien Enselme
h1. Paramètres de scripts
150
151
h2. Généralités
152
153
Un script peut prendre des paramètres qui ont le même but que les arguments d'une fonction : lui passer des informations. Un paramètre peut être :
154
155
* une variable
156
* une chaîne de caractère (donc un nombre, en shell on ne fait pas la distinction). Si la chaîne à passer en paramètre contient plusieurs mots séparés par des espaces, ne pas oublier de la mettre entre ' ou ".
157
158
{{tip(Si une varaible coucou contient la chaîne 'salut', alors '$coucou toi' sera compris _$coucou toi_ tandis que "$coucou toi" sera interprété en _salut toi_)}}
159
160
Les paramètres se passent à un script comme ceux d'une commande. Ils sont ensuite disponibles dans l'ordre avec des numéros :
161
162
* le premier : $1
163
* le deuxième : $2
164
* et ainsi de suite
165
166
{{important(Le shell ne supporte *que* 9 paramètres)}}
167
168
h2. Les paramètres spéciaux
169
170
* $0 : contient le nom du script
171
* $# : contient le nombre d'arguments passés au script
172
{{important(Le paramète $0 est toujours passé au script. $# est donc toujours supérieur ou égale à 1)}}
173
* $* : l'ensemble des paramètres en un seul argument A DETAILLER
174
* $? : le code de retour de la dernière commande invoquée
175
* $$ : le PID du shell qui exécute le script
176
* $! : le PID du dernier processus lancé en arrière plan
177
* $@ : L'ensemble des arguments, un argument par paramètre A DETAILLER
178
179
h2. Les commandes shift et set
180
181
La commande @set@ permet d'affecter les paramètres. Ainsi @set bonjour salut bonsoir@ va initialiser $1 à bonjour, $2 à salut et $3 à bonsoir. Les paramètres spéciaux $#, $* et $@ sont mis à jour.
182
183
La commande @shift@ permet de décaler les variables. Ainsi, si après @shift@ $1 prend la valeur de $2 et ainsi de suite. @shift n@ décale les arguments de n
184
185 17 Julien Enselme
h1. Les fonctions
186
187
Il est tout à fait possible de définir en shell des fonctions que ce soit dans un script ou un terminal. La syntaxe est la même.
188
189
<pre>
190
nom_de_la-foncion () {
191
  CMDS
192
}
193
</pre>
194
195
Les fonctions ainsi créées s'utilise comme les commandes classiques et leurs arguments se manipulent exactement comme ceux d'un script. Voir [[Petit_precis_de_shell#Les-redirections-de-flux|la section dédiée]]. Il faut néanmoins faire attention à deux points :
196
197
* la portée des varibles
198
* la valeur de retour
199
200
Par défaut, les varialbes définies dans la fonction resteront accessibles une fois la fonction exécutée. De même les varables définies auparavant restent acessibles dans la fonction. *Ces varaibles sont donc globales par défaut.* Pour qu'une variables soit locale, il faut utiliser le mot clé @local@ lors de sa définition. Par exemple : @local nom=clubdrupal@.
201
202
Pour qu'une fonction en bash retourne une valeur comme vous pouvez en avoir l'habitude dans d'autre langage, il faut utiliser la commande @echo@. En effet, il n'existe pas d'instruction @return@ puisque par défaut les variables sont globales. Il faut alors faire très attention. Par exemple avec la fonction suivante :
203
204
<pre>
205
<code class="bash">
206
x_files () {
207
  top_secret=`dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" "`
208
  echo $top_secret
209 8 Julien Enselme
}
210
</code>
211
</pre>
212 9 Julien Enselme
213
* Si on fait @x_files@ on affiche à l'écran le contenu de @$top_secret@
214
* Si on fait @passwd=`x_files`@ on affecte à la variable @$passwd@ le contenu de @$top_secret@
215
216
h1. Les redirections de flux
217 1 Julien Enselme
218 19 Julien Enselme
Les flux représentent les sorties générées par les commandes. Par défaut, il existe deux flux :
219
220
* Le flux standard
221
* Le flux d'erreur
222
223
Par défaut, il s'affiche sur la sortie standard (votre écran pour être bref). Il peut s'avérer intéressant d'envoyer ces flux ailleurs (logs, le néant, etc.). Pour cela, on va les rediriger. Par exemple pour rediriger la sortie de @ls@ dans un fichier nommé toto, on fait :
224
225
* @ls > toto@
226
* *ou*
227
* @ls >> toto@
228
229
La première solution efface le contenu du fichier puis écrit dedans. La seconde ajoute la sortie à la fin du fichier. On a ici redirigé le flux standard. Pour rediriger les flux d'erreurs, on utilise les symboles @2>@ ou @2>>@. On peut évidemment combiner les deux : @ls -R / > mes_fichiers.txt 2> errors.log@ avec toutes les variantes possibles.
230
231
Pour rediriger l'erreur au même endroit que l'entrée, on peut faire @ls > toto 2> toto@ ou plus simplement @ls > toto 2>&1@.
232
233
Pour rediriger une sortie vers le néant, on l'envoie dans /dev/null.
234 9 Julien Enselme
235 8 Julien Enselme
h1. Importer une configuration
236
237
@. config-file.sh@
238
239
h1. Mode debug
240 1 Julien Enselme
241
Lorsqu’un de vos scripts shell bug il peut être difficile de savoir d’où vient le problème. Heureusement, le shell propose un mode débug qui vous dit pour chaque ligne comment elle est exécuté, avec quels paramètres (les variables sont remplacées par leur contenu).
242
243
Il suffit de faire : @sh -x SCRIPT@
244
245 8 Julien Enselme
h1. Différences notables avec bash
246 15 Julien Enselme
247 18 Julien Enselme
* RANDOM
248
* let
249
* &> et |&
250
* le nombre de paramètres
251
252 1 Julien Enselme
h1. Divers
253
254 7 Julien Enselme
h2. Différences entre la sortie de ls et de find
255 9 Julien Enselme
256
ls : chemin relatif ; find auei : chemin absolu
257 18 Julien Enselme
258
h1. Sources et liens externes
259
260
* http://www.commentcamarche.net/faq/5444-bash-les-parametres