RousselTMLEARNING

Article · Administration Linux : de la découverte à l'expertise

Scripts Bash robustes

1. Les bases #

Un script, c'est une suite de commandes.

Squelette #

Structure d'un script Bash
Toujours la même organisation : on retrouve vite ce que l'on cherche.
#!/usr/bin/env bash
# backup-etc.sh : archive /etc dans /var/backups
set -euo pipefail

readonly DEST=/var/backups
readonly STAMP=$(date +%F_%H%M)

main() {
    mkdir -p "$DEST"
    tar -czf "$DEST/etc_$STAMP.tar.gz" /etc
    echo "Archive créée : $DEST/etc_$STAMP.tar.gz"
}

main "$@"
chmod +x backup-etc.sh && sudo ./backup-etc.sh
bash -x backup-etc.sh   # exécuter en traçant chaque commande
OptionEffet
set -earrête le script à la première commande en échec
set -uerreur si une variable n'est pas définie
set -o pipefailun pipe échoue si une de ses commandes échoue

Variables et guillemets #

nom="web 01"
echo "$nom"          # guillemets doubles : la variable est développée, les espaces préservés
echo '$nom'          # guillemets simples : texte littéral
fichiers=$(ls /etc)  # substitution de commande
echo "${nom:-defaut}"     # valeur par défaut
echo "${#nom}"            # longueur
echo "${fichier%.log}.gz" # remplacer un suffixe
(( total = 3 * 7 )) ; echo "$total" 
Bonne Pratique : Mettez toujours les variables entre guillemets doubles ("$var") : sans eux, un nom de fichier avec un espace devient deux arguments.

2. Contrôle de flux #

Conditions, boucles, fonctions.

Conditions #

if [[ -f /etc/nginx/nginx.conf ]]; then echo "nginx configuré"; fi
if ! systemctl is-active --quiet nginx; then
    systemctl restart nginx
fi
[[ $EUID -eq 0 ]] || { echo "À lancer en root" >&2; exit 1; }
[[ $usage -gt 90 && $env == prod ]] && alerte
case "$1" in
    start|stop) systemctl "$1" app ;;
    *) echo "Usage : $0 {start|stop}" >&2; exit 2 ;;
esac

Tests utiles #

TestVrai si
-f / -d / -efichier / répertoire / existe
-r -w -xlisible, modifiable, exécutable
-z / -nchaîne vide / non vide
-eq -ne -lt -gtcomparaisons numériques
== !=, =~comparaison de chaînes, expression régulière

Boucles #

for host in web01 web02 db01; do
    ssh "$host" uptime
done
for f in /var/log/app/*.log; do gzip "$f"; done
while read -r user shell; do
    echo "$user utilise $shell"
done < <(awk -F: '$3>=1000 {print $1, $7}' /etc/passwd)
for i in {1..5}; do curl -sf http://localhost:8080/health && break; sleep 2; done

Fonctions et codes de retour #

log() { echo "$(date '+%F %T') [$1] ${*:2}" | tee -a /var/log/monscript.log; }
check_disk() {
    local usage
    usage=$(df --output=pcent / | tail -1 | tr -dc '0-9')
    (( usage < ${1:-90} ))      # code retour 0 si OK
}
if ! check_disk 85; then log WARN "disque racine presque plein"; fi
echo $?   # code de retour de la dernière commande (0 = succès)

Un script doit renvoyer 0 en cas de succès et un code non nul en cas d'erreur : cron, systemd, Ansible et les pipelines CI s'en servent pour détecter l'échec.

Codes de retour
Un script qui renvoie toujours 0 rend ses échecs invisibles.

3. Rendre un script robuste #

Ce qui distingue un script de production.

trap, verrou et arguments #

#!/usr/bin/env bash
set -euo pipefail
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT                       # nettoyage, même en cas d'erreur
trap 'echo "Erreur ligne $LINENO" >&2' ERR

exec 9>/run/lock/backup.lock
flock -n 9 || { echo "Déjà en cours" >&2; exit 1; }   # empêcher deux exécutions

DRY_RUN=0 ; RETENTION=7
while getopts "nr:h" opt; do
    case $opt in
        n) DRY_RUN=1 ;;
        r) RETENTION=$OPTARG ;;
        h|*) echo "Usage : $0 [-n] [-r jours]"; exit 0 ;;
    esac
done

Qualité #

ShellCheck
ShellCheck repère les guillemets manquants et les commandes dangereuses.
  • Analysez chaque script avec ShellCheck (aussi en CI).
  • Rendez les scripts idempotents : les relancer ne doit rien casser (mkdir -p, tester avant de créer).
  • Proposez un mode simulation (-n) pour les actions destructrices.
  • Journalisez avec horodatage, sur stderr pour les erreurs.
  • Versionnez les scripts dans Git ; au-delà de ~200 lignes ou de logique complexe, passez à Python ou à Ansible.

Planifier #

Un script de maintenance se lance avec un timer systemd (journalisation, rattrapage, dépendances) ou cron. Testez-le d'abord avec l'environnement minimal : env -i /bin/bash --noprofile --norc ./script.sh.

📄 Scripts Bash pour l'administrateur : écrire des scripts robustes →

Mon suivi

  • ⏱ Durée estimée : ≈ 11 min

Connectez-vous pour suivre votre progression et prendre des notes. Se connecter

✉️ Poser une question

Articles recommandés

Bonnes Pratiques Kubernetes

Meilleures pratiques pour sécuriser et optimiser les déploiements Kubernetes.

Comparaison Offres Kubernetes

Analyse complète des offres managées de Kubernetes avec points forts, fonctionnalités, tarificati...

Stratégies de placement Kubernetes

Présentation des stratégies de placement dans Kubernetes pour optimiser la gestion des charges de...

CNI Kubernetes : Flannel, Calico et Cilium comparés

Kubernetes CNI : comprendre les plugins réseau (Container Network Interface) et comparer Flannel,...

Gestionnaires de packages

Les différents gestionnaires de packages pour Kubernetes et leurs avantages.

Jobs vs Serverless

Comparaison entre les Jobs Kubernetes et le modèle Serverless pour le calcul de tâches en arrière...

PersistentVolume, PersistentVolumeClaim et StorageClass dans Kubernetes

PersistentVolume (PV), PersistentVolumeClaim (PVC) et StorageClass dans Kubernetes : différences,...

Resource Quota Kubernetes

Guide complet sur les quotas de ressources Kubernetes pour la gestion des namespaces.

ConfigMaps et Secrets

Guide complet sur les ConfigMaps et Secrets dans Kubernetes.