Kiste
DE

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.