Zum Inhalt springen

ShellCheck in der CI: Bash-Skripte ohne Fußangeln deployen

9. Juni 2026 durch
ShellCheck in der CI: Bash-Skripte ohne Fußangeln deployen
Carsten Depping

Ein fehlendes Anführungszeichen in einem Admin-Skript ist ungefähr so lustig wie rm -rf "$BACKUP_DIR/"*, wenn $BACKUP_DIR leer ist. Also: gar nicht. Genau deshalb haben wir ShellCheck in die CI geworfen. Nicht als Deko, sondern als Türsteher für unsere Shell-Skripte.

ShellCheck ist ein statischer Analyzer für Shell-Skripte. Das Tool schaut sich Bash, sh, dash und ksh an und meckert bei typischen Fehlern: unquotierte Variablen, kaputte Tests, falsche Redirects, unsichere Globs, tote Variablen. Kurz: Dinge, die nachts um 03:17 Uhr Tickets erzeugen.

Installation lokal ist unspektakulär:

apt install shellcheck

Oder auf macOS:

brew install shellcheck

Dann ein Skript prüfen:

shellcheck backup.sh

Klassiker:

!/bin/bash
for file in $BACKUP_DIR/*.tar.gz; do
scp $file root@$HOST:/backup/
done

ShellCheck schreit hier völlig zurecht. $BACKUP_DIR, $file und $HOST sind nicht gequotet. Wenn Pfade Leerzeichen enthalten oder Variablen leer sind, wird’s spannend. Die bessere Variante:

!/usr/bin/env bash
set -euo pipefail
for file in "$BACKUP_DIR"/*.tar.gz; do
scp "$file" "root@$HOST:/backup/"
done

set -euo pipefail ist kein magischer Schutzschild, aber ein brauchbarer Helm. -e beendet bei Fehlern, -u bei nicht gesetzten Variablen, pipefail sorgt dafür, dass Pipelines nicht alles schönreden.

Damit das nicht nur auf dem Laptop des gewissenhaften Admins läuft, kommt ShellCheck in die CI. Beispiel GitLab CI:

stages:
  - lint

shellcheck:
  image: koalaman/shellcheck-alpine:stable
  stage: lint
  script:
    - shellcheck scripts/*.sh

Wenn deine Skripte in mehreren Verzeichnissen liegen:

script:
  - find . -type f -name "*.sh" -print0 | xargs -0 shellcheck

Für GitHub Actions sieht das so aus:

name: shellcheck
on:
  push:
  pull_request:
jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install ShellCheck
        run: sudo apt-get update && sudo apt-get install -y shellcheck
      - name: Run ShellCheck
        run: find . -type f -name "*.sh" -print0 | xargs -0 shellcheck

Wichtig: Nicht blind alles wegdrücken. Wenn ShellCheck meckert, hat es meistens einen Punkt. Falls du eine Warnung bewusst ignorierst, dokumentiere sie direkt im Skript:

shellcheck disable=SC2086
rsync $RSYNC_OPTIONS "$SRC/" "$DST/"

Aber bitte nicht global mit der großen Keule alles deaktivieren. Das ist wie Monitoring ausschalten, weil Nagios nervt.

Praktisch ist auch eine .shellcheckrc im Repo:

shell=bash
severity=warning

Damit ist klar, welche Shell gemeint ist und ab welcher Stufe die CI rot wird. Für Legacy-Skripte kannst du erstmal mit severity=error starten und später anziehen. Hauptsache, neue Fehler kommen nicht mehr rein.

Unser Fazit aus dem Selbstversuch: ShellCheck findet peinliche Bugs, bevor sie produktiv werden. Die CI sorgt dafür, dass das nicht vom Koffeinlevel einzelner Menschen abhängt. Genau so muss Admin-Automatisierung aussehen: langweilig, reproduzierbar und ohne Bash-Goblin im Serverraum.

ShellCheck in der CI: Bash-Skripte ohne Fußangeln deployen
Carsten Depping 9. Juni 2026
Diesen Beitrag teilen