Bash Scripting : Automatise Tout !
🎯 Objectifs de ce cours
À la fin, tu seras capable de :
✅ Créer un script Bash : De ta première ligne à l'exécution
✅ Utiliser les variables : Stocker et réutiliser des valeurs
✅ Passer des paramètres : Rendre tes scripts flexibles
✅ Ajouter des conditions : If/then/else pour la logique
✅ Boucler : For et while pour répéter
✅ Automatiser des tâches DevOps : Déploiements, backups, monitoring
✅ Déboguer : Comprendre et corriger les erreurs
❌ Le Problème : Les Tâches Répétitives
Imagine ça :
Tous les jours, tu dois :
1. Chercher les logs d'erreurs → grep "ERROR"
2. Les archiver → tar -czf
3. Les envoyer → scp vers un serveur
4. Nettoyer l'espace → rm old files
5. Notifier l'équipe → mail
⏰ 30 minutes à la main, CHAQUE JOUR
❌ Erreurs possibles
❌ Impossible à faire à 18h
Avec un script ?
./daily-cleanup.sh
# 1 seconde. Fini. Tous les jours via cron.
| ❌ Manuel | ✅ Script |
|---|---|
| 30 minutes par jour | 2 secondes |
| Erreurs humaines | Cohérent à 100% |
| Impossible à 18h | Fonctionne 24/7 |
| Pas versionnée | Code source contrôlé |
Les scripts c'est le fondement du DevOps. C'est INDISPENSABLE.
🧱 Qu'est-Ce Qu'Un Script ?
Un script, c'est simple :
Fichier texte contenant des commandes
↓
Bash les exécute une par une
↓
Les résultats sortent à l'écran (ou se sauvegardent)
Exemple :
#!/usr/bin/env bash
echo "Bonjour le monde !"
date
pwd
ls -la
C'est juste des commandes que tu tapes normalement, mais dans un fichier.
Le #!/usr/bin/env bash ? C'est le "shebang". Il dit "utilise Bash pour exécuter ce fichier".
📝 Créer Ton Premier Script
Étape 1 : Créer le fichier
nano hello.sh
Ça ouvre un éditeur vide. Tu tapes :
#!/usr/bin/env bash
echo "Hello DevOps !"
Étape 2 : Sauvegarder
- Appuie sur
Ctrl+X - Tape
Y(oui) - Appuie sur
Entrée
Étape 3 : Rendre exécutable
chmod +x hello.sh
Le +x = "ajoute la permission d'exécution".
Étape 4 : Lancer
./hello.sh
Résultat :
Hello DevOps !
Voilà ! Tu viens de créer un script. 🎉
🧮 Les Variables : La Mémoire De Ton Script
Une variable, c'est une boîte où tu stockes une valeur.
Créer Une Variable
#!/usr/bin/env bash
# Variables
user="tartempion"
server="192.168.1.100"
port=22
echo "Connexion à $server comme $user"
Règles importantes :
- Pas d'espace autour du = : user="deploy" (pas user = "deploy")
- Les $ permettent d'accéder à la valeur
- Mets des guillemets autour des strings
Utiliser Une Variable
#!/usr/bin/env bash
app_name="MyApp"
version="1.2.3"
echo "Application: $app_name"
echo "Version: $version"
echo "Déploiement de $app_name v$version"
Résultat :
Application: MyApp
Version: 1.2.3
Déploiement de MyApp v1.2.3
Variables Spéciales Utiles
$0 # Nom du script
$1 # 1er paramètre
$2 # 2e paramètre
$# # Nombre total de paramètres
$? # Code retour de la dernière commande (0=succès)
$$ # Le PID du script (son identifiant)
Exemples :
#!/usr/bin/env bash
echo "Je suis: $0"
echo "1er param: $1"
echo "J'ai $# paramètres"
ls /nonexistent
echo "Le ls a retourné: $?"
🎯 Les Paramètres : Passe Des Valeurs Au Script
Au lieu de coder les valeurs en dur, tu peux les passer quand tu lances le script.
Script Simple Avec Paramètres
#!/usr/bin/env bash
if [ $# -eq 0 ]; then
echo "Usage: $0 <server> <user>"
exit 1
fi
server=$1
user=$2
echo "Connecte à $server comme $user"
ssh $user@$server
Utilisation
./connect.sh 192.168.1.100 tartempion
# Résultat: Connecte à 192.168.1.100 en tant que tartempion
Cas d'usage DevOps :
# deploy.sh
#!/usr/bin/env bash
app=$1
version=$2
environment=$3
echo "Déploiement de $app version $version en $environment"
# ... rest of deployment logic
./deploy.sh myapp 1.2.3 production
🔀 Les Conditions : Prendre Des Décisions
Les conditions permettent de dire "SI ceci, ALORS fais cela".
Syntaxe de Base
if [ condition ]; then
# Actions si vraie
else
# Actions si fausse
fi
Comparaisons Courantes
# Chaînes
[ "$user" = "admin" ] # Égal
[ "$user" != "guest" ] # Pas égal
[ -z "$var" ] # Variable vide
[ -n "$var" ] # Variable non-vide
# Nombres
[ $count -eq 0 ] # Égal
[ $count -ne 0 ] # Pas égal
[ $count -gt 5 ] # Plus grand que
[ $count -lt 10 ] # Plus petit que
[ $count -ge 5 ] # Supérieur ou égal
[ $count -le 10 ] # Inférieur ou égal
# Fichiers
[ -f "$file" ] # Fichier existe
[ -d "$dir" ] # Dossier existe
[ -r "$file" ] # Fichier lisible
[ -w "$file" ] # Fichier writable
[ -x "$file" ] # Fichier exécutable
# Logique
[ "$a" = "true" ] && [ "$b" = "true" ] # ET
[ "$a" = "true" ] || [ "$b" = "true" ] # OU
Exemple : Vérifier Un Utilisateur
#!/usr/bin/env bash
user=$1
if [ "$user" = "admin" ]; then
echo "Accès complet"
sudo commands
elif [ "$user" = "tartempion" ]; then
echo "Accès déploiement"
deploy commands
else
echo "Accès refusé"
exit 1
fi
Exemple : Vérifier Si Un Fichier Existe
#!/usr/bin/env bash
config_file="/etc/myapp/config.yaml"
if [ -f "$config_file" ]; then
echo "Config trouvée, lancement..."
source "$config_file"
else
echo "Config manquante ! Aborté."
exit 1
fi
🔁 Les Boucles : Répéter Des Actions
Les boucles permettent de faire la même action plusieurs fois.
Boucle FOR : Itérer Sur Une Liste
#!/usr/bin/env bash
for server in web1 web2 web3; do
echo "Ping vers $server"
ping -c 1 $server
done
Itérer sur des fichiers :
#!/usr/bin/env bash
for file in /var/log/*.log; do
echo "Archivant $file"
gzip "$file"
done
Itérer sur une plage de nombres :
#!/usr/bin/env bash
for i in {1..10}; do
echo "Itération $i"
done
Avec des pas :
for i in {0..100..10}; do
echo $i # 0, 10, 20, ..., 100
done
Boucle WHILE : Répéter Tant Qu'Une Condition Est Vraie
#!/usr/bin/env bash
counter=1
max=5
while [ $counter -le $max ]; do
echo "Compteur: $counter"
counter=$((counter + 1))
done
Lire un fichier ligne par ligne :
#!/usr/bin/env bash
while IFS= read -r line; do
echo "Ligne: $line"
done < data.txt
Attendre qu'une condition soit vraie :
#!/usr/bin/env bash
while ! ping -c 1 192.168.1.100 > /dev/null 2>&1; do
echo "Serveur pas accessible. Attente..."
sleep 5
done
echo "Serveur accessible !"
📚 Cas D'Usage DevOps Réels
1️⃣ Déploiement Simple
#!/usr/bin/env bash
APP=$1
VERSION=$2
echo "📦 Déploiement de $APP v$VERSION"
# Télécharger
wget https://releases.example.com/$APP-$VERSION.tar.gz
# Extraire
tar -xzf $APP-$VERSION.tar.gz -C /opt/
# Redémarrer le service
systemctl restart $APP
echo "✅ Déploiement terminé"
./deploy.sh myapp 1.2.3
2️⃣ Backup Automatique
#!/usr/bin/env bash
SOURCE="/var/www/app"
BACKUP_DIR="/backups"
DATE=$(date +%Y-%m-%d)
echo "💾 Backup de $SOURCE"
tar -czf $BACKUP_DIR/app-$DATE.tar.gz $SOURCE
# Garder seulement les 7 derniers backups
find $BACKUP_DIR -name "app-*.tar.gz" -mtime +7 -delete
echo "✅ Backup fait: app-$DATE.tar.gz"
3️⃣ Monitoring Basique
#!/usr/bin/env bash
ALERT_EMAIL="devops@example.com"
# Vérifier l'espace disque
disk_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $disk_usage -gt 80 ]; then
echo "⚠️ ALERTE: Disque à $disk_usage%" | mail -s "Alert" $ALERT_EMAIL
fi
# Vérifier CPU
cpu_load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}')
# (continuer le traitement)
4️⃣ Log Cleanup
#!/usr/bin/env bash
LOG_DIR="/var/log"
DAYS=30
echo "🧹 Nettoyage des logs (> $DAYS jours)"
# Supprimer les vieux logs
find $LOG_DIR -name "*.log" -mtime +$DAYS -delete
# Compresser les logs récents
for file in $LOG_DIR/*.log; do
[ -f "$file" ] && gzip -9 "$file"
done
echo "✅ Logs nettoyés"
5️⃣ Configuration Management
#!/usr/bin/env bash
ENV=$1
case $ENV in
production)
echo "Configuration PROD"
export DB_HOST="prod-db.internal"
export DB_USER="prod_user"
;;
staging)
echo "Configuration STAGING"
export DB_HOST="staging-db.internal"
export DB_USER="staging_user"
;;
*)
echo "Environnement inconnu: $ENV"
exit 1
;;
esac
echo "Déploiement en $ENV avec $DB_HOST"
🧬 Combiner Tout Ça : Un Script Complet
#!/usr/bin/env bash
# Variables
APP="myapp"
VERSION=$1
SERVERS=("web1" "web2" "web3")
BACKUP_DIR="/backups"
# Vérifier les paramètres
if [ -z "$VERSION" ]; then
echo "Usage: $0 <version>"
exit 1
fi
# Créer backup
echo "📦 Backup..."
tar -czf $BACKUP_DIR/$APP-$(date +%s).tar.gz /opt/$APP
# Déployer sur chaque serveur
for server in "${SERVERS[@]}"; do
echo "🚀 Déploiement vers $server..."
if ping -c 1 $server > /dev/null; then
ssh deploy@$server "
cd /opt/$APP
git pull origin main
./build.sh
systemctl restart $APP
"
echo "✅ $server OK"
else
echo "❌ $server injoignable"
fi
done
echo "🎉 Déploiement complet de v$VERSION"
⚠️ Les Pièges Courants
| ❌ Erreur | ✅ Solution |
|---|---|
user=admin (pas de guillemets) |
user="admin" ou user='admin' |
if [$user = "admin"] (pas d'espaces après [ et avant ]) |
if [ "$user" = "admin" ] (espaces APRÈS [ et AVANT ] obligatoires) |
Oublier le #!/bin/bash |
Toujours commencer par le shebang |
chmod 777 (trop de droits) |
chmod +x script.sh (juste exécution) |
| Pas de vérification de paramètres | Toujours vérifier $# ou si les fichiers existent |
🧠 Debugging : Quand Ça Casse
Voir Ce Qui Se Passe
# Exécuter avec traces
bash -x script.sh
# Ou ajouter au début du script
set -x # Active le verbose
set -v # Montre les commandes lues
Vérifier Les Erreurs
./script.sh
echo $? # 0 = succès, autre = erreur
Ajouter Des Logs
#!/usr/bin/env bash
LOG_FILE="/var/log/script.log"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
log "Démarrage du script"
log "Erreur: fichier non trouvé"
🧾 Cheat Sheet : Les Constructions Essentielles
| But | Syntaxe | Exemple |
|---|---|---|
| Variable | var="value" |
app="myapp" |
| Utiliser | $var |
echo $app |
| Paramètre 1 | $1 |
server=$1 |
| Nombre de params | $# |
if [ $# -eq 0 ] |
| Code retour | $? |
echo $? |
| Calcul | $((a + b)) |
x=$((5 + 3)) |
| String vide | [ -z "$var" ] |
if [ -z "$user" ] |
| String non-vide | [ -n "$var" ] |
if [ -n "$msg" ] |
| Fichier existe | [ -f "$file" ] |
if [ -f "/etc/config" ] |
| Dossier existe | [ -d "$dir" ] |
if [ -d "/var/log" ] |
| Nombre égal | [ $a -eq $b ] |
if [ $count -eq 0 ] |
| Nombre > | [ $a -gt $b ] |
if [ $age -gt 18 ] |
| Boucle for | for i in list; do ... done |
for f in *.log |
| Boucle while | while [ cond ]; do ... done |
while [ $x -lt 10 ] |
| If/else | if [ cond ]; then ... else ... fi |
Condition |
| Sorties | echo "text" |
echo "Hello" |
🎯 Checklist : Tu Maîtrises Bash Quand...
- ✅ Tu crées un script sans Googler
- ✅ Tu utilises des variables correctement
- ✅ Tu passes des paramètres à un script
- ✅ Tu écris des conditions if/else
- ✅ Tu boucles sur des listes ou des fichiers
- ✅ Tu vérifies les erreurs avec
$? - ✅ Tu logs tes actions dans un fichier
- ✅ Tu debugges avec
bash -x - ✅ Tu planifies tes scripts avec cron
🚀 Tips Pro
1️⃣ Toujours Vérifier Les Paramètres
#!/usr/bin/env bash
if [ $# -lt 2 ]; then
echo "Usage: $0 <server> <action>"
exit 1
fi
2️⃣ Utiliser set -e Pour Arrêter En Cas D'Erreur
#!/usr/bin/env bash
set -e # Arrête si une commande échoue
cd /opt/app
npm install
npm build
systemctl restart app
# Si une ligne échoue, le script s'arrête
3️⃣ Créer Une Fonction Réutilisable
#!/usr/bin/env bash
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}
log "Démarrage"
log "Milieu"
log "Fin"
4️⃣ Utiliser Des Chemins Absolus
# ❌ Mauvais
cd /tmp
./script.sh
# ✅ Bon
/opt/scripts/script.sh
5️⃣ Planifier Avec Cron
# Éditer crontab
crontab -e
# Exécuter chaque jour à 2h du matin
0 2 * * * /opt/scripts/daily-backup.sh
🚀 Prochaines Étapes
Maintenant que tu maîtrises Bash :
- Apprendre les fonctions avancées : Modulariser tes scripts
- Utiliser sed/awk/grep : Traiter les données dans tes scripts
- Créer des pipelines : Combiner plusieurs scripts
- Implémenter l'error handling : Gérer les erreurs proprement
- Versionner tes scripts : Git pour tes automatisations
- Utiliser Ansible : Orchestration multi-serveurs
Bash est le fondement du DevOps. Tout ce que tu fais en production, tu le fais via des scripts Bash (direct ou via Ansible/Terraform qui utilisent Bash en arrière-plan).
Les trois piliers : Terminal + sed/awk + Scripting = tu es un vrai DevOps ! 💪
Bienvenue dans l'automatisation totale ! 🚀