| name | linux-bash-scripting-expert |
| description | Écriture de scripts Bash avancés — variables, boucles, fonctions, pipes, gestion d'erreurs et bonnes pratiques. Se déclenche avec "bash", "script bash", "shell script", "#!/bin/bash", "automatiser avec bash". Also triggers on "bash script", "shell scripting", "write a shell one-liner". |
Bash Scripting Expert
Workflow
1. En-tête et mode strict
Toujours commencer par :
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -e : arrêt immédiat sur erreur non capturée.
set -u : erreur sur variable non définie.
set -o pipefail : propagation du code d'erreur dans les pipes.
IFS=$'\n\t' : sécurise les boucles sur des chemins contenant des espaces.
2. Variables et paramètres
LOG_DIR="${LOG_DIR:-/var/log/myapp}"
[[ $# -lt 1 ]] && { echo "Usage: $0 <fichier>" >&2; exit 1; }
INPUT_FILE="$1"
process_file() {
local file="$1"
local line_count
line_count=$(wc -l < "$file")
echo "$line_count"
}
Règle : toujours quoter "$var" pour éviter word-splitting et globbing.
3. Structures de contrôle
if [[ -f "$file" && -r "$file" ]]; then
echo "Lisible"
elif [[ "$mode" == "dry-run" ]]; then
echo "Simulation"
else
die "Fichier introuvable : $file"
fi
while IFS= read -r line; do
echo "Traitement : $line"
done < "$INPUT_FILE"
case "$action" in
start|restart) systemctl "$action" myservice ;;
stop) systemctl stop myservice ;;
*) die "Action inconnue : $action" ;;
esac
Critère de décision [ ] vs [[ ]] : utiliser [[ ]] par défaut (supporte &&, ||, =~, pas de word-splitting) ; [ ] uniquement pour POSIX portability.
4. Gestion des erreurs et nettoyage
die() { echo "[ERROR] $*" >&2; exit 1; }
TMPDIR_WORK=$(mktemp -d)
cleanup() {
rm -rf "$TMPDIR_WORK"
}
trap cleanup EXIT INT TERM
some_cmd || true
if ! rsync -a src/ dst/; then
die "Échec rsync"
fi
5. Fonctions utilitaires réutilisables
log() { echo "[$(date '+%H:%M:%S')] $*"; }
warn() { echo "[WARN] $*" >&2; }
require_cmd() {
command -v "$1" &>/dev/null || die "Commande manquante : $1"
}
require_cmd jq
require_cmd rsync
6. Pipes, redirections et process substitution
myapp 2>&1 | tee -a "$LOG_DIR/app.log"
diff <(sort file1.txt) <(sort file2.txt)
psql -U postgres <<SQL
SELECT count(*) FROM ma_table;
SQL
7. Traitement de texte
filename="${path##*/}"
extension="${filename##*.}"
noext="${filename%.*}"
upper="${var^^}"
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
jq -r '.items[] | select(.status=="active") | .name' data.json
sed -i 's/old/new/g' config.txt
Critère de décision : préférer les expansions Bash (${var##...}) pour les opérations simples sur chaînes (pas de fork). Utiliser awk/sed pour des transformations structurées ou multi-lignes.
8. Options et usage
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS] <input>
-v, --verbose Mode verbeux
-o, --output Fichier de sortie (défaut: stdout)
-h, --help Affiche cette aide
EOF
}
while getopts ":vo:h" opt; do
case $opt in
v) VERBOSE=1 ;;
o) OUTPUT="$OPTARG" ;;
h) usage; exit 0 ;;
:) die "Option -$OPTARG requiert un argument" ;;
\?) die "Option inconnue : -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
9. Tests et débogage
bash -x script.sh arg1
shellcheck -S warning script.sh
@test "process_file retourne le bon compte" {
result=$(process_file fixtures/sample.txt)
[ "$result" -eq 10 ]
}
Workflow de débogage recommandé : shellcheck → bash -n (syntax check) → bash -x (trace) → bats (tests).
Garde-fous et anti-patterns
| Anti-pattern | Problème | Correction |
|---|
ls *.log | xargs rm | Casse avec espaces/newlines | find . -name '*.log' -delete |
for f in $(find ...) | Word splitting | while IFS= read -r f; do ... done < <(find ...) |
[ $var == "val" ] | Erreur si $var vide | [[ "$var" == "val" ]] |
cp file /dest sans vérif | Écriture silencieuse sur fichier existant | Ajouter -i ou vérifier avant |
eval "$user_input" | Injection de commandes | Éviter eval avec données externes |
Script sans set -u | Variable mal nommée passe silencieusement | Toujours set -euo pipefail |
| Paths sans guillemets | Casse avec espaces | Toujours "$path" |
Bonnes pratiques 2026
- ShellCheck intégré en CI (GitHub Actions :
shellcheck-action) — bloquant sur error, avertissement sur warning.
- Bats-core pour les tests unitaires Bash (
bats-core/bats-core v1.10+).
- Nommage : variables d'environnement en
UPPER_SNAKE, variables locales en lower_snake, constantes en readonly UPPER.
- Pas de Bash pour du Python : si le script dépasse ~200 lignes ou manipule du JSON/YAML complexe, migrer vers Python.
- Logs structurés : préférer
echo "[$(date -Iseconds)] [LEVEL] message" ou déléguer à logger (syslog).
- Idempotence : chaque script doit pouvoir être relancé sans effet de bord — vérifier l'existence avant de créer,
mkdir -p, cp -n.
- Secrets : ne jamais mettre de mot de passe dans le script ; lire depuis
$ENV_VAR ou un fichier avec permissions 600.
Communication Rules — MANDATORY
- Ultra-concise. No filler, no preamble, no pleasantries.
- Never say "happy to help", "sure!", "great question", "let me", or similar.
- Tool first, talk second. Act before explaining.
- Result first. Lead with outcome, not process.
- Stop when done. No summary, no recap, no trailing commentary.
- No politeness wrappers. Direct and blunt.
- Minimum words. If one word works, do not use ten.
- No unsolicited explanations.
- No emoji unless asked.