Bash-Skripte, die dich nicht überraschen
Die Gewohnheiten, die Shell-Skripte sicher machen, und wann man auf Python wechselt.
Die Gewohnheiten, die Shell-Skripte sicher machen, und wann man auf Python wechselt.

Bash ist überall in DevOps. CI-Pipelines, Docker-Dateien, Bereitstellungs-Skripte, Cron-Jobs, schnelle Automatisierungen. Es ist der Klebstoff, der die Infrastruktur zusammenhält.
Bash hat versteckte Gefahren. Standardmäßig läuft es immer nach Fehlern, behandelt undefinierte Variablen als leer und teilt Wörter auf unerwartete Weise. Ein Skript, das auf Ihrem Laptop gut funktioniert, könnte versehentlich den falschen Ordner in der Produktion löschen, wenn eine Variable leer ist.
Hier sind die Gewohnheiten, die meine Drehbücher langweilig machen, auf die beste Art und Weise.
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
Was sie tun:
set -e: das Skript stoppen, wenn ein Befehl fehlschlägt, anstatt weiterzumachen.set -u: behandeln undefinierte Variablen als Fehler, anstelle einer leeren Zeichenfolge.set -o pipefail: eine Pipeline versagt, wenn irgendein Befehl darin versagt, nicht nur der letzte.IFS=$'\n\t': nur auf Neulinien und Registerkarten, nicht auf Leerzeichen. Weniger Überraschungen mit Dateinamen mit Leerzeichen.Warum? set -u Es ist so wichtig, in einem Beispiel:
rm -rf "$BUILD_DIR/"*
Wenn BUILD_DIR ist versehentlich ausgeschaltet, ohne set -u Das wird rm -rf /*- Ich weiß . Mit set -u, das Skript endet mit einem Fehler. Diese einzige Linie hat viele Systeme gerettet.
(set -e hat einige bekannte Randfälle, wie Befehle in Bedingungen oder Unterhallen. Es ist nicht perfekt, aber es ist eine große Verbesserung gegenüber dem Standardverhalten.)
Bash geht davon aus, dass du weißt, was du tust. Gute Drehbücher machen diese Annahme nicht über irgendjemanden, auch nicht über ihren Autor.
ShellCheck ist ein Linter für Shell-Skripte, und das nützlichste Werkzeug, um bessere Bash zu schreiben. Es fängt nicht zitierte Variablen, falsche Vergleiche, nutzlose catDie Kommission hat die Kommission aufgefordert, die in den letzten Jahren vorgenommenen Maßnahmen zu prüfen.
shellcheck deploy.sh
Fügen Sie es Ihrem Redakteur und Ihrem Informanten hinzu. Ich behandle ShellCheck Warnungen wie Kompiliererfehler.
Nennen Sie Ihre Variablen. - Immer. - Ich weiß. "$file"Nein . $file- Ich weiß . Nicht zitierte Variablen werden auf Leerzeichen aufgeteilt und als Wildcards ausgeweitet.
Verwendung [[ ]] für Prüfungen in Bash nicht [ ]- Ich weiß . Es ist sicherer und unterstützt mehr Funktionen.
if [[ -z "${ENVIRONMENT:-}" ]]; then
echo "ENVIRONMENT must be set" >&2
exit 1
fi
Vorgaben und erforderliche Kontrollen mit Parametererweiterung:
REGION="${REGION:-eu-central-1}" # default value
: "${API_TOKEN:?API_TOKEN is required}" # fail with a message if unset
Verwendung local in Funktionen Also lecken keine Variablen.
Fehler auf stderr schreiben (>&2) und bei Ausfall mit Nicht-Null-Codes aussteigen.
Reinigen Sie mit trap, auch wenn das Skript fehlschlägt:
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
Verwendung $(...) statt von Backticks für die Kommandoersetzung.
Vermeiden Sie das Parsen ls. Verwenden Sie Kugeln oder find Stattdessen.
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<EOF
Usage: $(basename "$0") -e <environment> [-d]
-e target environment (staging|production)
-d dry run
EOF
}
log() { printf '%s [%s] %s\n' "$(date -u +%FT%TZ)" "${1}" "${2}" >&2; }
main() {
local env="" dry_run=false
while getopts ":e:dh" opt; do
case "$opt" in
e) env="$OPTARG" ;;
d) dry_run=true ;;
h) usage; exit 0 ;;
*) usage; exit 1 ;;
esac
done
[[ "$env" =~ ^(staging|production)$ ]] || { usage; exit 1; }
log INFO "Deploying to $env (dry run: $dry_run)"
if [[ "$dry_run" == false ]]; then
: # real work here
fi
}
main "$@"
Es hat Argument-Parsing, Validierung, Logging mit Zeitstempeln, einen Trockenlaufmodus und eine main Funktion. Verstanden, löschen Sie, was Sie nicht brauchen.
Bash ist großartig, um Befehle zusammenzuhalten. Es ist schlecht in fast allem anderen. Ich wechsle auf Python (oder Go), wenn ein Skript:
jq Ruf an.Python mit einer ordnungsgemäßen CLI-Bibliothek oder einem kleinen Go-Tool ist an diesem Punkt viel einfacher zu lesen, zu testen und zu warten.
CI YAML enthält oft mehrzeilige Shell-Skripte. Es gelten die gleichen Regeln:
set -euo pipefail - Sie ist standardmäßig. Fügen Sie es hinzu oder setzen Sie die Shell-Optionen für den gesamten Job.Hinzufügen set -euo pipefail An der Spitze jedes Skripts und ShellCheck sie alle. Diese zwei Gewohnheiten verhindern die meisten Katastrophen, die ich von Shell-Skripten gesehen habe.
Ich denke, Bash ist ein scharfes Messer. Verwenden Sie es für kleine Schnitte, halten Sie es scharf mit ShellCheck, und wechseln Sie zu einem richtigen Werkzeug, wenn die Arbeit größer wird.
Desly