Polarys

Scripts shell

Variables, conditions et boucles

Variables, conditions et boucles en shell

Automatiser des tâches répétitives, c'est le coeur du métier de technicien système. Un script shell, c'est simplement une suite de commandes dans un fichier texte que l'on exécute en une fois. Vous connaissez déjà les commandes individuelles : les variables, conditions et boucles vous permettent de les rendre intelligentes.

La structure d'un script

#!/bin/bash
# Ce commentaire explique le but du script
# Auteur : Alice - Date : 2026-01-15

echo "Démarrage du script"

La première ligne #!/bin/bash s'appelle le shebang : elle indique quel interpréteur utiliser. Rendez le script exécutable avec chmod +x script.sh avant de le lancer avec ./script.sh.

Variables

# Déclaration (pas d'espace autour du =)
NOM="srv-glpi"
PORT=443
DOSSIER="/var/log/glpi"

# Utilisation ($ devant le nom)
echo "Serveur : $NOM sur le port $PORT"
echo "Logs dans : ${DOSSIER}/php-errors.log"

# Variables spéciales
echo $0    # nom du script
echo $1    # premier argument passé au script
echo $#    # nombre d'arguments
echo $?    # code de retour de la dernière commande (0 = succès)

Conditions if/elif/else

#!/bin/bash
SERVICE="apache2"

# Tester si un service tourne
if systemctl is-active --quiet $SERVICE; then
    echo "$SERVICE est actif"
elif systemctl is-enabled --quiet $SERVICE; then
    echo "$SERVICE est installé mais arrêté"
else
    echo "$SERVICE n'est pas installé"
fi

# Tester si un fichier existe
if [ -f "/etc/glpi/config_db.php" ]; then
    echo "Config GLPI trouvée"
else
    echo "ERREUR : config GLPI manquante"
    exit 1    # quitter le script avec code d'erreur
fi

# Comparaisons numériques
ESPACE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
if [ $ESPACE -gt 90 ]; then
    echo "ALERTE : disque à $ESPACE%"
fi

Opérateurs de test fichier : -f (fichier), -d (dossier), -e (existe), -r (lisible), -z (variable vide)

Boucles for

# Boucle sur une liste
for SERVEUR in srv-glpi srv-ad srv-backup; do
    echo "Ping $SERVEUR..."
    ping -c 1 $SERVEUR > /dev/null && echo "OK" || echo "HORS LIGNE"
done

# Boucle sur des fichiers
for LOG in /var/log/glpi/*.log; do
    echo "Taille de $LOG : $(du -sh $LOG | cut -f1)"
done

# Boucle numérique
for i in $(seq 1 5); do
    echo "Tentative $i..."
done

Boucles while

# Attendre qu'un service démarre
COMPTEUR=0
while ! systemctl is-active --quiet apache2; do
    echo "Attente démarrage Apache... ($COMPTEUR s)"
    sleep 2
    COMPTEUR=$((COMPTEUR + 2))
    if [ $COMPTEUR -gt 60 ]; then
        echo "Timeout : Apache n'a pas démarré"
        exit 1
    fi
done
echo "Apache est démarré !"

Cas concret

Script de vérification quotidienne des serveurs PME :

#!/bin/bash
# check-serveurs.sh : Vérifie la disponibilité des serveurs

RAPPORT="/var/log/check-serveurs-$(date +%Y%m%d).log"

echo "=== Vérification $(date) ===" > $RAPPORT

check_host() {
    IP=$1
    NOM=$2
    if ping -c 1 -W 2 $IP > /dev/null 2>&1; then
        echo "OK    $NOM ($IP)" | tee -a $RAPPORT
    else
        echo "FAIL  $NOM ($IP) : HORS LIGNE" | tee -a $RAPPORT
    fi
}

check_host "192.168.1.10" "srv-glpi"
check_host "192.168.1.20" "srv-ad"
check_host "192.168.1.30" "srv-backup"

echo "Rapport : $RAPPORT"
flowchart TD
  START([Début du script]) --> READ[Lire liste serveurs]
  READ --> LOOP{Pour chaque serveur}
  LOOP --> PING[ping -c 1 serveur]
  PING --> OK{Code retour = 0 ?}
  OK -->|Oui| LOG_OK["Écrire 'OK' dans rapport"]
  OK -->|Non| LOG_FAIL["Écrire 'FAIL' dans rapport"]
  LOG_OK --> NEXT[Serveur suivant]
  LOG_FAIL --> NEXT
  NEXT --> LOOP
  LOOP -->|Tous testés| END([Fin : afficher rapport])

Erreurs fréquentes

  • Mettre des espaces autour du = dans une assignation : NOM = "srv" est une erreur (bash cherche une commande "NOM"). La bonne syntaxe : NOM="srv".
  • Oublier les guillemets autour de $VARIABLE dans les tests : si la variable est vide, [ $VAR -gt 0 ] devient [ -gt 0 ] qui cause une erreur.
  • Confondre = (assignation) et == (comparaison dans [[ ]]) : dans [ ], utilisez = pour comparer des chaînes.

À retenir

  • Le shebang #!/bin/bash est obligatoire en première ligne.
  • $? contient le code de retour de la dernière commande : 0 = succès, autre = erreur.
  • Toujours tester un script avec bash -n script.sh (dry-run syntax check) avant de l'exécuter.

Mini-exercice

Créez un script /tmp/espace.sh qui affiche un avertissement si le disque / est utilisé à plus de 80%. Utilisez df / | tail -1 | awk '{print $5}' | tr -d '%' pour obtenir le pourcentage. Rendez-le exécutable et testez-le.

Quiz de validation

Quiz - 10 questions

1. À quoi sert la ligne '#!/bin/bash' en première ligne d'un script ?

2. Quelle variable spéciale contient le code de retour de la dernière commande exécutée ?

3. Pourquoi 'NOM = srv-glpi' (avec espaces autour du =) provoque-t-il une erreur ?

4. Quel opérateur teste si un fichier existe ET est un fichier régulier (pas un dossier) ?

5. Dans une boucle for, comment parcourir tous les fichiers .log de /var/log/glpi/ ?

6. Comment vérifier la syntaxe d'un script bash sans l'exécuter ?

7. Un script doit s'arrêter avec un code d'erreur si la config GLPI est manquante. Quelle instruction utiliser ?

8. Quelle boucle est la mieux adaptée pour attendre qu'un service démarre (tenter toutes les 2 secondes jusqu'à succès ou timeout) ?

9. Que fait 'echo "Rapport" | tee -a /var/log/rapport.log' ?

10. Un script de monitoring vérifie 10 serveurs et s'arrête au premier échec. Quelle structure est la plus appropriée ?

Suis ta progression

Crée un compte gratuit pour suivre ta progression et accéder à toutes les leçons.