Linux

Bash — Scripts d'automatisation

Écrire des scripts Bash pour automatiser les tâches récurrentes : sauvegarde, monitoring, déploiement.

← Retour aux tutoriels Linux
📚 C'est quoi un script Bash ? Un script Bash est un fichier texte contenant une série de commandes Linux qui s'exécutent automatiquement les unes après les autres. Au lieu de taper 10 commandes à la main à chaque fois, vous les écrivez une fois dans un fichier et vous le lancez. C'est comme une recette de cuisine : chaque ligne est une instruction que l'ordinateur suit dans l'ordre. Le "shebang" (#!/bin/bash) en première ligne indique à Linux d'utiliser Bash pour interpréter le script.
ⓘ Prérequis Un système Linux (Debian/Ubuntu). Connaissances de base en ligne de commande. Bash est installé par défaut.

Structure d'un script Bash

Voici votre premier script. Il affiche des informations sur le système. Chaque ligne est commentée pour que vous compreniez exactement ce qui se passe :

#!/bin/bash
# ↑ Shebang : cette ligne OBLIGATOIRE en 1ère position dit à Linux
#   d'utiliser Bash pour exécuter ce script

# mon-premier-script.sh
# Description : Affiche des informations utiles sur le système

echo "=== Informations Système ==="

# $(commande) exécute une commande et insère le résultat dans le texte
echo "Hostname   : $(hostname)"                    # Nom de la machine

# lsb_release affiche la version de l'OS. Le 2>/dev/null masque les erreurs
# si la commande n'existe pas, on utilise une alternative avec /etc/os-release
echo "OS         : $(lsb_release -ds 2>/dev/null || cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)"

echo "Kernel     : $(uname -r)"                    # Version du noyau Linux
echo "Uptime     : $(uptime -p)"                   # Depuis combien de temps le serveur tourne
echo "IP         : $(hostname -I | awk '{print $1}')"  # Adresse IP principale

echo "Disk Usage :"
# df -h = espace disque en format lisible (Go, Mo)
# tail -1 = on prend la dernière ligne (le disque principal /)
# awk formate la sortie pour n'afficher que ce qui nous intéresse
df -h / | tail -1 | awk '{printf "  Used: %s / %s (%s)\n", $3, $2, $5}'

echo "RAM Usage  :"
# free -h = mémoire RAM en format lisible
# grep Mem = on filtre la ligne "Mem" (mémoire physique)
free -h | grep Mem | awk '{printf "  Used: %s / %s\n", $3, $2}'

Pour le rendre exécutable et le lancer :

# chmod +x rend le fichier exécutable (droit d'exécution)
# Sans cette commande, Linux refusera de lancer le script
chmod +x mon-premier-script.sh

# ./ signifie "dans le dossier courant". On lance le script !
./mon-premier-script.sh

Script de sauvegarde automatique

Ce script crée une archive compressée d'un dossier avec la date dans le nom, et supprime les anciennes sauvegardes automatiquement. C'est le script le plus utile en production :

#!/bin/bash
# backup.sh — Sauvegarde un dossier avec rotation automatique

# ─── VARIABLES DE CONFIGURATION ───
# Modifiez ces valeurs selon vos besoins
SOURCE="/var/www/html"    # Le dossier à sauvegarder
DEST="/backup"            # Où stocker les sauvegardes
DATE=$(date +%Y-%m-%d_%H%M%S)    # Date actuelle au format 2026-03-28_143022
ARCHIVE="backup_${DATE}.tar.gz"  # Nom du fichier archive (unique grâce à la date)
RETENTION=7               # Nombre de jours de conservation (les plus vieilles seront supprimées)

# ─── CRÉATION DU DOSSIER DE DESTINATION ───
# mkdir -p : crée le dossier ET ses parents si nécessaire, sans erreur si déjà existant
mkdir -p "$DEST"

# ─── CRÉATION DE L'ARCHIVE ───
echo "[$(date)] Début de la sauvegarde..."
# tar = outil d'archivage Linux
# -c = create (créer une archive)
# -z = gzip (compresser l'archive pour réduire sa taille)
# -f = file (spécifier le nom du fichier de sortie)
# -C = changer de répertoire avant d'archiver (pour éviter les chemins absolus dans l'archive)
tar -czf "${DEST}/${ARCHIVE}" -C "$(dirname "$SOURCE")" "$(basename "$SOURCE")"

