Fonctions en BASH
Vous avez sûrement déjà perdu patience à retaper « bêtement » des instructions dans votre terminal. Bien qu’existent des raccourcis (par exemple, fléche du haut) pour récupérer des instructions précédentes, ici est proposé une solution plus générale et modulable : les fonctions en language BASH. Elles constituent un moyen efficace pour effectuer des commandes groupées qui doivent être répétées.
Le format
Le format d’une fonction en BASH est le suivant :
func(){
<commands>
}
Les arguments
Il est bien sûr possible de passer des arguments à une fonction. Les arguments de la fonction doivent être fournis directement après le nom de la fonction. Par exemple,
func arg1 arg2
A l’intérieur des fonctions, les arguments sont accessibles par “$1”, “$2”, …
ATTENTION: les arguments ne doivent pas être indiqués dans les parenthèses lors de la définition de la fonction.
Boucle FOR
Au sein de ces fonctions, il est possible d’inclure bon nombre de structures d’instructions bien connues. Les boucles FOR, par exemple, suivent la syntaxe suivante :
for var in <list>
do
<commands>
done
Ici, les éléments de la liste sont assignés, les uns après les autres, à la variable var
. A chaque itération, les commandes entre do
et done
sont executées.
REMARQUE: Ici les listes ont été introduites. En bash, une liste est initialisée en enfermant entre paranthèses ses éléments, séparés d’un espace.
array = (input1.txt input2.txt input3.txt)
Elles suivent la syntaxe habituelle des listes. Pour référer à la liste en entier ou à un élément particulier de celle-ci:
${array[0]} -> input1.txt
${array[1]} -> input2.txt
${array[2]} -> input3.txt
${array[*]} -> input1.txt input2.txt input3.txt
L’exemple
Voici un exemple concret lié à la réalisation de notre projet. La fonction timing
prenant comme argument le nombre de threads de calcul indique le temps d’exécution (ainsi que d’autres mesures de performance) de l’exécutable fact
pour différents fichiers d’entrée.
timing(){
make fact
./fact -N "$1" input1.txt output.txt
array=(input1.txt input2.txt input3.txt)
for i in ${array[*]}
do
echo Time : "$i" with "$1" threads
command time -f "Real elapsed time [s] \t %e \nMax portion of RAM occupied [Kbytes] \t %M\n" ./fact -N "$1" "$i" output.txt
done
make clean
}
Quelques commentaires :
- Avant de prendre des mesures sur l’exécutable
fact
, il est recommandé de l’executer une première fois. (Fact se trouve alors dans la cache du filesystem). Ceci permet d’éviter que systématiquement la première exécution soit plus lente que les autres. - La commande
command
permet d’écraser le mot clétime
fourni par le shell bash au profit de l’utilitairetime
davantage modulable. Petit test:type time
VStype command type
dans votre terminal.
En pratique
Il y a en pratique deux “voies” pour définir des fonctions en BASH.
Dans le terminal
Il est possible de définir directement une fonction dans votre terminal. Neanmoins, ceci implique que votre fonction ne sera pas sauvegardée à long terme.
Dans un fichier .sh
Il est donc préférable de l’insérer dans un fichier .sh, autrement appelé script. Reprenant l’exemple ci-dessus, voici le contenu du fichier timing.sh
(situé dans le même répertoire que votre Makefile) où la fonction timing
est executée 3 fois avec un nombre de threads de calcul croissant.
#!/bin/bash
timing(){
make fact
./fact -N "$1" input1.txt output.txt
array=(input1.txt input2.txt input3.txt)
for i in ${array[*]}
do
echo Time : "$i" with "$1" threads
command time -f "Real elapsed time [s] \t %e \nMax portion of RAM occupied [Kbytes] \t %M\n" ./fact -N "$1" "$i" output.txt
done
make clean
}
timing 1
timing 2
timing 4
PRATIQUE: Voici shellcheck, un analyseur statique (comme cppcheck en C), qui permet l’obtention d’un feedback interactif de vos scripts.
Pour exectuer le fichier timing.sh
:
./timing.sh
ASTUCE: Il est probable que vous aillez à modifier les permissions (ici, d’execution) du fichier créé. Il suffit d’entrer la commande chmod +x timing.sh
pour rendre l’exécution du fichier .sh accessible. La commande ls -l
permet de vérifier la bonne exécution de l’opération.
POUR INFO: A noter que les fichiers .sh
ne sont pas propre au shell BASH (d’ailleurs, il a fallu indiquer à ce fichier le shell à utiliser #!/bin/bash
). Il existe un type de fichier propre au BASH: les fichiers .bashrc
qui permettent une configuration permanente (par default) de votre shell BASH (voir, par exemple, l’article de Diego Houtart ). A noter aussi le fichier .profile
qui d’une certaine manière initialise et particularise votre environnement dans le shell BASH.
Bien entendu, ceci n’est qu’une introduction aux fonctions en BASH et celle-ci n’attend qu’à être approfondie. Je vous invite vivement à vous documenter pour dénicher peut-être d’autres astuces facilitant encore davantage l’exécution de commandes.