The book is currently only available in German.
Standard-Bibliothek — `prozess`
Verfügbar — implementiert in Phase B.7.7. Vollständige Spec in
docs/prozess.md.
prozess startet andere Programme synchron: git, ls, python, irgendein CLI-Tool. Das ist der natürliche Brückenkopf zwischen Kiste-Skripten und dem Rest des Systems.
29.1 Die vier Funktionen
| Funktion | Use-Case |
|---|---|
prozess.ausgeführt(args, [opt]) |
Voller Output als Karte; du prüfst exit-code selber |
prozess.ausgabe(args, [opt]) |
Du brauchst nur stdout; exit≠0 ist ein Fehler |
prozess.exit_code(args, [opt]) |
Du brauchst nur den Code; Output egal |
prozess.erfolgreich(args, [opt]) |
Du willst nur prüfen ob's klappt → wahr/falsch |
nutze prozess
// Voller Output:
nimm r = prozess.ausgeführt(["git", "status", "--porcelain"])
sag r["exit_code"] // 0
sag r["stdout"] // " M datei.ki\n?? neu.ki\n"
sag r["stderr"] // ""
// Strikte Form:
nimm version = prozess.ausgabe(["git", "--version"])
sag version // "git version 2.45.0\n"
// Nur exit-code:
sag prozess.exit_code(["git", "diff", "--exit-code"]) // 0 oder 1
// Boolean-Prädikat:
wenn prozess.erfolgreich(["git", "rev-parse", "--git-dir"]) {
sag "Wir sind in einem Git-Repo"
}
29.2 Sicherheits-Linie: args ist IMMER eine Liste
Das ist die wichtigste Regel. Kiste verbietet Shell-Strings — args ist immer eine Liste:
// Sicher:
prozess.ausgeführt(["git", "status", "--porcelain"])
// Verboten — wirft Fehler:
prozess.ausgeführt("git status")
Warum so streng? Stell dir vor, ein Skript baut ein Kommando aus User-Input:
// HYPOTHETISCH — geht in Kiste NICHT, weil String-args verboten:
nimm name = "ich; rm -rf /"
prozess.starte("echo " + name) // → würde rm ausführen!
Mit Liste-args geht das nicht — jedes Element ist ein eigenes Argument:
nimm name = "ich; rm -rf /"
prozess.ausgeführt(["echo", name]) // echo druckt den String literal
Das ist „Shell-Injection unmöglich-by-construction". Wer wirklich Shell-Features braucht (Pipes, Redirects), muss das explizit schreiben:
prozess.ausgeführt(["sh", "-c", "git status | head -5"])
So ist die Shell-Ausführung sichtbar im Code — Reviewer erkennen sofort, was passiert.
29.3 Optionen-Karte
Konsistent mit csv und prozess-Pattern: zweites Argument ist eine Karte mit benannten Schlüsseln.
| Schlüssel | Default | Beschreibung |
|---|---|---|
arbeitsverzeichnis |
aktuelles CWD | Working Directory |
umgebung |
aktuelle Env | zusätzliche/überschreibende Env-Vars |
eingabe |
"" |
stdin-Input |
zeitlimit_ms |
kein Timeout | Prozess nach N ms killen |
stderr_zu_stdout |
falsch |
stderr in stdout mergen |
// Programm in /tmp ausführen:
prozess.ausgabe(["ls"], {"arbeitsverzeichnis": "/tmp"})
// Mit eigener Env-Variable:
prozess.ausgabe(["python", "skript.py"], {"umgebung": {"DEBUG": "1"}})
// Stdin füttern:
nimm sortiert = prozess.ausgabe(["sort"], {"eingabe": "b\na\nc\n"})
// Timeout: nach 5 Sekunden killen:
prozess.ausgabe(["sleep", "60"], {"zeitlimit_ms": 5000})
// → Fehler: "Zeitlimit von 5000ms überschritten"
29.4 Praxis: Git-Status prüfen, Datei verarbeiten
nutze prozess
nutze datei
// Sind wir in einem Git-Repo?
wenn nicht prozess.erfolgreich(["git", "rev-parse", "--git-dir"]) {
sag "Bitte in einem Git-Repo ausführen."
umgebung.beende(1)
}
// Welche Dateien sind unstaged?
nimm status = prozess.ausgabe(["git", "status", "--porcelain"])
// Wenn Output nicht leer → es gibt Änderungen
wenn länge(status) > 0 {
sag "Unstaged changes:"
sag status
}
29.5 Was nicht in prozess v1 ist
- Streaming-stdout während Prozess läuft — kommt mit
bytes-Modul. - Async (Prozess starten, später warten) — synchron deckt 95 % der Use-Cases ab.
- Pipes zwischen Kiste-Prozessen — wer das braucht, nutzt
sh -c "a | b". - Rohe Bytes für stdout/stderr — UTF-8-only in v1. Nicht-UTF-8-Output → Fehler. Wer rohe Bytes braucht, wartet auf
bytes-Modul. - Process-Groups, Signal-Handling — Plattform-spezifisch, später bei Bedarf.