Chapitre 12 : Le Bourne Shell
Toutes les commandes que nous nous avons vu jusqu’à présent sont standards et ne sont pas propres à un shell particulier. Avant d’entamer la programmation shell elle-même, il nous faut voir quelques options détaillées du shell par défaut, le Bourne Shell.
Fichier de configuration
Le Bourne Shell dispose d’un fichier de configuration chargé et exécuté lors du lancement du shell. Il est généralement placé dans le répertoire par défaut de l’utilisateur et se nomme .profile.
PATH=/home/oracle/bin:$ORACLE_HOME/bin:/usr/sbin:/usr/local/bin:/usr/bin:/sqlbt/datatools/obacktrack/bin:/usr/opt/networker/bin:.
#export NLS\_SORT=BINARY
#. /usr/local/bin/oraenv
umask 022
Commandes internes et externes
Une commande peut être interne ou externe. Une commande interne est une commande directement incluse et interprétée par le shell, sans passer par un quelconque exécutable. Un exemple est la commande cd.
Une commande externe est un exécutable que le shell recherchera dans une liste de chemins prédéfinis, le PATH, puis exécutera en tant que processus fils.
D’autres mécanismes existent, comme les fonctions et les alias (hors Bourne Shell), que nous aborderons plus tard.
Herescript
La redirection « << » n’a pas été abordée car elle est particulière. Elle permet l’utilisation des Herescripts (Script ici). Un herescript permet la saisie d’un texte jusqu’à un point donné et l’envoi de son résultat à une commande ou un filtre. Les redirections classiques sont aussi autorisées. Après le « << » on indique une chaîne définissant la fin de saisie, par exemple ici end.
$ tr "[a-z]" "[A-Z]" << end
> bonjour les amis
> ceci est un exemple
> de herescript
> end
BONJOUR LES AMIS
CECI EST UN EXEMPLE
DE HERESCRIPT
Ouverture de canaux
Les canaux standards sont au nombre de trois et numérotés de 0 à 2. Ainsi 0< équivaut à < et 1> à >. La commande exec permet d’ouvrir sept autres canaux numérotés de 3 à 9. On a donc en tout dix canaux.
On peut envisager, dans le cadre de traitements, de sortir certains résultats par le canal 3, d’autres par le 4, et ainsi de suite. Les canaux ouvert le sont en entrée et en sortie.
$ exec num_canal > fichier_ou_reunion
$ exec 3>dump.log
$ ls -l >&3
$ cat dump.log
total 5716
-rw-r--r-- 1 oracle system 0 Aug 14 15:55 dump.log
-rwxr-xr-x 1 oracle dba 0 Aug 12 11:05 fic1
-rw-r--r-- 4 oracle system 0 Aug 12 11:05 fic2
-rw-r----- 1 oracle dba 0 Aug 12 11:05 fic3
-rw-r--r-- 1 oracle system 33 Aug 12 12:03 fic4
-rw-r--r-- 4 oracle system 0 Aug 12 11:05 hardlink2_fic2
-rw-r--r-- 4 oracle system 0 Aug 12 11:05 hardlink3_fic2
-rw-r--r-- 4 oracle system 0 Aug 12 11:05 hardlink_fic2
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic1 -> fic1
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic2 -> fic2
-rw-r--r-- 1 oracle system 252 Aug 12 14:30 liste
-rw-r--r-- 1 oracle system 234 Aug 13 10:06 liste2
-rw-r--r-- 1 oracle system 4829707 Aug 14 11:23 liste_ls
-rw-r--r-- 1 oracle system 974408 Aug 13 15:20 ls.txt
-rw-r--r-- 1 oracle system 4010 Aug 13 09:10 mypass
-rw------- 1 oracle system 106 Aug 14 11:09 nohup.out
drwxr-xr-x 2 oracle dba 8192 Aug 12 11:21 rep1
drwxr-xr-x 2 oracle system 8192 Aug 14 14:16 rep2
drwxr-xr-x 2 oracle system 8192 Aug 14 14:17 seb1
drwxr-xr-x 2 oracle system 8192 Aug 14 14:17 seb2
-rw-r--r-- 1 oracle system 2564 Aug 13 13:45 toto.tar.gz
-rw-r--r-- 1 oracle system 402 Aug 13 09:33 users
Tous ce qui sera écrit dans le canal 3 sera écrit dans le fichier dump.log. On peut ensuite fermer le canal en le réunissant avec un pseudo-canal (canal de fermeture -).
$ exec 3>&-
Groupement de commandes
Nous avons vu que le chaînage de commande est possible avec le ;. Il est aussi possible de grouper les commandes. Quand on exécute les commandes suivantes :
$ uname -a ; pwd ; ls -l >resultat.txt &
seule la dernière commande est exécutée en tâche de fond et seul son résultat est redirigé dans le fichier resultat.txt.
Une solution serait :
$ uname -a >resultat.txt & ; pwd >> resultat.txt & ; ls -l >> resultat.txt &
[1] 18232
[2] 18238
[3] 18135
C’est une solution complexe et qui ne marchera pas toujours. De plus même si les commandes sont lancées séquentiellement, elles tournent toutes en parallèle et c’est la première finie qui écrira en premier dans le fichier. La solution consiste en l’utilisation des parenthèses ( ).
$ (uname -a ; pwd ; ls -l) > resultat.txt &
[1] 18239
$
[1] Done ( uname -a; pwd; ls -l ) > resultat.txt
Dans ce cas, toutes les commandes placées entre les parenthèses sont lancées par un sous-shell, qui va ensuite exécuter les commandes précisées séquentiellement telles qu’indiquées. Ainsi la redirection concerne l’ensemble des commandes et rien n’empêche de lancer ce sous-shell en arrière-plan. On distingue bien d’ailleurs un seul PID 18239 lors de l’exécution des commandes.
Une seconde possibilité est l’utilisation des accolades {...}. Dans ce cas aucun sous-shell n’est exécuté, et si une commande interne (cd ou autre) est exécutée, elle concerne le shell actif. L’accolade fermante doit être placée juste après un ;.
$ { uname -a; pwd; ls -l; } > resultat.txt
Liaison et exécution conditionnelle
En plus du chaînage classique, les commandées peuvent être liées et exécutées de façon conditionnelle. La condition d’exécution d’une commande est la réussite ou non de la précédente.
Chaque commande une fois exécutée sort un code retour, généralement 0 si tout s’est bien passé, 1 ou 2 en cas d’erreur. Le shell peut récupérer cette valeur par la variable $#.
(Les variables seront abordées plus en détail dans le chapitre de Programmation Shell).
$ ls
...
$ echo $?
0
Les caractères « && » et « || » permettent d’effectuer une exécution conditionnelle.
commande1 && commande2
commande1 || commande2
La commande située après « && » sera exécutée uniquement si la commande précédente a retourné 0 (réussite). La commande située après « || » ne sera exécutée que si la commande précédente a retourné autre chose que 0.
$ cat liste
Produit objet prix quantites
souris optique 30 15
dur 30giga 100 30
dur 70giga 150 30
disque zip 12 30
disque souple 10 30
ecran 15 150 20
ecran 17 300 20
ecran 19 500 20
clavier 105 45 30
clavier 115 55 30
carte son 45 30
carte video 145 30
$ (grep "souris" liste && echo "Souris trouvee") || echo "Souris introuvable"
souris optique 30 15
Souris trouvee
$ (grep "memoire" liste && echo "Memoire trouvee") || echo "Memoire introuvable"
Memoire introuvable
Photo récupérée de bashlogo.com