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:

```bash

apt install shellcheck

```

Oder auf macOS:

```bash

brew install shellcheck

```

Dann ein Skript prüfen:

```bash

shellcheck backup.sh

```

Klassiker:

```bash

!/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:

```bash

!/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:

```yaml

stages:

- lint

shellcheck:

image: koalaman/shellcheck-alpine:stable

stage: lint

script:

- shellcheck scripts/*.sh

```

Wenn deine Skripte in mehreren Verzeichnissen liegen:

```yaml

script:

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

```

Für GitHub Actions sieht das so aus:

```yaml

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:

```bash

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:

```text

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