\chapter{Le Shell}\index{shell} \label{chap:shell} Le \texttt{shell} est le coquillage qui isole le MC/P\footnote{Master Control Program} des yusers. En gros, hein, je vais simplifier, et me limiter aux bricolages constructifs et/ou amusant. Il y aura du gore\index{gore} aussi, parce que le shell est à la fois un interpréteur de commande et un langage de programmation. Ces deux notions ont beaucoup de choses en commun, comme nous allons essayer de le voir. Certains qualifient le shell de « langage de glue », et c'est une image assez pertinente. Nous allons nous concentrer sur le \textsl{Bourne again shell} (aka \texttt{bash}\footnote{aka GNU/shell ?}) qui est un des plus répandus, du moins dans le monde Linux\index{Linux}. Mais il en existe d'autres : sh, ksh, ash, zsh, tthsh\dots Ce qui, bien entendu, pose quelques problèmes de compatibilité. Ou alors, il faut reste \textsc{posix}, mais c'est pour le moment une autre histoire. Parce que là, on est plutôt dans une optique « morefun » sur l'utilisation de nos machines. % ============================================================== \section{Interpréteur}\index{cli} Ceci est un prompt : \texttt{tth@redlady:\textasciitilde\$}. Son petit nom est \texttt{PS1}. On peut y mettre plein d'informations utiles et de \textsl{mises en forme} assez funky\footnote{Un peu de calme, fatalerrors !} permettant d'enhancer la reliability de votre UI/UX. Mais surtout il est là pour indiquer qu'il attend vos ordres, qu'il est prèt à interpréter vos lignes de commandes. \begin{verbatim} tth@redlady:~$ date --utc Thu Oct 5 00:53:01 UTC 2023 tth@redlady:~$ \end{verbatim} Ces ordres peuvent être des commandes internes à l'interpréteur, d'autres seront des commandes fournies par des exécutables externes. Pour le début, la différence n'est pas importante. Mais comment le shell fait-il pour retrouver tous les outils dont il a besoin ? Simplement, il connait une liste d'endroits où aller chercher, une sorte de chemin de recherche, c'est d'ailleurs pour ça que cette liste est nommée \texttt{PATH}\index{PATH}. Il est très simple de la visualiser~: \begin{verbatim} tth@redlady:~/Devel/TetaTricks$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games \end{verbatim} % ============================================================== \section{Un langage}\index{script} Le shell est aussi, et surtout, un langage de programmation à part entière. Il est parfois appelé \textsl{glue-language} parce qu'il permet de "coller" ensemble plusieurs opérations élémentaires, d'abord avec ses opérateurs internes et ensuite par l'utilisation d'outils extérieurs\footnote{Grep, Sed, Awk, BwBasic, Sort, Gfortran...} divers. C'est \textsl{très} efficace. Nous allons commencer par voir quelques notions liées à la création d'un script exécutable, puis d'un enchainement de commandes. Nous passerons ensuite aux structures de contrôle, comme les tests et les boucles. % -------------------------------------------------------------- \subsection{Le shebang} \index{shebang} \label{shebang} Le shebang, c'est ce couple de caractères \texttt{\#!} qui apparait au tout début d'un script shell. Le 'she' est l'abréviation de 'sharp', qui veut dire 'coupant' en français. C'est probablement une allusion aux cotés tranchants du \texttt{\#}. Quand au 'bang', c'est le point d'exclamation après l'explosion de la forkbomb. Quand on demande au noyau\index{kernel} d'exécuter un fichier \texttt{(man 3 exec}), il va en lire d'abord les premiers octets. Si les deux premiers sont \textsl{0x23 0x21}, le reste de la première ligne sera interprété pour lancer un autre exécutable, avec un traitement particuler des options. Et à ce momment-là des explications, on entend Serguey qui hurle du fond de la salle « schmod777 en force ! ». Et il a bien raison. En effet, ce fichier doit être vu comme possiblement exécutable selon les droits 'X' qu'il a. Il y a une commande prévue à cet effet, dont nous allons voir l'usage à l'instant, avec la création d'un script complet~: \begin{verbatim} tth@redlady:~$ echo '#!/bin/bash' > foo.sh tth@redlady:~$ echo 'printf "%x" 85 >> foo.sh tth@redlady:~$ chmod u+x ./foo.sh tth@redlady:~$ ./foo.sh 55 tth@redlady:~$ cat foo.sh #!/bin/bash printf "%x\n" 85 tth@redlady:~$ \end{verbatim} % ============================================================== \section{Le pipeline}\index{pipeline}\label{pipeline} Une invention géniale, dont vous pouvez voir un exemple d'utilisation par un gadget sonore en page \pageref{say-uptime} et un bout de code C en page \pageref{filtre-unix}. Exemple rapide, où la commande \texttt{uptime} envoie sa sortie dans le tuyau, et la commande \texttt{tr} va lire le tuyau pour son entrée~: \begin{verbatim} $ uptime | tr ' ' 'X' X09:22:29XupX33Xdays,X14:00,XX8Xusers,XXloadXaverage:X0.12,X0.17,X0.17 \end{verbatim} Bien entendu, on peut utiliser plusieurs tuyaux pour construire une chaine de traitements% \footnote{La chaine de compilation \textsc{eqn/tbl/roff} est un bon exemple}. On peut même « intercepter » ce qui transite par un des tuyaux. \begin{verbatim} tth@redlady:~/Devel/TetaTricks$ date | tee foo.txt | tr 'EASLeasl' '34573457' W3d 53p 25 16:07:01 C35T 2024 tth@redlady:~/Devel/TetaTricks$ cat foo.txt Wed Sep 25 16:07:01 CEST 2024 \end{verbatim} % ============================================================== % new Wed Sep 25 14:00:07 UTC 2024 \section{L'environnement} \index{environ} Commençons par une petite histoire. Un jour\footnote{été 2024 ?}, je suis tombé par un hasard improbable sur une variable d'environnement nommée \textsc{hostname}. Qui contenait précisément "redlady" ! Tout bien. Alors, quelques jours avant, vers 2006, je l'ai utilisée dans un bout de code en C, que j'avais depuis bien bien longtemps oublié au fond d'une 8" hard-sectored. Et là, ça ne marche pas comme je l'espérais. Voyez ce bout de code~: \begin{verbatim} char *nom = "HOSTNAME"; printf("%s -> %s\n", nom, getenv(nom)); \end{verbatim} Il me renvoit \texttt{HOSTNAME -> (null)}. Krkrkr. % ============================================================== \section{Structures de contrôle} Les plus importantes sont là : le choix, la boucle, l'attente, le \textsc{goto}\index{goto} calculé, la sélection, \textsl{make your choice}. % -------------------------------------------------------------- \subsection {Les tests} Deux éléments sont ils égaux ? Et d'abord, ces deux éléments sont-ils comparables ? % -------------------------------------------------------------- \subsection {Les boucles} Exemple très simple~: \begin{verbatim} for foo in A B C D do echo ${foo} done \end{verbatim} Autre exemple, un peu moins simple~: \begin{verbatim} for foo in $(seq 0 37 133) do printf "foo = %3d\n" ${foo} done \end{verbatim} % ============================================================== \section{Les fonctions} Une bonne manière de rendre votre code modulaire, et de réutiliser des bouts de code à volonté depuis plusieurs programmes. Une fonction peut accepter des paramètres, qui seront connus sous les petits noms de \texttt{\$1 \$2 ... \$n}. Voici un fichier contenant quelques fonctions~: \lstinputlisting{code/shell/fonctions.sh} Pour les utiliser, il faut d'abord les charger dans le shell courant. C'est la directive \texttt{source}\index{source} qui s'en charge~: \lstinputlisting{code/shell/demofonctions.sh} XXX expliquer "source" \index{XXX} % ============================================================== % https://bwog-notes.chagratt.site/2023/le-heredoc/ \section{Heredoc} Un nom bien difficile à traduire, peut-être par « document en place » ? C'est un moyen simple et efficace de mettre des données textuelles (comme des commandes pour un logiciel particulier) dans un script afin de les envoyer dans le \textsl{stdin} d'un logiciel. Par exemple, quelques commandes pour générer un graphique avec Gnuplot\index{gnuplot} sur la console \textsl{dumb}. \lstinputlisting{code/shell/heredoc.sh} Après le \textsl{shebang}, nous avons la création de la variable pour le titre, et ensuite l'appel à Gnuplot avec la redirection \texttt{$<<$ \_\_EOC\_\_} % bug affichage "<<" qui va envoyer sur le stdin de Gnuplot la suite du script shell (des commandes gnuplot), jusque au marqueur de fin, qui est \texttt{\_\_EOC\_\_} dans notre cas. ... et la démonstration~: \begin{verbatim} tth@redlady:~/Devel/TetaTricks/code/shell$ ./heredoc.sh Here Doc (9946) 1 +-------------------------------------------------------------+ | + + + + + + + + + | | 0.7*sin(x) ******* | | ****** ****** | 0.5 |-+ ** ** ** ** +-| | ** * * ** | | ** ** ** ** | | ** ** ** ** | |* ** ** *| 0 |-+ * * +-| | ** ** | | * * | | * * | -0.5 |-+ ** ** +-| | *** *** | | ******* | | | | + + + + + + + + + | -1 +-------------------------------------------------------------+ 0 1 2 3 4 5 6 7 8 9 \end{verbatim} Je pense que l'exemple est assez parlant. Pour un exemple plus complet, toujours avec gnuplot, c'est vers la page \pageref{chap:gnuplot}. % ============================================================== \section{Les \textsl{locales}} \index{locales} % new: Mon Apr 17 10:54:45 UTC 2023 Quelle sont les différences entre \texttt{en\_US.UTF-8} et \texttt{C.UTF-8} ? % ============================================================== % https://wiki.fiat-tux.fr/books/d%C3%A9veloppement/page/ajouter-des-couleurs-a-ses-scripts-shell \section{Écrire en couleur} \index{ANSI} \index{escape} \begin{verbatim} BLACK='\033[0;30m' RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[0;37m' \end{verbatim} % ============================================================== \section{Questions à voir} \begin{itemize} \item le traitement des chaines de caractères\dots \item la gestion des co-routines\dots \end{itemize} % ==============================================================