Ce guide a été conçu pour vous aider à comprendre les règles fondamentales de la programmation shell (aussi appelé shell scripting).
#!/bin/sh
# Script vérifiant l'espace disque et les utilisateurs connectés
echo "--- Vérification système ---"
# Vérifier espace disque
df -h / | tail -1 | awk '{print "Espace disque utilisé: " $5}'
# Lister utilisateurs connectés
echo "Utilisateurs connectés:"
who
# Vérifier si un fichier existe
if [ -f "/etc/hosts" ]; then
echo "Le fichier hosts existe"
fi
#!/bin/bash
# Script de surveillance avec fonctionnalités bash spécifiques
echo -e "\033[1;34m--- Monitoring Système ---\033[0m"
# Tableau de services à vérifier
services=("ssh" "apache2" "mysql")
# Vérification des services avec couleurs
for service in "${services[@]}"; do
if systemctl is-active "$service" &>/dev/null; then
echo -e "\033[32m$service est actif\033[0m"
else
echo -e "\033[31m$service est arrêté\033[0m"
fi
done
# Utilisation d'une regex (spécifique bash)
if [[ $(hostname -I) =~ ^[0-9]{1,3}\.[0-9]{1,3} ]]; then
echo "IP valide trouvée"
fi
Dans l'entête d'un script, il est commun d'écrire #!/bin/sh ou #!/bin/bash afin d'identifier facilement le langage utilisé par le script
Pour faire un script, il faut tout d'abord créer un fichier:
touch mon_script.sh
Éditer le fichier et mettre le code du script:
nano mon_script.sh
Voici un exemple de script que nous pouvons utiliser:
#!/bin/sh
# Mon premier script shell
echo "Hello World!"
# Demander le nom de l'utilisateur
echo "Quel est votre nom ?"
read nom
# Afficher un message personnalisé
echo "Bonjour $nom, bienvenue dans le shell scripting!"
Il ne faut pas oublier de donner les droits d'exécution au fichier:
chmod +x mon_script.sh
Finalement, il faut exécuter le script
./mon_script.sh
#ou
sh mon_script.sh
#ou
bash mon_script.sh
Vous devriez avoir un résultat similaire à celui-ci:
Hello World!
Quel est votre nom ?
Pablo
Bonjour Pablo, bienvenue dans le shell scripting!
Une variable dans un script sh est un espace de stockage nommé qui permet de conserver des valeurs (texte, nombres, chemins, etc.) pour une utilisation ultérieure dans le script.
#!/bin/sh
# Déclaration de variables
NOM="Pablo" # Variable texte
AGE=25 # Variable numérique
DATE=$(date +%Y-%m-%d) # Variable avec commande
CHEMIN="/home/user" # Variable chemin
# Utilisation des variables
echo "Nom: $NOM"
echo "Age: $AGE"
echo "Date: $DATE"
echo "Chemin: $CHEMIN"
Voici quelques caractéristiques sur les variables:
Il existe différent types de variables:
Variables locales définies pour l'exécution du script actuel uniquement.
variable="valeur"
nom="Pierre"
Variables d'environnement accessibles par tous les processus d'enfants
export VARIABLE="valeur"
PATH
: chemins de recherche des exécutablesHOME
: répertoire personnel de l'utilisateurUSER
: nom de l'utilisateur courantVariable globale est essentiellement une variable d'environnement qui peut être utilisée par le script principal et tous ses sous-scripts ou processus enfants. Il y a deux méthodes principales pour la définir :
export
:#!/bin/sh
# Définir et exporter la variable globale
export GLOBAL_VAR="valeur globale"
# Ou en deux étapes
GLOBAL_VAR="valeur globale"
export GLOBAL_VAR
# Dans ~/.bashrc ou /etc/profile
GLOBAL_VAR="valeur globale"
export GLOBAL_VAR
Il est recommandé d'utiliser des majuscules pour les variables globales (convention)
unset
Variables spéciales
$0
: nom du script$1
, $2
, etc. : arguments passés au script$#
: nombre d'arguments$*
ou $@
: tous les arguments$?
: code retour de la dernière commande$$
: PID du processus actuel$!
: PID du dernier processus lancé en arrière-planVariables en lecture seule qui ne peuvent plus être modifiées après la déclaration.
readonly variable="valeur"
Pour utiliser une variable, on ajoute le symbole $ devant son nom :
$variable
ou${variable}.
La deuxième syntaxe avec accolades est recommandée pour éviter les ambiguïtés.
Voici quelques exemples de variables:
#!/bin/sh
# Variables locales
message="Hello"
# Variables d'environnement
export LANG="fr_FR.UTF-8"
# Variables spéciales
echo "Nom du script: $0"
echo "Premier argument: $1"
echo "Tous les arguments: $@"
echo "Nombre d'arguments: $#"
echo "PID du script: $$"
echo "Statut dernière commande: $?"
#!/bin/sh
# Correct
NOM="Jean" # Pas d'espace autour du =
echo "$NOM" # Avec guillemets double
RESULTAT=$(ls -l) # Commande entre $()
# Incorrect
NOM = "Jean" # Ne fonctionne pas
echo $NOM # Pas recommandé (sans guillemets)
RESULTAT='ls -l' # Ancien style
Deux types de guillemets sont utilisés en scriptingL
Guillemets Simples (')
#!/bin/sh
NOM="Jean"
DATE=$(date)
# Avec guillemets simples
echo 'Bonjour $NOM' # Affiche: Bonjour $NOM
echo 'Date: $(date)' # Affiche: Date: $(date)
echo 'Symbole $ littéral' # Affiche: Symbole $ littéral
Guillemets Doubles (")
#Exécuter le tout sous le Shell (car avec BASH il va avoir des soucis avec \n)
#!/bin/sh
#Exécuter le tout sous le Shell (car avec BASH il va avoir des soucis avec \n)
NOM="Jean"
DATE=$(date)
# Avec guillemets doubles
echo "Bonjour $NOM" # Affiche: Bonjour Jean
echo "Date: $DATE" # Affiche: Date: [date actuelle]
echo "Ligne 1\nLigne 2" # Affiche sur deux lignes
Voici un exemple comparatif entre les deux types de guillemets:
#!/bin/sh
# Définition des variables
NOM="Jean"
AGE=25
# Différences d'utilisation
echo "1. $NOM a $AGE ans" # Affiche: 1. Jean a 25 ans
echo '2. $NOM a $AGE ans' # Affiche: 2. $NOM a $AGE ans
# Avec commandes
echo "Date: $(date)" # Affiche: Date: [date actuelle]
echo 'Date: $(date)' # Affiche: Date: $(date)
# Avec caractères spéciaux
echo "Première\nDeuxième" # Affiche sur deux lignes
echo 'Première\nDeuxième' # Affiche: Première\nDeuxième
Cas d'utilisation typique
#!/bin/sh
# Utiliser guillemets doubles pour:
CHEMIN="Le chemin est: $HOME/documents"
MESSAGE="Bonjour $USER, aujourd'hui: $(date)"
COMMANDE="Résultat: $(ls -l)"
# Utiliser guillemets simples pour:
REGEX='[A-Za-z]+'
TEXTE_LITTERAL='$5 exactement'
MOTIF='*.txt'
Bref:
La commande unset
dans un script sh est utilisée pour supprimer une variable ou une fonction.
#!/bin/sh
# Définition d'une variable
NOM="Jean"
echo "Nom: $NOM" # Affiche: Nom: Jean
# Suppression de la variable
unset NOM
echo "Nom: $NOM" # Affiche: Nom: (vide)
La commande readonly
ou typeset -r
est utilisée pour créer des variables en lecture seule (constantes) qui ne peuvent pas être modifiées ou supprimées.
#!/bin/sh
# Méthode 1 : readonly
readonly CONSTANTE1="Valeur1"
# Méthode 2 : typeset -r (bash)
typeset -r CONSTANTE2="Valeur2"
# Tentative de modification impossible
CONSTANTE1="Nouvelle valeur" # Erreur
CONSTANTE2="Nouvelle valeur" # Erreur
La commande read
est utilisée pour lire des entrées utilisateur ou des fichiers dans un script shell.
Voici un exemple pour les entrées utilisateurs:
#Exécuter le tout sous sou BASH (car avec SHELL il va avoir des soucis avec -s)
#!/bin/sh
# Lecture simple
echo "Entrez votre nom :"
read NOM
echo "Bonjour $NOM"
# -p : prompt
read -p "Entrez une valeur : " VALEUR
# -s : mode silencieux (pour mots de passe)
read -s -p "PIN : " PIN
# -t : timeout (en secondes)
read -t 5 -p "Vous avez 5 secondes : " REPONSE
# -n : nombre de caractères à lire
read -n 1 -p "Appuyez sur une touche [Y/N] : " CHOIX
# -r : mode raw (backslash non interprété)
read -r TEXTE
Le découpage des mots est défini par le caractère séparateur de champs. Ce séparateur est stocké dans la variable système IFS (Internal Field Separator).
$ set | grep IFS IFS=$' \t\n'
Par défaut, l’IFS contient l’espace, la tabulation \t et le saut de ligne \n.
La commande cut permet d’isoler une colonne dans un fichier ou dans un flux.
La commande tr permet de convertir une chaîne de caractères.
Les arguments sont renseignés lors de la saisie de la commande du script. Ils sont séparés par un espace.
./script argument1 argument2
Une fois exécuté, le script enregistre les arguments saisis dans des variables prédéfinies : les variables positionnelles. Ces variables sont utilisables dans le script comme n’importe quelle autre variable, à l’exception faite qu’elles ne peuvent pas être affectées.
#!/bin/sh
# $0 : Nom du script
# $1 : Premier argument
# $2 : Deuxième argument
# $@ : Tous les arguments (tableau)
# $# : Nombre d'arguments
# $* : Tous les arguments (chaîne)
echo "Nom du script: $0"
echo "Premier argument: $1"
echo "Deuxième argument: $2"
echo "Nombre d'arguments: $#"
echo "Tous les arguments: $@"
Le if est une structure de contrôle qui permet d'exécuter des actions conditionnelles en fonction de l'évaluation d'une condition.
#!/bin/sh
# Structure simple
if [ condition ]
#Commande si vrai
then
#Commande si faux
fi
Dans cette structure :
Voici un exemple simple:
#!/bin/bash
age=18
if [ $age -ge 18 ]; then
echo "Vous êtes majeur."
else
echo "Vous êtes mineur."
fi
Dans cet exemple, la condition [ $age -ge 18 ] vérifie si la variable age est supérieure ou égale à 18. Si la condition est vraie, le script affiche "Vous êtes majeur.". Sinon, il affiche "Vous êtes mineur.".
Attention aux espaces!!!
La structure if/elif/else est un ensemble de conditions dans un script shell qui permet d'exécuter différents blocs de code selon que certaines conditions soient vraies ou fausses, où "if" teste la première condition, "elif" teste les conditions alternatives si la première est fausse, et "else" s'exécute si aucune des conditions précédentes n'est vraie.
#!/bin/sh
# Structure if-else
if [ condition ]
then
# commandes si vrai
else
# commandes si faux
fi
# Structure if-elif-else
if [ condition1 ]
then
# commandes si condition1 vraie
elif [ condition2 ]
then
# commandes si condition2 vraie
else
# commandes si aucune condition vraie
fi
Exemple de code utilisant elif:
#!/bin/sh
# Vérification de l'âge
read -p "Entrez votre âge : " age
if [ "$age" -lt 12 ]
then
echo "Vous êtes un enfant"
elif [ "$age" -lt 18 ]
then
echo "Vous êtes un adolescent"
elif [ "$age" -lt 60 ]
then
echo "Vous êtes un adulte"
else
echo "Vous êtes un senior"
fi
Les opérateurs de comparaison dans un script shell sont des symboles ou expressions spéciales qui permettent de comparer des valeurs (nombres, chaînes de caractères, fichiers) pour effectuer des tests conditionnels et prendre des décisions dans le script, en utilisant la notation suivante:
#!/bin/sh
# Pour les nombres
[ $a -eq $b ] # Égal (notion mathematique =)
[ $a -ne $b ] # Non égal (notion mathematique !=)
[ $a -gt $b ] # Plus grand que (notion mathematique >)
[ $a -lt $b ] # Plus petit que (notion mathematique <)
[ $a -ge $b ] # Plus grand ou égal (notion mathematique >=)
[ $a -le $b ] # Plus petit ou égal (notion mathematique <=)
# Pour les chaînes
[ "$a" = "$b" ] # Égal
[ "$a" != "$b" ] # Non égal
[ -z "$a" ] # Chaîne vide
[ -n "$a" ] # Chaîne non vide
# Pour les fichiers
[ -f "$file" ] # Existe et est un fichier
[ -d "$dir" ] # Existe et est un répertoire
[ -r "$file" ] # Lisible
[ -w "$file" ] # Modifiable
[ -x "$file" ] # Exécutable
Les conditions multiples dans un script shell permettent de combiner plusieurs tests en utilisant les opérateurs logiques "&&" (ET) pour exiger que toutes les conditions soient vraies, "||" (OU) pour qu'au moins une condition soit vraie, et "!" (NON) pour inverser une condition, permettant ainsi des évaluations complexes dans une seule instruction.
Opérateur logique "AND" : En sh, l'opérateur logique "AND" est représenté par &&. Il est utilisé pour évaluer deux conditions et retourne vrai si les deux conditions sont vraies. Sinon, il retourne faux.
Opérateur logique "OR" : L'opérateur logique "OR" est représenté par ||. Il est utilisé pour évaluer deux conditions et retourne vrai si l'une des deux conditions est vraie. Sinon, il retourne faux.
Opérateur logique "NOT" : L'opérateur logique "NOT" est représenté par !. Il est utilisé pour inverser le résultat d'une condition.
#!/bin/sh
# AND (&&)
if [ "$age" -ge 18 ] && [ "$pays" = "France" ]
then
echo "Majeur en France"
fi
# OR (||)
if [ "$role" = "admin" ] || [ "$role" = "superuser" ]
then
echo "Accès autorisé"
fi
# Combinaison complexe
if [ "$age" -ge 18 ] && ([ "$pays" = "France" ] || [ "$pays" = "Belgique" ])
then
echo "Majeur en France ou en Belgique"
fi
La boucle while est une structure de contrôle qui permet d'exécuter de manière répétée un ensemble d'instructions tant qu'une condition donnée est évaluée comme étant vraie (c'est-à-dire non nulle).
Voici la syntaxe de base avec un exemple:
#!/bin/sh
# Structure simple
while [ condition ]
do
# commandes à répéter
done
# Exemple basique
compteur=1
while [ $compteur -le 5 ]
do
echo "Compteur: $compteur"
compteur=$((compteur + 1))
done
La boucle while est utile pour :
Attention aux boucles infinies
La commande break
dans une boucle while permet d'interrompre immédiatement l'exécution de la boucle et d'en sortir lorsqu'une condition spécifique est atteinte, même si la condition principale de la boucle est toujours vraie.
#!/bin/sh
# Boucle infinie
while true
do
read -p "Commande (q pour quitter) : " cmd
if [ "$cmd" = "q" ]
then
break
fi
# Exécute la commande
$cmd
done
Une condition d'arrêt est une expression ou un test qui, lorsqu'il devient vrai (ou faux selon la logique utilisée), permet de mettre fin à l'exécution d'une boucle pour éviter qu'elle ne s'exécute indéfiniment.
# Toujours avoir une condition d'arrêt
compteur=1
max=5
while [ $compteur -le $max ]
do
echo $compteur
compteur=$((compteur + 1))
done
Une autre façon d'écrire ce code serait:
#!/bin/sh
count=1
while [ $count -le 5 ]
do
echo "Le compteur est à : $count"
((count++))
done
echo "Boucle terminée."
count++ est égale à compteur=$((compteur + 1))
La boucle for en bash est une structure de contrôle qui permet d'itérer sur une liste d'éléments donnée. Cette boucle est souvent utilisée pour exécuter un ensemble d'instructions un nombre prédéfini de fois.
Voici la syntaxe de base et un exemple:
#!/bin/sh
# Structure simple
for variable in liste_valeurs
do
# commandes
done
# Exemple basique
for i in 1 2 3 4 5
do
echo "Numéro: $i"
done
Voici d'autres exemples de séquence:
#!/bin/sh
# Avec une séquence de nombres
for i in {1..5}
do
echo "Compteur: $i"
done
#Avec une séquence spécifique
for i in 1 2 3 4 5
do
echo "La valeur de i est : $i"
done
#Avec le terme séquence
for i in $(seq 1 5)
do
echo "Itération $i"
done
# Alternative moderne
for i in {1..5}
do
echo "Tour $i"
done
# Avec des chaînes
for nom in Jean Pierre Marie
do
echo "Bonjour $nom"
done
# Avec des fichiers
for fichier in *.txt
do
echo "Traitement de $fichier"
done
Une particularité de la boucle for est son utilisation avec un compteur selon la structure suivante:
# Structure : for (( initialisation; condition; incrémentation/décrémentation ))
#!/bin/sh
for (( counter=10; counter>0; counter-- ))
do
echo -n "$counter "
done
printf "\n"
La boucle for est utile pour :
Les fonctions en shell sont des blocs de code réutilisables qui peuvent être appelés plusieurs fois dans un script. Voici un exemple:
#!/bin/sh
# Méthode 1
nom_fonction() {
# instructions
echo "Hello World"
}
# Appel de la fonction
nom_fonction
Une fonction avec paramètres permet de passer des valeurs à une fonction pour les utiliser dans son exécution.
#!/bin/sh
# Fonction avec paramètres
dire_bonjour() {
nom="$1" # Premier paramètre
age="$2" # Deuxième paramètre
echo "Bonjour $nom, tu as $age ans"
}
# Appel avec paramètres
dire_bonjour "Jean" "25"
Une fonction avec retour permet de renvoyer des valeurs ou un statut à partir d'une fonction.
#!/bin/sh
# Fonction avec valeur de retour
calculer_somme() {
a="$1"
b="$2"
retour=$((a + b))
return $retour # Retourne la valeur
}
# Appel et récupération
calculer_somme 5 3
resultat=$? # Récupère la valeur retournée
echo "Résultat: $resultat"
Voici l'explication des variables locales et globales dans les fonctions shell :
ma_fonction() {
local var1="locale" # Variable locale (existe seulement à l'intérieur dans ma_fonction)
var2="globale" # Variable globale (existe dans tout le script)
}
Voici un exemple avec une variable locale:
ma_fonction() {
# Variable locale (accessible uniquement dans la fonction)
local nom="Jean"
echo "Dans la fonction: $nom"
}
ma_fonction
echo "Hors fonction: $nom" # $nom n'est pas accessible ici
Voici un exemple avec une variable globale:
# Variable globale (accessible partout)
age=25
ma_fonction() {
echo "Dans la fonction: $age" # Accessible
age=30 # Modifie la variable globale
}
echo "Avant: $age" # Affiche 25
ma_fonction
echo "Après: $age" # Affiche 30
Points clés :
local
pour variables de fonction