Regeln, Standards, Kontextstruktur und Werkzeuge übernommen; 2nd-brain- Inhalte (Stacks, Ansible-Inventar, Architektur, Knowledge) entfernt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
162 lines
8.8 KiB
Markdown
162 lines
8.8 KiB
Markdown
# 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
|
||
```
|
||
<scriptdir>/
|
||
├── 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 <Name aus ai/context/responsible.md>
|
||
## @owner <Name/Rolle aus ai/context/responsible.md>
|
||
## @assist KI-unterstützt (<Modell>), geprüft von <author>
|
||
## @version 1.0.0 (07.10.2026)
|
||
##
|
||
## @usage backup_db.sh [Optionen] <datenbank>
|
||
## @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 <pfad> [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_<LANG>` (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 <level> "…"` | – | – | 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} <ziel>/` (`_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.
|