Cours ‐ Shell - vbridonneau/CoursSysteme GitHub Wiki
Shell
Le rôle du shell est de fournir une interface utilisateur afin de pouvoir lancer des commandes et naviguer dans le système de fichier.
Interface utilisateur
Différents types d'interpréteur
Il existe différents interpréteurs shell.
Par défaut, les systèmes basés sur Linux et Unix utilisent bash
, mais il en existe bien d'autres.
Nom | Description |
---|---|
sh | conforme au normes POSIX (donc portable) |
bash | surcouche de sh (configurable par exemple) |
zsh | shell du domaine public |
Par la suite nous verrons comment exécuter et écrire des scripts et commandes en bash
.
Interpréteur Bash
L'interpréteur bash permet d'écrire du code shell afin de lancer des commandes dans le terminal. Il est possible de le configurer afin de changer par exemple le prompt :
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
Le fichier .bashrc
situé dans le répertoire ~/
permet de configurer l'interpréteur bash.
Dans ce fichier on retrouve entre autre des variables d'environnements et des alias afin de configurer bash
.
Entre autres choses, on trouve des alias comme :
alias ls='ls --color=auto'
Les alias sont des raccourcis sur des commandes.
pipes
Combinaison de commande avec les Il est possible de rediriger la sortie d'une commande vers l'entrée d'une seconde commande.
commande1 | commande2
Un exemple d'utilisation serait de faire du traitement de texte. Par exemple, en supposant qu'un fichier contienne les informations suivantes :
nom,dateDeNaissance,villeDeNaissance
Alice,10/05/1997,Le Havre
Bob,11/06/1993,Rouen
...
Si l'on souhait extraire de ce fichier uniquement le nom des personnes ainsi que leur ville de naissance, on pourra écrire :
cat fichier | cut -d',' -f1,3
Redirections des flux d'entrée et de sortie
Comme tout programme C, un processus en cours d'exécution a une entrée standard ainsi qu'une sortie et erreur standard.
Lorsque l'on souhaite mettre la sortie d'un programme lancé depuis le terminal, ou depuis un script shell, il suffit d'utiliser le symbol >
:
commande > fichierSortie.txt
De la même façon que l'on peut renvoyer la sortie d'un programme dans un fichier, il est possible de renvoyer l'erreur standard ansi que l'entrée standard.
Pour rediriger l'erreur standard dans un fichier, on utilisera la syntaxe 2>
.
Pour rediriger l'entrée standard vers l'entrée d'un programme, on utilisera le caractère <
.
Voici un exemple :
cat fichier | cut -d',' -f1,3 > donnee.csv 2> log.txt
Mettre des processus en arrière plan
Lorsque l'on souhaite exécuter des programmes que l'on sait mettre du temps à s'exécuter, il est possible de vouloir lancer le programme et de reprendre la main juste après.
Pour cela, il suffit de rajouter le caractère &
à la fin de la commande :
simulationTresLongue &
Un exemple reprenant les deux points précédents et ouvrant firefox depuis le terminal est le suivant :
firefox 2> /dev/null &
Variables
Les variables en bash servent à stocker des valeurs, soit des résultats de commandes ou des nombres. Pour créer une variables, on procède de la manière suivante :
MA_VARIABLE=valeur
Note : attention, il faut absolument que le symbole =
soit collé au nom de la variable et à la valeur que l'on souhaite lui affecter.
Il est possible d'effectuer et de manipuler des variables shell.
Opérations arithmétiques
Pour effectuer des opérations arithmétiques sur des variables shelld, il suffit de les mettre à l'intérieur de $(())
ou $[]
.
Voici quelques exemples :
CPT=$((CPT + 1))
MULTIPLICATION=$[4 * 2]
Note : il est impossible de faire des divisions et d'obtenir des résultats sous forme de nombres flotants en bash avec l'opérateur /
.
Pour pallier le problème, on peut soit utiliser la commande bc
ou d'utiliser la commande python3 -c
.
Manipulation dans des chaines de caractères
Il est possible de manipuler des variables shell avec des chaines de caractères.
Pour pouvoir utiliser une variable dans une chaine de caractère, on utilisera les "
et pas les '
:
x=42
echo "Valeur de x : $x" # Affichera : Valeur de x : 42
echo 'Valeur de x : $x' # Affichera : Valeur de x : $x
Variables variables d'environnements
Les variables d'environnements sont des variables spéciales auxquelles on peut accéder depuis un script bash ou un programme C sans avoir à besoin de les définirs.
Elles contiennent des valeurs de configurations déclarées dans des fichiers parcourus lors du lancement de bash ou lors de l'appel à la commande source
sur un fichier contant des déclaration de telles variables.
Elles sont accessibles via la commande env
.
Parmis elles on trouve :
Nom | Description |
---|---|
USER | nom de l'utilisateur |
PATH | ensemble de chemins de réperotires contenant des exécutables |
LANG | langue utilisée pour afficher des |
PWD | chemin absolu du répertoire courrant |
HOME | chemin absolu vers le home |
Il est enfin possible de convertir une variable en variable d'environnement avec la commande export
, comme dans l'exemple qui suit :
export LANG=fr_FR.utf8
Il est également possible de faire l'opération inverse :
export -n MA_VARIABLE
Si l'on souhaite accéder aux variables d'environnements, on peut y parvenir en utilisant la commande env
.
Elle affiche le nom des variables et leur valeur séparé par le symbol =
:
(Prompt bash)$ > env
(Sortie sur le terminal):
SHELL=/bin/bash
WSL_DISTRO_NAME=Ubuntu-20.04
WT_SESSION=4e7b8725-3d72-40fc-9810-2634b20b0c23
NAME=DESKTOP-NA2NB2H
PWD=/mnt/c/Users/vincb/Documents/Systeme/WikiTPs/Bash
LOGNAME=vbridonneau
MOTD_SHOWN=update-motd
HOME=/home/vbridonneau
LANG=C.UTF-8
Scripts bash
Lorsque l'on souhaite écrire plusieurs commandes dans le but d'effectuer une tâche, il est utile de pouvoir les regrouper dans un même fichier appelé script. Dans ce qui suit, nous allons voir comment gérer les arguments d'un script, comment écrire des conditions et pour finir, comment écrire des boucles.
Paramètres
Comme pour des programmes C, il est possible de paramétrer des scripts bash :
bash monScript.sh arg1 arg2 ...
Pour accéder à la valeur des arguments dans un script, on utilise le symbole $ suivit de l'indice de l'argument.
Un seul indice possède un statut à part, c'est $0
.
Il fait référence au nom du programme et peut être vu comme un équivalent de argv[0]
en C.
On pourra écrire le script suivant si l'on souhaite accéder au nom du script aisni qu'au neuf premiers arguments :
nomDuProgramme=$0
arg1=$1
arg2=$2
#...
arg9=$9
Attention : Même si on peut passer en argument plus de dix valeurs en argument,
il n'est cependant pas possible d'accéder au dixième et au suivant en utilisant par exemple la syntaxe $10.
Pour pouvoir y accéder, il faudra appeler la commande shift
qui a pour effet de décaler les arguments de 1.
Ainsi, après un appel à shift
, $1 fera référence au second argument et $9 au dixième.
Seul $0 n'est pas affecter par shift
et stocke toujours le nom du script en cours d'exécution.
Voici un exemple manipulant les arguments d'un programme
programme=$0
arg1=$1
echo "Nom du programme : $programme, premier argument : $arg1"
En bonus, voici un exemple permettant d'obtenir le dixième argument avec shift
:
# Un exemple d'utilisation de shift
echo "9ème argument $9"
shift
echo "10ème argument $9"
Conditions
Les conditions permettent d'exécuter des blocs de code en fonction d'une condition spécifique. Les structures de contrôle utilisées en bash sont if
, elif
et else
.
Elles s'utilisent comme suit :
if test1
then # Mot clé necessaire
# Liste d'instructions
elif test2 # Equivalent à un else if
then
# Liste d'instructions
else
# Liste d'instructions
fi
Pour réaliser des tests de comparaison en bash, on utilise la syntaxe [ arg1 op arg2 ]
ou [ op arg2 ]
.
Pour faire des comparaisons entre des nombres, les opérateurs sont les suivants :
Opérateur | Description | Exemple |
---|---|---|
-eq | vérifie si deux nombres sont égaux | [ $n -eq 0 ] |
-ne | vérifie si deux nombres sont différents | [ $n -ne $m ] |
-lt | vérifie si le premier argument est strictement plus petit que le second | [ $a -lt $b ] |
-gt | vérifie si le premier argument est strictement plus grand que le second | [ $a -gt $b ] |
-le | vérifie si le premier argument est inférieur ou égal au second | [ $a -le $b ] |
-ge | vérifie si le premier argument est supérieur ou égal au second | [ $a -ge $b ] |
On trouve également quelques opérations sur les fichiers :
Opérateur | Description | Exemple |
---|---|---|
-e | vérifie si l'argument passé existe dans le répertoire courant | [ -e $fichier ] |
-f | vérifie si l'argument passé est un fichier dans le répertoire courant | [ -f $fichier ] |
-d | vérifie si un fichier est un répertoire | [ -d $fichier ] |
Et également des opérations sur les chaines de caractères :
Opérateur | Description | Exemple |
---|---|---|
= | vérifie si deux chaines sont égales | [ $s1 = $s2 ] |
!= | vérifie si deux chaines sont différents | [ $s1 != $s2 ] |
-z | vérifie si une chaine de caractère est vide | [ -z $chaine ] |
Boucles
Les boucles permettent d'itérer sur une séquence d'instructions. En Bash, les boucles les plus couramment utilisées sont la boucle for
et la boucle while
.
La boucle for
fonctionne comme suit :
for variable in commande
do
# des choses à faire
done
Par exemple, si on veut parcourir tous les fichiers d'un répertoire, on peut écrire :
for fichier in `ls`
do
# des choses à faire
done
La boucle while
s'utilise d'une façon similaire :
while condition
do
# Commandes
done
Voici l'exemple d'une boucle affichant les nombres de 0 à 10 et leur carré
for nombre in `seq 0 10`
do
echo $nombre $[nombre*nombre]
done
Variables spéciales
Certaines métadonnées d'un script peuvent être accessibles comme par exemple :
Nom | Description |
---|---|
$? | statut renvoyé par la dernière commande exécutée |
$@ | liste des arguments d'un script |
$* | similaire à $@ |
$# | nombre d'arguments passés à un script bash |
Ces variables sont utiles à bien des usages. Avec elles, on peut par exemple vérifier si un script à bien reçu le bon nombre d'argument, ou si une commande c'est terminé sans problème.
programme=$0
arg1=$1
echo "Nom du programme : $programme, premier argument : $arg1"
echo "Nombre d'arguments : $#"
echo "Liste des arguments : $@"
echo "Premier argument : $arg1"
Voici un exemple reprenant tous les concepts que l'on a vu.
Son but est de parcourir les fichiers d'un répertoire et d'afficher leur taille (la commande s'appelle du
voir plus bas) :
if [ $# -ne 1 ]
then
echo "Usage $0 [rep]"
exit 1
elif [ -e $1 ] && ! [ -d $1 ]
then
echo "$1 n'est pas un répertoire"
exit 1
fi
REP=$1
for fichier in `ls $REP`
do
if [ -f $fichier ]
then
du -h $fichier
fi
done
Quelques commandes utiles
echo
La commande echo
permet d'afficher du code dans le terminale.
On peut l'utiliser par exemple lorsque l'on souhaite afficher la valeur d'une variable :
echo "Les chemins vers des exécutables sont : $PATH" # On fait bien attention à utiliser " et pas ' pour les chaines de caractères.
grep
La commande grep est utilisée pour rechercher des motifs dans des fichiers ou des flux de données. Voici un exemple simple permettant de rechercher dans un fichier C la liste de tous les includes réalisés :
grep "#include" < fichier.c
du
La commande du
est utilisée pour afficher l'utilisation de l'espace disque par les fichiers et répertoires. Voici un exemple affichant la taille de chaque répertoire dans le répertoire courant de manière lisible pour un humain :
du -h
wc
La commande wc
permet de compter le nombre de caractères, le nombre de mots et le nombre de lignes du fichier passer en paramètres.
Par exemple, sur le fichier .bashrc
on pourra écrire :
wc ~/.bashrc
On peut également combiner cette commande à d'autres.
Par exemple, si l'on veut savoir combien de fichier commence par la lettre B
ou b
, on pourra écrire :
ls | grep "^[Bb]" | wc -l