Travaux Dirigés de aas
2. La portée en Shell
Le Shell n'est pas seulement un langage de commandes mais un petit environnement d'exécution paramétré par des variables prédéfinies et des fichiers consultés automatiquement. Comme dans tout langage formel, la portée des variables est un problème non trivial, particulièrement aigu dans le contexte d'un système multi-tâches. La question concerne aussi les alias, les fonctions Shell et les paramètres positionnels qui désignent des arguments différents selon leur occurrence dans les scripts, en particulier dans les fichiers d'initialisation, au nombre de trois : Voici donc une collection d'exercices illustrant les subtilités du Shell sur cette question.

1 Le profil et le délogeur

Au minimum, existe un profil général dans /etc/profile exécuté pour tous les utilisateurs (les administrateurs y mettaient autrefois des annonces générales, mais avec le démarrage automatique des gestionnaires de fenêtres, le message n'a plus le temps d'être lu, il vaut mieux recourir au courrier).

Ensuite, le processus login lance l'exécution du profil spécifique de l'utilisateur, situé dans son répertoire principal, sous le nom de .bash_profile et exécutera à la fin .bash_logout (s'ils sont absents, .profile et .logout seront tentés). Le rôle du profil se réduit aujourd'hui à déterminer l'aspect de la session : on peut y affecter la variable SHELL indiquant l'interprète souhaité (/bin/bash en général) ou lancer le gestionnaire de fenêtres.

Exercice : sachant que la commande tty renvoie le terminal utilisé (/dev/*tty* ou /dev/console) et que le serveur de fenêtre X-window se lance par la commande xinit, écrire un profil lançant celui-ci si l'on se connecte de la console et qu'il ne l'est pas déjà.


Obtenir un formulaire de soumission de comptes rendus

2 L’environnement

L'environnement .bashrc doit définir au moins les variables PATH et PS1 (le prompt) pour assurer un minimum de confort. Par exemple :

PATH=/bin :/usr/bin$ PS1='% '$ export PATH $

La directive export est indispensable pour que les scripts aient accès à la valeur de PATH: c'est l'équivalent d'une déclaration de globalité, tandis que le prompt est spécifique à la session. Implicitement, l'exécution de ce script s'est faite par :

source .bashrc

ou l'équivalent :

. .bashrc

car autrement la valeur de PS1 n'aurait duré que le temps d'exécution du script.

Exercice : la commande man arg donne la page de manuel décrivant la commande arg. Pour trouver cette page de manuel dans l'arborescence, man exploite la variable MANPATH semblable à PATH dans sa syntaxe et sa sémantique. En général, le nom des répertoires y figurant est man, convention reprise par la plupart des utilitaires Unix installables à volonté quelque part dans l'arboresence /usr. En utilisant la commande find, initialiser dans votre .bashrc la variable .MANPATH à la liste des répertoires (séparés par des deux-points) de nom man trouvé dans l'arboresence /usr.

Le fichier .bashrc met également en place les options générales fournies par la commande set (dénonciation ou non des variables indéfinies, de fichiers implicitement détruits par une redirection etc).

Signalons enfin le fichier .inputrc qui configure l'éditeur de lignes du Shell. Faire man readline pour redéfinir les touches, le complément automatique des noms de fichiers etc. En fait, readline est une bibliothèque indépendante de Shell, reprise par de nombreux utilitaires Unix pour garantir l'homogénéité de l'ergonomie du système.


Obtenir un formulaire de soumission de comptes rendus

3 Les paramètres positionnels

A chaque exécution d'un script Shell, les variables $1 $2 ... sont affectées aux arguments qui suivent le nom du script. En outre, il existe :

Exercice : soit la session :

ls -l$
total 40$
-rw-r-----  1 esj  www      0  7 Oct 11:18 encore un fichier de mac$
-rw-r-----  1 esj  www  16197  7 Oct 11:31 td.tex$
-rwxr-xr--  1 esj  www     33  7 Oct 11:31 de$
et supposant que le script de contienne for i in * ; do ls -l "i"; done dire ce que fera :
de "encore un fichier de mac" td.tex de$
de *
de "*"
La commande shift permet d'ignorer le premier paramètre, en renumérotant les suivants à partir de 1. Exercice : écrire un script prenant en argument un répertoire et des fichiers, et qui placent ceux-ci dans celui-là.
Obtenir un formulaire de soumission de comptes rendus

4 Un cas à part

En plus de la conditionnelle standard, le Shell offre la construction

case valeur in motif1) instructions   ;  ; ... motifN) instructions   ; esac

La valeur est comparée aux différents motifs et le premier qui correspond à la valeur déclenche les instructions correspondantes, les autres étant ignorées. Les motifs peuvent contenir des caractères spéciaux  ; en particulier, le motif * correspond à toutes les valeurs. Ils peuvent aussi contenir le caractère | qui permet de regrouper plusieurs motifs devant exécuter les mêmes instructions.

Ecrire un script recevant en argument un nom de fichier, et selon son extension (les caractères qui suivent le point le plus à droite), lui applique un utilitaire supposé le reconnaître, soit par exemple :

Si l'extension n'est pas reconnue, exécuter le fichier s'il est exécutable, sinon envoyer une erreur dans le flux des erreurs.


Obtenir un formulaire de soumission de comptes rendus

5 Une autre boucle

La structure while condtion   ;do instructions   ; done est assez peu utilisée dans un langage comme Shell peu tourné vers les applications numériques. Toutefois, elle est intéressante à utiliser en conjonction avec l'instruction read, qui lit une ligne sur le flux d'entrée et affecte à chacune des variables données en argument le mot correspondant sur la ligne (et à la dernière variable, tous les mots restants). Ainsi

echo foo bar et encore ça | read a b c

affecte foo à a, bar à b et et encore ça à c. Toutefois, read n'est pas utile dans ce contexte car les variables a, b, c n'ont de valeur que dans le processus n'exécutant que read. Une utilisation plus intéressante est de placer read comme condition de while: elle retournera 0 lorsque le flux sera tari, et sinon permettra à while d'accéder aux variables affectées.

Application : sachant que /etc/passwd contient des lignes formées de mots séparés par des deux-points (:) indiquant successivement : le login, le mot de passe, l'UID, le GID, le nom, le répertoire principal et enfin le shell de tous les utilisateurs de la machine, écrire un script qui, prenant en argument un login, retourne le nom de l'utilisateur (indication : utiliser la commande tr pour remplacer les deux-points).


Obtenir un formulaire de soumission de comptes rendus

6 Reconnaître les options

Lors d'un appel de shell-script, tout ce qui suit le nom du script est considéré comme des arguments. Pour traiter à part les chaînes de deux caractères formée d'un tiret puis d'une lettre, et même accepter l'abréviation -abc comme équivalent de -a -b -c, bash fournit la construction getopts que l'on peut passer comme condition de while selon le schéma suivant :

while getopts 'abc' variable   ; do ... done

Si les paramètres du script contient les deux chaînes -a et -b, ou la chaine -ab, la boucle sera exécutée deux fois, la variable indiquée prenant successivement les valeurs a puis b ou l'inverse selon l'ordre des arguments). En outre, dans le premier argument de getopts, chaque lettre peut être suivie d'un deux-point, stipulant que cette option exige un opérande qui sera alors affecté à la variable OPTARG. Un deux-point initial provoque l'affectation de la variable indiquée à la valeur   ? pour les options ne figurant pas dans le premier argument (autrement le message option invalide sera émis). Enfin, la variable OPTIND indique l'indice du premier paramètre qui n'est pas une option. Ecrire un script équivalent de ls, mais acceptant ses options habituelles en majuscules.


Obtenir un formulaire de soumission de comptes rendus

logo-spip E. Saint-James & F. Kordon - Master Informatique - UPMC Valid XHTML 1.0!
Calculé le 19 janvier 2021 à 10h06min