- Startseite
- Documentation
- Nativ
- Natives Shell-, PTY-, Prozess- und Tastatur-Interna
Natives Shell-, PTY-, Prozess- und Tastatur-Interna
Dieses Dokument behandelt die Ausführungs-/Prozess-/Terminal-Primitive in @f5-sales-demo/pi-natives: shell, pty, ps und keys, unter Verwendung der Architekturbegriffe aus docs/natives-architecture.md.
Implementierungsdateien
Abschnitt betitelt „Implementierungsdateien“crates/pi-natives/src/shell.rscrates/pi-natives/src/shell/windows.rs(nur Windows)crates/pi-natives/src/pty.rscrates/pi-natives/src/ps.rscrates/pi-natives/src/keys.rscrates/pi-natives/src/task.rs(gemeinsames Abbruchverhalten, verwendet von shell/pty)packages/natives/src/shell/index.tspackages/natives/src/shell/types.tspackages/natives/src/pty/index.tspackages/natives/src/pty/types.tspackages/natives/src/ps/index.tspackages/natives/src/ps/types.tspackages/natives/src/keys/index.tspackages/natives/src/keys/types.tspackages/natives/src/bindings.ts
Schichtzuständigkeit
Abschnitt betitelt „Schichtzuständigkeit“- TS-Wrapper-/API-Schicht (
packages/natives/src/*): typisierte Einstiegspunkte, Abbruchoberfläche (timeoutMs,AbortSignal) und JS-Ergonomie. - Rust-N-API-Modulschicht (
crates/pi-natives/src/*): Shell-/PTY-Prozessausführung, Prozessbaum-Traversierung/-Beendigung und Tastensequenz-Analyse. - Validierungs-Gate (
native.ts, Architekturebene): stellt sicher, dass erforderliche Exporte (Shell,executeShell,PtySession,killTree,listDescendants, Schlüsselhilfsfunktionen) vorhanden sind, bevor Wrapper verwendet werden.
Shell-Subsystem (shell)
Abschnitt betitelt „Shell-Subsystem (shell)“API-Modell
Abschnitt betitelt „API-Modell“Zwei Ausführungsmodi werden bereitgestellt:
- Einmalig über
executeShell(options, onChunk?). - Persistente Sitzung über
new Shell(options?), dann wiederholtesshell.run(...).
Beide streamen die Ausgabe über einen threadsicheren Callback und geben { exitCode?, cancelled, timedOut } zurück.
Sitzungserstellung und Umgebungsmodell
Abschnitt betitelt „Sitzungserstellung und Umgebungsmodell“Rust erstellt brush_core::Shell mit:
- nicht-interaktivem Modus,
do_not_inherit_env: true,- expliziter Umgebungsrekonstruktion aus der Host-Umgebung,
- Ausschlussliste für shell-sensitive Variablen (
PS1,PWD,SHLVL, Bash-Funktionsexporte usw.).
Verhalten der Sitzungsumgebung:
ShellOptions.sessionEnvwird einmalig bei der Sitzungserstellung angewendet.ShellRunOptions.envist befehlsbezogen (EnvironmentScope::Command) und wird nach jedem Lauf zurückgesetzt.PATHwird unter Windows speziell mit Groß-/Kleinschreibungs-unempfindlicher Deduplizierung zusammengeführt.
Nur-Windows-Pfaderweiterung (shell/windows.rs): Erkannte Git-for-Windows-Pfade (cmd, bin, usr/bin) werden angehängt, sofern vorhanden und noch nicht enthalten.
Laufzeit-Lebenszyklus und Zustandsübergänge
Abschnitt betitelt „Laufzeit-Lebenszyklus und Zustandsübergänge“Die persistente Shell (Shell.run) verwendet diese Zustandsmaschine:
- Inaktiv/Nicht initialisiert:
session: None. - Laufend: das erste
run()erstellt die Sitzung verzögert, speichert dascurrent_abort-Token und führt den Befehl aus. - Abgeschlossen + Keepalive: wenn der Ausführungssteuerungsfluss
Normalist, wirdcurrent_abortgelöscht und die Sitzung wiederverwendet. - Abgeschlossen + Abbau: wenn der Steuerungsfluss schleifen-/skript-/shell-exit-bezogen ist (
BreakLoop,ContinueLoop,ReturnFromFunctionOrScript,ExitShell), wird die Sitzung verworfen (session: None). - Abgebrochen/Zeitüberschreitung: Der Lauf-Task wird abgebrochen, Wartezeit (2 s), dann erzwungener Abbruch; Sitzung wird verworfen.
- Fehler: Sitzung wird verworfen.
Die einmalige Shell (executeShell) erstellt und verwirft bei jedem Aufruf immer eine neue Sitzung.
Streaming-/Ausgabeverhalten
Abschnitt betitelt „Streaming-/Ausgabeverhalten“- Stdout/Stderr werden in eine gemeinsame Pipe geleitet und gleichzeitig gelesen.
- Der Leseprozess dekodiert UTF-8 inkrementell; ungültige Bytesequenzen erzeugen
U+FFFD-Ersatz-Chunks. - Nach Abschluss des Prozesses hat der Ausgabe-Drain Leerlauf-/Maximumsbeschränkungen (
250 msLeerlauf,2 sMaximum), um ein Hängenbleiben bei Hintergrundjobs zu vermeiden, die Dateideskriptoren offenhalten.
Abbruch, Zeitüberschreitung und Hintergrundjobs
Abschnitt betitelt „Abbruch, Zeitüberschreitung und Hintergrundjobs“CancelTokenwird austimeoutMsund einem optionalenAbortSignalkonstruiert.- Bei Abbruch/Zeitüberschreitung wird der Shell-Abbruch-Token ausgelöst, anschließend erhält der Task ein 2-s-Zeitfenster für einen geordneten Abbruch, bevor ein erzwungener Abbruch erfolgt.
- Bei einem Abbruch werden Hintergrundjobs beendet (
TERM, dann verzögertesKILL) unter Verwendung von Brush-Job-Metadaten.
Verhalten von Shell.abort():
- bricht nur den aktuell laufenden Befehl für diese
Shell-Instanz ab, - ist eine erfolgreiche Nulloperation, wenn nichts ausgeführt wird.
Fehlerverhalten
Abschnitt betitelt „Fehlerverhalten“Häufig auftretende Fehler umfassen:
- Sitzungsinitialisierungsfehler (
Failed to initialize shell), - Arbeitsverzeichnisfehler (
Failed to set cwd), - Fehler beim Setzen/Zurücksetzen der Umgebung,
- Snapshot-Quellfehler,
- Fehler beim Erstellen/Klonen von Pipes,
- Ausführungsfehler (
Shell execution failed: ...), - Task-Wrapper-Fehler (
Shell execution task failed: ...).
Ergebnisebene der Abbruch-Flags:
- Zeitüberschreitung ->
exitCode: undefined,timedOut: true. - Abbruchsignal ->
exitCode: undefined,cancelled: true.
PTY-Subsystem (pty)
Abschnitt betitelt „PTY-Subsystem (pty)“API-Modell
Abschnitt betitelt „API-Modell“new PtySession() stellt bereit:
start(options, onChunk?) -> Promise<{ exitCode?, cancelled, timedOut }>write(data)resize(cols, rows)kill()
Laufzeit-Lebenszyklus und Zustandsübergänge
Abschnitt betitelt „Laufzeit-Lebenszyklus und Zustandsübergänge“PtySession-Zustandsmaschine:
- Inaktiv:
core: None. - Reserviert:
start()installiert den Steuerkanal synchron (core: Some), bevor die asynchrone Arbeit beginnt, sodasswrite/resize/killsofort gültig werden. - Laufend: Die blockierende PTY-Schleife verarbeitet den Kindprozesszustand, Leseereignisse, Abbruch-Heartbeat und Steuernachrichten.
- Terminal geschlossen: Kindprozess-Exit + Leseabschluss.
- Abgeschlossen:
corewird nach Abschluss des Start-Tasks immer aufNonezurückgesetzt (Erfolg oder Fehler).
Nebenläufigkeits-Guard:
- Ein Start während bereits ausgeführter Sitzung gibt
PTY session already runningzurück.
Spawn-/Anhänge-/Schreib-/Lese-/Beendigungsmuster
Abschnitt betitelt „Spawn-/Anhänge-/Schreib-/Lese-/Beendigungsmuster“- PTY wird über
portable_pty::native_pty_system().openpty(...)geöffnet. - Befehle werden derzeit als
sh -lc <command>mit optionalemcwdund Umgebungsüberschreibungen ausgeführt. write()sendet rohe Bytes an PTY-Stdin.resize()begrenzt Dimensionen (cols 20..400,rows 5..200) und ruft die Master-Größenänderung auf.kill()markiert den Lauf als abgebrochen und beendet den Kindprozess.
Ausgabepfad:
- ein dedizierter Leser-Thread liest den Master-Stream,
- inkrementelle UTF-8-Dekodierung mit
U+FFFD-Ersatz bei ungültigen Bytes, - Chunks werden über den N-API-Threadsafe-Callback weitergeleitet.
Abbruch- und Zeitüberschreitungssemantik
Abschnitt betitelt „Abbruch- und Zeitüberschreitungssemantik“timeoutMsundAbortSignalspeisen einenCancelToken.- Die Schleife ruft periodisch
ct.heartbeat()auf; der Abbruch löst das Beenden des Kindprozesses aus. - Die Zeitüberschreitungsklassifizierung ist zeichenkettenbasiert (Teilstring
"Timeout"im Heartbeat-Fehler).
Fehlerverhalten
Abschnitt betitelt „Fehlerverhalten“Fehlerfälle umfassen:
- PTY-Zuweisungs-/Öffnungsfehler,
- PTY-Spawn-Fehler,
- Fehler beim Erwerb von Writer/Reader,
- Fehler beim Kindprozessstatus/-warten,
- Lock-Vergiftung,
- Steuerkanal-Trennung (
PTY session is no longer available).
Steueraufruf-Fehler bei nicht laufender Sitzung:
write/resize/killgebenPTY session is not runningzurück.
Prozessbaum-Subsystem (ps)
Abschnitt betitelt „Prozessbaum-Subsystem (ps)“API-Modell
Abschnitt betitelt „API-Modell“killTree(pid, signal) -> numberlistDescendants(pid) -> number[]
Der TS-Wrapper registriert außerdem die native Kill-Tree-Integration in gemeinsame Dienstprogramme über setNativeKillTree(native.killTree).
Plattformspezifische Implementierung
Abschnitt betitelt „Plattformspezifische Implementierung“- Linux: liest rekursiv
/proc/<pid>/task/<pid>/children. - macOS: verwendet
libprocproc_listchildpids. - Windows: erstellt einen Snapshot der Prozesstabelle mit
CreateToolhelp32Snapshot, baut eine Eltern->Kinder-Zuordnung auf und beendet mitOpenProcess(PROCESS_TERMINATE)+TerminateProcess.
Kill-Tree-Verhalten
Abschnitt betitelt „Kill-Tree-Verhalten“- Nachkommen werden rekursiv gesammelt.
- Die Beendigungsreihenfolge ist bottom-up (tiefste Nachkommen zuerst), um Neu-Elternschaft von Waisen zu reduzieren.
- Der Root-PID wird zuletzt beendet.
- Der Rückgabewert ist die Anzahl erfolgreicher Beendigungen.
Signalverhalten:
- POSIX: Das angegebene
signalwird ankillübergeben. - Windows:
signalwird ignoriert; die Beendigung ist eine bedingungslose Prozessbeendigung.
Fehlerverhalten
Abschnitt betitelt „Fehlerverhalten“Dieses Modul wirft absichtlich keine Fehler auf der API-Oberfläche:
- fehlende/nicht zugängliche Prozessbaumzweige werden übersprungen,
- Kill-Fehler pro PID werden als erfolglos gezählt (keine Fehler),
- ein Nachschlage-Fehltreffer liefert typischerweise
[]vonlistDescendantsund0vonkillTree.
Tastaturanalyse-Subsystem (keys)
Abschnitt betitelt „Tastaturanalyse-Subsystem (keys)“API-Modell
Abschnitt betitelt „API-Modell“Bereitgestellte Hilfsfunktionen:
parseKey(data, kittyProtocolActive)matchesKey(data, keyId, kittyProtocolActive)parseKittySequence(data)matchesKittySequence(data, expectedCodepoint, expectedModifier)matchesLegacySequence(data, keyName)
Analysemodell
Abschnitt betitelt „Analysemodell“Der Parser kombiniert:
- direkte Einzelbyte-Zuordnungen (
enter,tab,ctrl+<Buchstabe>, druckbares ASCII), - O(1)-Legacy-Escape-Sequenz-Nachschlagen (PHF-Map),
- xterm-
modifyOtherKeys-Analyse, - Kitty-Protokoll-Analyse (
CSI u,CSI ~,CSI 1;...<Buchstabe>), - Normalisierung zu Tasten-IDs (
ctrl+c,shift+tab,pageUp,f5usw.).
Modifikatorverarbeitung:
- Nur Shift-/Alt-/Ctrl-Bits werden für den Tastenabgleich verglichen,
- Lock-Bits werden vor dem Vergleich maskiert.
Layout-Verhalten:
- Der Basis-Layout-Fallback ist absichtlich eingeschränkt, sodass remappte Layouts keine falschen Übereinstimmungen für ASCII-Buchstaben/-Symbole erzeugen.
Fehlerverhalten
Abschnitt betitelt „Fehlerverhalten“- Nicht erkannte oder ungültige Sequenzen erzeugen
nullaus Parse-Funktionen. - Abgleichsfunktionen geben
falsebei Parse-Fehler oder Nichtübereinstimmung zurück. - Kein geworfener Fehler für fehlerhafte Tastatureingaben.
JS-Wrapper-API ↔ Rust-Export-Zuordnung
Abschnitt betitelt „JS-Wrapper-API ↔ Rust-Export-Zuordnung“Shell + PTY + Prozess
Abschnitt betitelt „Shell + PTY + Prozess“| TS-Wrapper-API | Rust-N-API-Export | Hinweise |
|---|---|---|
executeShell(options, onChunk?) | executeShell (execute_shell) | Einmalige Shell-Ausführung |
new Shell(options?) | Shell-Klasse | Persistente Shell-Sitzung |
shell.run(options, onChunk?) | Shell::run | Sitzung bei Keepalive-Steuerungsfluss wiederverwenden |
shell.abort() | Shell::abort | Bricht aktiven Lauf für diese Shell-Instanz ab |
new PtySession() | PtySession-Klasse | Zustandsbehaftete PTY-Sitzung |
pty.start(options, onChunk?) | PtySession::start | Interaktiver PTY-Lauf |
pty.write(data) | PtySession::write | Rohe Stdin-Weiterleitung |
pty.resize(cols, rows) | PtySession::resize | Begrenzte Terminaldimensionen |
pty.kill() | PtySession::kill | Erzwingt die Beendigung des aktiven PTY-Kindprozesses |
killTree(pid, signal) | killTree (kill_tree) | Kindprozesse-zuerst-Prozessbaum-Beendigung |
listDescendants(pid) | listDescendants (list_descendants) | Rekursive Nachkommenauflistung |
| TS-Wrapper-API | Rust-N-API-Export | Hinweise |
|---|---|---|
matchesKittySequence(data, cp, mod) | matchesKittySequence (matches_kitty_sequence) | Kitty-Codepoint+Modifikator-Abgleich |
parseKey(data, kittyProtocolActive) | parseKey (parse_key) | Normalisierter Tasten-ID-Parser |
matchesLegacySequence(data, keyName) | matchesLegacySequence (matches_legacy_sequence) | Exakte Legacy-Sequenz-Map-Prüfung |
parseKittySequence(data) | parseKittySequence (parse_kitty_sequence) | Strukturiertes Kitty-Parse-Ergebnis |
matchesKey(data, keyId, kittyProtocolActive) | matchesKey (matches_key) | High-Level-Tastenabgleich |
Bereinigung verlassener Sitzungen und Finalisierungshinweise
Abschnitt betitelt „Bereinigung verlassener Sitzungen und Finalisierungshinweise“- Persistente Shell-Sitzung: Wenn ein Lauf abgebrochen/durch Zeitüberschreitung beendet/fehlergeschlagen/ohne Keepalive-Steuerungsfluss ist, verwirft Rust explizit den internen Sitzungszustand. Erfolgreiche normale Läufe behalten die Sitzung zur Wiederverwendung.
- PTY-Sitzung:
corewird immer nach Abschluss vonstart()gelöscht, einschließlich Fehlerpfade. - Kein expliziter JS-Finalizer-gesteuerter Kill-Vertrag wird durch Wrapper bereitgestellt; die Bereinigung ist primär an Laufabschluss-/Abbruchpfade gebunden. Aufrufer sollten
timeoutMs,AbortSignal,shell.abort()oderpty.kill()für einen deterministischen Abbau verwenden.