# ─── VÉRIFICATION DU RÉSULTAT ───
# $? contient le code de retour de la dernière commande (0 = succès, autre = erreur)
if [ $? -eq 0 ]; then
    echo "[$(date)] Sauvegarde réussie : ${ARCHIVE}"
    # du -h = affiche la taille du fichier en format lisible (Mo, Go)
    SIZE=$(du -h "${DEST}/${ARCHIVE}" | cut -f1)
    echo "[$(date)] Taille : ${SIZE}"
else
    echo "[$(date)] ERREUR : La sauvegarde a échoué !" >&2  # >&2 envoie vers stderr (erreur)
    exit 1  # Quitter le script avec un code d'erreur
fi

# ─── ROTATION : SUPPRESSION DES ANCIENNES SAUVEGARDES ───
echo "[$(date)] Nettoyage des sauvegardes de plus de ${RETENTION} jours..."
# find cherche les fichiers correspondant au pattern
# -mtime +7 = modifié il y a plus de 7 jours
# -delete = les supprime
find "$DEST" -name "backup_*.tar.gz" -mtime +${RETENTION} -delete

echo "[$(date)] Terminé."

Script de monitoring serveur

Un script qui vérifie l'état des services et envoie une alerte :

#!/bin/bash
# monitor.sh — Vérifie les services et l'espace disque
# Ce script est conçu pour tourner toutes les 5 minutes via cron

# Fichier où seront écrits les résultats
LOG="/var/log/monitor.log"
# Seuil d'alerte pour le disque (en pourcentage)
DISK_THRESHOLD=80

# Fonction "log" : affiche un message avec la date ET l'écrit dans le fichier log
# tee -a = écrit à la fois à l'écran et à la fin du fichier (-a = append)
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG"
}

# --- Vérification des services ---
# On définit la liste des services à surveiller dans un tableau
SERVICES=("ssh" "nginx" "docker")

# Boucle : pour chaque service dans la liste...
for svc in "${SERVICES[@]}"; do
    # systemctl is-active vérifie si le service tourne
    # --quiet = pas de sortie texte, juste le code retour
    # 2>/dev/null = masque les erreurs si le service n'existe pas
    if systemctl is-active --quiet "$svc" 2>/dev/null; then
        log "OK : $svc est actif"
    else
        log "ALERTE : $svc est DOWN !"
    fi
done

# --- Vérification de l'espace disque ---
# df / = espace disque de la partition racine
# awk '{print $5}' = récupère la 5ème colonne (pourcentage)
# tr -d '%' = enlève le symbole % pour pouvoir comparer les chiffres
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')

# -gt = "greater than" (supérieur à)
if [ "$DISK_USAGE" -gt "$DISK_THRESHOLD" ]; then
    log "ALERTE : Disque à ${DISK_USAGE}% (seuil: ${DISK_THRESHOLD}%)"
else
    log "OK : Disque à ${DISK_USAGE}%"
fi

# --- Vérification de la RAM ---
# free = affiche l'utilisation mémoire
# $3/$2 = mémoire utilisée / mémoire totale (en pourcentage)
RAM_USED=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100}')
log "INFO : RAM utilisée à ${RAM_USED}%"

Variables, conditions et boucles

Variables et paramètres

#!/bin/bash
# Quand vous lancez un script avec des arguments (ex: ./script.sh hello world)
# ces arguments sont accessibles via des variables spéciales :

echo "Script : $0"          # $0 = le nom du script lui-même
echo "Argument 1 : $1"      # $1 = le 1er argument passé ("hello")
echo "Nombre d'arguments : $#"  # $# = combien d'arguments au total

# Créer ses propres variables (pas d'espace autour du =)
NOM="serveur-web"
PORT=8080
# ${} permet d'insérer une variable dans du texte
echo "Déploiement de ${NOM} sur le port ${PORT}"

Conditions

#!/bin/bash
FILE="/etc/nginx/nginx.conf"

