# Bash-Standard (verbindlich) > Gilt für jedes Bash-Script dieser Basis und ihrer Projekte. Referenzimplementierung: [`templates/bash/`](templates/bash/). > Die Scripts in `bin/` sind nach diesem Standard gebaut und dienen als Beispiele. ## 1. Bausteine – drei Dateien, mehr nicht ``` / ├── mein_script.sh # Präambel (= Hilfe) + Bootstrap + Funktionen + main ├── _functions.sh # gemeinsame Basis – Kopie aus templates/bash/, NICHT lokal ändern ├── _functions.local.sh # optional: projektspezifische Funktionen (lädt _functions.sh automatisch) ├── .env # optional: Einstellungen (nie im Git) └── .env.example # Pflicht, wenn .env genutzt wird: gleiche Schlüssel, Platzhalter ``` Mehrere Scripts in einem Verzeichnis teilen sich `_functions.sh` und `.env`. Das frühere Modell (`_global_functions.sh`, `_project_functions.sh`, `_project_settings.sh`) entfällt: Settings → `.env`, Projektfunktionen → `_functions.local.sh`. ## 2. Aufbau eines Scripts ```bash #!/usr/bin/env bash #------------------------------------------------------------------------------- ## @file backup_db.sh ## @brief Sichert die Datenbank nach $DIR_BACKUP ## @author ## @owner ## @assist KI-unterstützt (), geprüft von ## @version 1.0.0 (07.10.2026) ## ## @usage backup_db.sh [Optionen] ## @options ## @OPTIONS@ ## @env .env neben dem Script (Vorlage: .env.example) ## @exit 0 = ok · 1 = Fehler · 2 = Aufruffehler #------------------------------------------------------------------------------- set -Eeuo pipefail SCRIPT_PATH="$(readlink -f -- "${BASH_SOURCE[0]}")" # Bootstrap – unverändert übernehmen SCRIPT_DIR="${SCRIPT_PATH%/*}" SCRIPT_NAME="${SCRIPT_PATH##*/}" source "${SCRIPT_DIR}/_functions.sh" || { echo "FEHLER: ${SCRIPT_DIR}/_functions.sh fehlt" >&2; exit 1; } B_OPTS+=( "k|keep|value:TAGE|14|Sicherungen so lange behalten" ) b_init "$@" set -- "${ARGS[@]}" ## @brief Hauptablauf ## @param $1 Datenbankname ## @return 0 ok, 1 Fehler main() { … } main "$@" ``` ### Präambel = Hilfe = Doku - Der Header zwischen den ersten beiden `#-----`-Linien ist **gleichzeitig** die Hilfe (`-h`): `b_usage` gibt alle `##`-Zeilen ohne `## ` aus. - `## @OPTIONS@` wird durch die Optionsliste aus `B_OPTS` ersetzt → Hilfe und Optionen können nicht auseinanderlaufen. - `##` ist der Doku-Marker (wie `/**` bei javadoc). `bin/bashdoc.sh script.sh` erzeugt daraus Markdown. Normale Kommentare mit `#`. - Header-Pflichtfelder: `rules/headers.md`. ## 3. Pfadsicherheit | Variable | Inhalt | |---|---| | `SCRIPT_PATH` | absoluter, aufgelöster Pfad des Scripts (Symlinks aufgelöst) | | `SCRIPT_DIR` | Verzeichnis des Scripts – Basis für `.env`, `_functions.sh`, relative Pfade aus `.env` | | `SCRIPT_NAME` | Dateiname des Scripts | | `B_CALL_DIR` | `$PWD` beim Aufruf – Basis für relative Pfade **von der Kommandozeile** | | `B_LIB_DIR` | Verzeichnis von `_functions.sh` | | `B_TMP_DIR` | Temp-Verzeichnis nach `b_tmpdir`, wird beim Exit gelöscht | - Nie `cd` als Voraussetzung, nie relative Pfade ohne Basis. Helfer: `b_abspath [basis]` (Default-Basis `SCRIPT_DIR`). - Faustregel: Pfade aus `.env`/Defaults → relativ zu `SCRIPT_DIR`; Pfade, die der Benutzer tippt → relativ zu `B_CALL_DIR`. ## 4. Optionen (`B_OPTS`) Format je Eintrag: `"kurz|lang|typ[:META]|default|Beschreibung"` – `typ` = `flag` (0/1) oder `value`. | Quelle | Wo | Hinweis | |---|---|---| | Standard (`-h -d -q -n -l`) | `_functions.sh` (`B_OPTS_STD`) | immer da | | Script-eigen | im Script vor `b_init`: `B_OPTS+=(…)` | Regelfall | | Verzeichnisweit | `.env`: `B_OPTS+=(…)` | gilt für alle Scripts des Verzeichnisses | - Ergebnis: Variable `OPTION_` (Großbuchstaben, `-` → `_`): `--dry-run` → `OPTION_DRY_RUN`, `--keep 7` → `OPTION_KEEP=7`. - Unterstützt: `-d`, `-dn` (gebündelt), `-l datei`, `-ldatei`, `--logfile datei`, `--logfile=datei`, `--debug=0`, `--` (Ende der Optionen). Positionsargumente landen in `ARGS` (auch zwischen Optionen). - Unbekannte Option / fehlender Wert → Meldung, Hinweis auf `--help`, Exit 2. - Immer `+=` verwenden, nie `B_OPTS=(…)` (würde Einträge aus `.env`/`_functions.local.sh` löschen). Kein `|` in Default/Text. ### Vorrang (und Gültigkeit von Umgebungsvariablen) **Default < `.env` < Umgebung < Kommandozeile** - Exportierte `B_*`/`OPTION_*`-Variablen aus der Umgebung werden vor dem Laden von `.env` gesichert und danach wiederhergestellt (`B_LOG_LEVEL=debug ./script.sh` gewinnt gegen `.env`). Nicht exportierte Shell-Variablen des Aufrufers sieht das Script ohnehin nicht. - Für eigene Projektwerte in `.env` dasselbe Verhalten per `VAR="${VAR:-default}"`. - `.env` wird **nicht** automatisch exportiert. Werte, die Kindprozesse brauchen, explizit `export`ieren (Geheimnisse möglichst nicht). - Wirkung der Standardoptionen: `-d` → `B_LOG_LEVEL=debug`, `-q` → `B_LOG_CONSOLE=0`, `-l` → `B_LOG_FILE`, `-n` → `brun` führt nichts aus. ## 5. Ausgabe & Logging – nie `echo` | Funktion | Level | Ziel Konsole | Zweck | |---|---|---|---| | `becho "…"` | info | stdout, ohne Präfix | Ersatz für `echo` | | `bdebug "…"` | debug | stderr, `[DEBUG]` | Details, nur bei `-d` | | `bwarn "…"` | warn | stderr, `[WARN]` | Auffälliges, Lauf geht weiter | | `berror "…"` | error | stderr, `[FEHLER]` | Fehler melden (Funktion entscheidet über `return`) | | `bdie "…" [rc]` | error | stderr | melden + beenden (rc 2 = Aufruffehler mit Hilfe-Hinweis) | | `blog "…"` | – | – | Basis aller obigen | Steuerung (`.env`, Umgebung oder Option): | Variable | Default | Bedeutung | |---|---|---| | `B_LOG_LEVEL` | `info` | Mindestlevel Konsole (`debug`/`info`/`warn`/`error`) | | `B_LOG_CONSOLE` | `1` | Konsole an/aus | | `B_LOG_FILE` | leer | Logdatei; leer = keine | | `B_LOG_FILE_LEVEL` | = `B_LOG_LEVEL` | eigenes Mindestlevel für die Datei | | `B_LOG_COLOR` | `auto` | Farben nur auf Terminal | Logdatei-Format: `JJJJ-MM-TT hh:mm:ss LEVEL script.sh[PID] Text`. **Ausnahme vom echo-Verbot:** echte Daten-Ausgabe für Pipes (`printf '%s\n' "$ergebnis"`) – Meldungen gehen nie auf stdout außer über `becho`. ## 6. Fehler, Return-Codes, Aufräumen - `set -Eeuo pipefail` ist Pflicht. `b_init` setzt Traps: `EXIT` (Aufräumen), `ERR` (meldet Befehl, Funktion, Zeile), `INT`/`TERM` (Exit 130/143 → EXIT-Trap). - **Return-Code-Prinzip:** Jede Funktion endet mit `return 0` (ok), `1` (Fehler) oder `2` (falscher Aufruf); dokumentiert unter `@return`. Fehler meldet die Funktion selbst (`berror`) und gibt den Code zurück – der Aufrufer entscheidet (`if f; then`, `f || return 1`). - Ergebnisse über stdout (`x="$(f)"`) oder globale Variablen mit Präfix – nie über Exit-Codes > 2. - Aufräumen: Script definiert optional `cleanup() { … }` – wird vom EXIT-Trap mit dem Exit-Code aufgerufen, auch bei Fehler/Abbruch. Temporäres immer über `b_tmpdir` (`$B_TMP_DIR`), wird automatisch entfernt. ## 7. Funktionsdoku („briefly!“) ```bash ## @brief Was die Funktion tut – ein Satz ## @param $1 Bedeutung ## @param $@ restliche Argumente ## @return 0 ok, 1 Fehler; Ausgabe auf stdout (falls zutreffend) name() { ``` - Direkt über der Funktion, keine Leerzeile dazwischen. Interne Helfer mit `_` beginnen (`bashdoc.sh` blendet sie ohne `-p` aus). - `local` für alle Variablen in Funktionen. ## 8. Weitere Helfer aus `_functions.sh` | Funktion | Zweck | |---|---| | `brun cmd args…` | ausführen bzw. bei `-n` nur anzeigen (kein `eval`, Argumente als Array) | | `b_require prog…` | prüft, ob Programme vorhanden sind | | `b_require_vars VAR…` | prüft, ob Variablen gesetzt sind | | `b_tmpdir` | legt `$B_TMP_DIR` an | | `b_abspath pfad [basis]` | absoluter Pfad | | `b_usage` | Hilfe ausgeben | ## 9. Stil - Bash ≥ 4.4. Shebang `#!/usr/bin/env bash`. 2 Leerzeichen Einrückung. - Immer quoten (`"$var"`, `"${arr[@]}"`), `[[ ]]` statt `[ ]`, `$(…)` statt Backticks, `printf` statt `echo -e`. - Dateinamen: Kleinbuchstaben, `_` als Trenner, Endung `.sh`; Hilfsdateien mit `_`-Präfix. - Variablen: Konstanten/Globale `GROSS`, lokale `klein`; Präfix `B_`/`_B_`/`OPTION_` ist für `_functions.sh` reserviert. - Prüfen vor Abgabe: `bash -n`, `shellcheck -x`, `-h`, `-n`, ein echter Lauf (lokal, `rules/testing.md`). ## 10. Neues Script in 4 Schritten 1. `cp ai/common/templates/bash/{script_template.sh,_functions.sh,.env.example} /` (`_functions.sh` nur, wenn noch nicht vorhanden). 2. Umbenennen, Header ausfüllen (Verantwortliche aus `responsible.md`), `B_OPTS` anpassen. 3. Funktionen mit Kurz-Doku + `main` schreiben. 4. Testen (§ 9), ggf. `bin/bashdoc.sh` für die Projektdoku. ## Änderungsprotokoll - 07.10.2026 – angelegt; Stack auf `.env` + `_functions.sh` (+ optional `_functions.local.sh`) reduziert.