316 lines
11 KiB
TeX
316 lines
11 KiB
TeX
\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}
|
|
|
|
|
|
% ==============================================================
|