# [ -f "$FILE" ] vérifie si le fichier existe (-f = file)
# [ -d "/chemin" ] vérifie si le dossier existe (-d = directory)
if [ -f "$FILE" ]; then
    echo "Nginx est installé, configuration trouvée."
elif [ -d "/etc/apache2" ]; then
    echo "Apache est installé à la place."
else
    echo "Aucun serveur web détecté."
fi

Boucles

#!/bin/bash
# Définit un tableau (array) de serveurs à tester
SERVERS=("web01" "web02" "db01" "db02")

# ${SERVERS[@]} = tous les éléments du tableau
for srv in "${SERVERS[@]}"; do
    echo "Ping de ${srv}..."
    # ping -c 1 = envoie 1 seul ping, -W 2 = timeout de 2 secondes
    # &>/dev/null = masque toute la sortie (on veut juste le résultat)
    # && = si le ping réussit, || = sinon
    ping -c 1 -W 2 "$srv" &>/dev/null && echo "  → $srv OK" || echo "  → $srv DOWN"
done

Script de déploiement web

#!/bin/bash
# deploy.sh — Déploie une application web depuis un dépôt Git
# Usage : ./deploy.sh https://github.com/user/mon-site.git

REPO_URL="$1"                     # Le 1er argument = l'URL du dépôt Git
DEPLOY_DIR="/var/www/html"        # Dossier où le site est hébergé
BACKUP_DIR="/backup/deploy"       # Dossier pour les sauvegardes avant déploiement
DATE=$(date +%Y%m%d_%H%M%S)       # Date actuelle pour nommer les fichiers

# Vérifie qu'on a bien fourni l'URL en argument
# -z = "zero length" (la variable est vide)
if [ -z "$REPO_URL" ]; then
    echo "Usage: $0 <url-du-repo-git>" >&2  # >&2 = affiche sur stderr (erreur)
    exit 1  # Quitte avec un code d'erreur
fi

# Étape 1 : Sauvegarde de la version actuelle (au cas où)
echo "→ Sauvegarde de la version actuelle..."
mkdir -p "$BACKUP_DIR"
# tar crée une archive compressée du site actuel
tar -czf "${BACKUP_DIR}/pre-deploy_${DATE}.tar.gz" -C "$DEPLOY_DIR" .

# Étape 2 : Mise à jour du code depuis Git
echo "→ Déploiement depuis ${REPO_URL}..."
cd "$DEPLOY_DIR" || exit 1  # Se placer dans le dossier (ou quitter si impossible)

# Vérifie si c'est déjà un dépôt Git (dossier .git présent)
if [ -d ".git" ]; then
    git pull origin main   # Oui → on met à jour le code existant
else
    rm -rf "$DEPLOY_DIR"/* # Non → on nettoie et on clone le dépôt
    git clone "$REPO_URL" "$DEPLOY_DIR"
fi

# Étape 3 : Redémarrer le serveur web pour prendre en compte les changements
echo "→ Redémarrage de Nginx..."
sudo systemctl reload nginx  # reload = recharge la config sans couper les connexions

echo "→ Déploiement terminé avec succès !"
✔ Utilisation
chmod +x deploy.sh
./deploy.sh https://github.com/user/mon-site.git

Bonnes pratiques

  • Toujours commencer par #!/bin/bash (shebang)
  • Utiliser set -euo pipefail pour arrêter le script en cas d'erreur
  • Mettre les variables entre guillemets : "$VARIABLE"
  • Ajouter des commentaires descriptifs
  • Logger les actions importantes
  • Tester avec bash -x script.sh pour le mode debug
#!/bin/bash
# Active le mode "strict" pour éviter les erreurs silencieuses
set -euo pipefail
# -e : arrête le script dès qu'une commande échoue (au lieu de continuer)
# -u : arrête si on utilise une variable non définie (faute de frappe !)
# -o pipefail : détecte les erreurs dans les pipes (cmd1 | cmd2)

# Mode debug (décommenter pour voir chaque commande avant son exécution)
# set -x
✔ Résultat Vous savez écrire des scripts Bash fonctionnels : sauvegarde avec rotation, monitoring des services, déploiement automatisé. Combinez-les avec cron pour les exécuter automatiquement.