Stromausfall während einer geprüften Agentenaktion führt zu unbekannten Ergebnissen
Ein Stromausfall während einer geprüften Agentenaktion kann zu einem unbekannten Ergebnis führen. Erfahre, wie sich Unterbrechungsgrenzen testen, Ergebnisse abgleichen und Wiederholungen sicher durchführen lassen.

Ein Stromausfall während einer geprüften Agentenaktion erzeugt nicht einfach einen Fehler. Er erzeugt ein Beweisproblem. Agent, lokales Gateway, Betriebssystem, Netzwerk und entfernter Dienst können jeweils an einer anderen Stelle stoppen. Wenn du dieses Durcheinander als «fehlgeschlagen» zusammenfasst, nur weil der Agent keine Antwort erhalten hat, wirst du irgendwann eine Aktion wiederholen, die bereits ausgeführt wurde.
Dieser Fehler passiert leicht, weil Protokolle wie eine Geschichte wirken. Ein Ermittler sieht eine genehmigte Aktion, eine ausgehende Anfrage und danach eine Lücke. Die Lücke fühlt sich wie eine Schlussfolgerung an. Das ist sie nicht. Sie bezeichnet ein Zeitfenster, in dem mehrere wesentlich unterschiedliche Ergebnisse möglich bleiben. Die richtige Reaktion hängt davon ab, welches System die benötigte Tatsache verwaltet.
Hier zeigt sich der Wert eines Audit-Trails. Er sollte festhalten, was das lokale System weiß, die unveränderte Form der gespeicherten Datensätze nachweisen und Unsicherheit sichtbar machen, statt sie zu überdecken. Er kann eine verlorene Antwort nicht in einen Beweis dafür verwandeln, dass ein Datenbankeintrag, eine Zahlung, ein Deployment oder ein entfernter Befehl nicht stattgefunden hat.
Ein Timeout ist eine Beweislücke, kein bestätigter Fehler
Ein Timeout sagt dir, dass ein Beteiligter vor Ablauf seiner Frist keine verwertbare Antwort beobachtet hat. Es sagt nicht, ob das Ziel die Anfrage erhalten, mit der Arbeit begonnen, sie festgeschrieben hat oder ob die Antwort auf dem Rückweg verloren ging.
Halte diese Ergebnisse in Vorfallnotizen und in jeder Benutzeroberfläche, die Agentenaktionen meldet, getrennt:
- Bestätigter Fehler: Das Ziel oder der lokale Executor lieferte dauerhafte Belege dafür, dass die angeforderte Operation abgelehnt oder zurückgesetzt wurde.
- Bestätigter Erfolg: Das System, das den geänderten Zustand verwaltet, lieferte eine Quittung, und eine anschließende Abfrage bestätigt den erwarteten Zustand.
- Unbekanntes Ergebnis: Die Aktion kann stattgefunden haben, aber die verfügbaren Belege können es weder bestätigen noch ausschließen.
- Nicht versucht: Das Gateway verweigerte die Aktion, bevor es die Arbeit an einen Executor oder Transport übergab.
«Unbekannt» ist keine vorsichtige Schreibweise für «wahrscheinlich fehlgeschlagen». Es ist ein Betriebszustand mit einem anderen Vorgehen. Du pausierst automatische Wiederholungen, bewahrst die Belege auf, fragst das maßgebliche System ab und entscheidest erst dann, ob eine Ausgleichsaktion oder Wiederholung sicher ist.
Oft wird zu früh ein weiteres Etikett eingeführt: «teilweise erfolgreich». Verwende es nur, wenn du die abgeschlossene und die unvollständige Teiloperation benennen kannst. Eine Deployment-Pipeline, die ein Artefakt erstellt, es aber nie freigeschaltet hat, liefert ein Teilergebnis, wenn beide Tatsachen bestätigt sind. Eine Anfrage, die verschwindet, nachdem der Client Bytes in einen Socket geschrieben hat, hat ein unbekanntes Ergebnis, selbst wenn die Anfrage einfach aussah.
RFC 9110 beschreibt dieselbe Unterscheidung in Protokollbegriffen. Nach einem Kommunikationsfehler erlaubt die Spezifikation die automatische Wiederholung idempotenter Methoden, weil die Wiederholung derselben beabsichtigten Operation dieselbe beabsichtigte Wirkung hat. Von der automatischen Wiederholung einer nicht idempotenten Anfrage rät sie ab, außer der Client kann feststellen, dass die ursprüngliche Anfrage nicht angewendet wurde, oder die Anwendung macht Wiederholungen sicher. Das ist eine semantische Regel, kein Transporttrick.
Ein Gateway für Agentenaktionen sollte die lokalen Tatsachen genau melden. «Anfrage gesendet, Abschluss nicht beobachtet» ist nützlich. «Aktion fehlgeschlagen» ist eine Behauptung, zu der der lokale Prozess möglicherweise nicht berechtigt ist.
Ein Stromausfall teilt eine Aktion in Dauerhaftigkeitsgrenzen
Eine Aktion kann mehrere Grenzen überschreiten, bevor jemand ein Endergebnis sieht. Schreibe sie auf, bevor du testest. Ein Test, der nur einen Prozess beendet, erzeugt sonst trügerische Sicherheit.
Eine typische HTTP-Aktion hat mindestens diese Grenzen:
- Das Gateway akzeptiert eine autorisierte Absicht und speichert sie lokal.
- Das Gateway erstellt die authentifizierte Anfrage und beginnt mit ihrer Übertragung.
- Der entfernte Dienst erhält genug von der Anfrage, um mit ihrer Verarbeitung zu beginnen.
- Der entfernte Dienst schreibt seine Nebenwirkung fest und erstellt eine Quittung.
- Das Gateway empfängt die Antwort und speichert das beobachtete Ergebnis.
Eine SSH-Aktion folgt einem ähnlichen Weg. Allerdings kann der entfernte Host einen Befehl starten, bevor der lokale Client dessen Exit-Status erfährt. Der Host kann außerdem Arbeit abspalten, die die Sitzung überlebt. Eine erfolgreiche TCP- oder SSH-Verbindung sagt nur sehr wenig darüber aus, an welcher Stelle ein Befehl gestoppt hat.
Lokale Schreibvorgänge haben eigene Grenzen. Ein Prozess kann ein Auditereignis anhängen, das Betriebssystem kann den Anhang in den Cache übernehmen, das Dateisystem kann Metadaten und Daten anordnen, und der Speicher kann die Bytes auch nach einem Stromausfall erhalten. Das sind keine austauschbaren Ereignisse.
Die POSIX-Spezifikation für fsync() besagt, dass der Aufruf die Übertragung der gepufferten Daten einer geöffneten Datei auf das Speichergerät anfordert und erst zurückkehrt, wenn die Operation abgeschlossen ist oder einen Fehler meldet. Die Begründung warnt außerdem, dass die tatsächliche Sicherheit von Implementierung und Speicherkonfiguration abhängt. Dieser Vorbehalt ist wichtig: Eine Anwendung darf aus einem erfolgreich zurückgekehrten Schreibaufruf nicht automatisch auf Sicherheit bei Stromverlust schließen.
Ordne für Untersuchungen jedem Datensatz eine Beweisklasse zu, statt jeden Zeitstempel als gleich dauerhaft zu behandeln:
| Beweisklasse | Was sie stützt | Was sie nicht stützt |
|---|---|---|
| Absicht akzeptiert | Das Gateway hat sich bereit erklärt, eine bestimmte Aktion zu versuchen | Dass eine Anfrage den Rechner verlassen hat |
| Versand begonnen | Das Gateway hat lokale Ausführung oder Transportarbeit begonnen | Dass das Ziel vollständige Eingaben erhalten hat |
| Entfernte Quittung | Das Ziel behauptet, eine Operation angenommen oder festgeschrieben zu haben | Dass das lokale System die Quittung vor dem Absturz gespeichert hat |
| Lokaler Abschlussdatensatz | Das Gateway hat ein Ergebnis beobachtet und gespeichert | Dass der entfernte Zustand durch spätere Arbeit unverändert bleibt |
| Abgleichsabfrage | Eine spätere Abfrage hat den Zustand des Ziels beobachtet | Den genauen Zeitpunkt der Zustandsänderung, sofern das Ziel ihn nicht festhält |
Diese Tabelle ist absichtlich streng. Eine Prozesszeile mit «Anfrage wird gesendet» ist ein Beleg für den Versand. Sie ist kein Beleg für die Zustellung. Ein Antworttext im Speicher ist ein Beobachtungsbeleg. Er ist erst dann ein dauerhafter lokaler Beleg, wenn dein Speicherpfad das getestete Fehlermodell überlebt.
Gib jeder Nebenwirkung vor dem Fehlertest eine Operationsidentität
Ein Ermittler kann eine unterbrochene Aktion nicht abgleichen, wenn das entfernte System keine stabile Möglichkeit hat, sie zu identifizieren. Füge eine Operationsidentität hinzu, bevor du einen Chaos-Test schreibst, nicht erst nachdem das erste Duplikat in der Produktion auftaucht.
Verwende nach Möglichkeit zwei IDs:
- Eine lokal erzeugte Aktions-ID für den einzelnen Versuch des Gateways.
- Eine vom Ziel erkannte Operations-ID, einen Idempotenzschlüssel, ein Anfrage-Token, eine Deployment-ID oder eine Transaktionsreferenz.
Beide können denselben Zufallswert enthalten, aber nimm nicht an, dass sie dasselbe bedeuten. Deine Aktions-ID identifiziert einen lokalen Auditdatensatz. Die entfernte ID wird erst nützlich, wenn das Ziel sie zusammen mit der Nebenwirkung speichert und eine Möglichkeit bietet, den daraus entstandenen Zustand abzurufen.
Bei einer API mit Idempotenzschlüsseln muss die Identität ausdrücklich in der Anfrage enthalten sein. Speichere außerdem einen Digest der relevanten Nutzdaten. So lässt sich erkennen, wenn ein Bediener versehentlich versucht, einen alten Schlüssel mit einer geänderten Anfrage wiederzuverwenden.
POST /v1/releases HTTP/1.1
Host: deploy.example.internal
Idempotency-Key: 8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1
Content-Type: application/json
{
"operation_id": "8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1",
"service": "catalog",
"artifact": "sha256:3c1f...",
"environment": "production"
}
Protokolliere weder den Authorization-Header noch das Bearer-Token oder einen vollständigen möglicherweise geheime Daten enthaltenden Body. Speichere Methode, Zielidentität, sichere Anfrage-Metadaten, Aktions-ID, Operations-ID und Nutzdaten-Digest. Du brauchst genug Belege, um Versuche zu vergleichen, ohne in deinem Auditsystem ein zweites Leck von Zugangsdaten zu erzeugen.
Ein brauchbarer Intent-Datensatz könnte so aussehen:
{
"event": "intent_accepted",
"action_id": "act_01JX8F3Z6Z",
"operation_id": "8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1",
"channel": "http",
"destination": "deploy.example.internal",
"method": "POST",
"path": "/v1/releases",
"payload_sha256": "3c1f...",
"authorization": "approved_for_session"
}
Dieser Datensatz verhindert einen häufigen Fehler bei Untersuchungen: Jemand vergleicht eine spätere Wiederholung nur anhand von Zeitstempel und Endpunkt mit der ersten Aktion, übersieht ein geändertes Artefakt oder Konto und erklärt zwei verschiedene Operationen für gleich.
Bei SSH muss die Operations-ID dort abgelegt werden, wo der entfernte Host sie behalten kann. Ein Shell-Befehl kann sie in strukturierten Protokollen führen, ein Deployment-Skript kann sie in einen Release-Datensatz schreiben oder ein entfernter Wrapper kann eine doppelte ID ablehnen. Verlasse dich nicht auf das Transkript des lokalen SSH-Clients als einzigen Beleg.
ssh [email protected] \
'/usr/local/bin/release --operation-id 8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1 --artifact sha256:3c1f...'
Wenn dieser Befehl einen Hintergrundprozess startet, muss der Prozess die Operations-ID speichern, bevor er etwas ändert. Sonst bleibt nach einem Verbindungsabbruch möglicherweise ein weiterarbeitender Host zurück, ohne dass sich die Arbeit zuverlässig finden lässt.
Simuliere Unterbrechungen an den Grenzen, die deine Entscheidung verändern
Ein sinnvoller Fehlertest beendet den Prozess an Punkten, die zu unterschiedlichen Entscheidungen des Ermittlers führen. Einen Client in einer Schleife zufällig zu beenden, findet zwar Fehler, erklärt aber nicht, was das Protokoll bedeutet.
Baue ein Testziel, das an kontrollierten Phasen pausieren und eine Abgleichsabfrage per Operations-ID beantworten kann. Es muss nicht aufwendig sein. Es muss den Unterschied zwischen empfangener Anfrage, festgeschriebener Nebenwirkung und gesendeter Antwort sichtbar machen.
Beginne mit fünf Fällen:
- Absturz vor der dauerhaften Speicherung der Absicht. Die Aktion sollte im dauerhaften lokalen Verlauf und beim Ziel fehlen. Wenn sich das Ziel geändert hat, ist die Reihenfolge deiner Operationen falsch oder eine andere Komponente hat die Aktion ausgelöst.
- Absturz nach der Speicherung der Absicht, aber vor dem Versand. Das Auditprotokoll sollte eine akzeptierte Aktion ohne Versanddatensatz zeigen. «Nicht versucht» ist nur dann zulässig, wenn das Gateway beweisen kann, dass es die Aktion nie an einen Transport oder Executor übergeben hat.
- Absturz während der Übertragung. Das Ziel kann nichts, eine Teilanfrage oder eine vollständige Anfrage sehen. Ordne das Ergebnis als unbekannt ein, solange das Ziel keine eindeutige Ablehnung oder Abfrageantwort liefert.
- Absturz nach dem entfernten Commit, aber vor der lokalen Speicherung des Abschlusses. Das Ziel sollte die Operation als abgeschlossen anzeigen, während im lokalen Verlauf das Abschlussereignis fehlt. Dieser Test legt gefährliche Wiederholungslogik offen.
- Absturz nach der lokalen Speicherung des Abschlusses, aber bevor der Agent die Antwort erhält. Das lokale Auditprotokoll enthält die Antwort, obwohl der Agent einen Timeout annimmt. Eine neue Agentensitzung muss den Aktionsdatensatz abfragen, statt blind eine zweite Operation auszulösen.
Ein lokales Testsystem kann Gateway und Testdienst mit benannten Pausendateien koordinieren. Die konkrete Implementierung kann abweichen, der Testvertrag jedoch nicht. Das System muss vor der Unterbrechung melden, welche Grenze erreicht wurde, und anschließend den Zielzustand für den Abgleich bewahren.
# Terminal 1: start the test destination with controlled pauses.
./test-api --pause-after=commit --state-file ./tmp/remote-state.json
# Terminal 2: run one authorized action with a known operation ID.
./gateway-test invoke \
--operation-id 8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1 \
--pause-file ./tmp/client-dispatch.pause
# When the destination reports "committed", terminate the local process.
kill -9 "$(pgrep -f 'gateway-test invoke')"
# Terminal 3: inspect the destination without issuing another mutation.
./test-api lookup 8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1
kill -9 testet den Absturz eines Prozesses. Es testet weder das Speicherverhalten bei einem harten Stromausfall noch macht es eine Aktion rückgängig, die der entfernte Dienst bereits angenommen hat. Diese Einschränkung ist beim Lernen der Ergebnisklassifizierung hilfreich. Sie zwingt das Team, den Tod des Aufrufers nicht als Beweis über das aufgerufene System zu behandeln.
Für echte Stromausfalltests verwende eine wegwerfbare Maschine oder eine virtualisierte Umgebung, in der sich abrupte Abschaltungen sicher wiederholen lassen. Ziehe nicht den Stecker eines Rechners, auf dem sich die einzige Kopie eines produktiven Tresors, von Auditmaterial oder eines Arbeitsverzeichnisses befindet. Speichere für jeden Lauf den genauen Build, Speichermodus, Testeingaben und die Zeitquelle. Ein Testergebnis ohne diesen Kontext ist nur eine Anekdote.
Ein Audit-Trail sollte sagen, was er weiß, und bewahren, was er nicht weiß
Ein gutes Auditprotokoll liest sich wie eine Reihe von Behauptungen mit klarer Reichweite. Es tut nicht so, als enthielte es die allwissende Wahrheit über Systeme, die es nicht beobachten kann.
Bei einer unterbrochenen Aktion solltest du einzelne Ereignisse aufzeichnen, statt ein veränderliches Statusfeld zu überschreiben. Eine nur anhängbare Folge kann die Tatsachen darstellen, ohne eine abschließende Antwort zu erfinden:
intent_accepted action=act_01JX8F3Z6Z op=8b4d... principal=agent-process
transport_started action=act_01JX8F3Z6Z channel=http
outcome_unobserved action=act_01JX8F3Z6Z reason=local-process-terminated
reconciled_success action=act_01JX8F3Z6Z receipt=rel_4921 source=remote-api
Die dritte Zeile darf nicht remote_failed lauten. Sie sagt nur, dass das Gateway kein endgültiges Ergebnis beobachten konnte. Die vierte Zeile fügt eine spätere Behauptung aus der Quelle hinzu, die den Release-Zustand verwaltet.
Diese Unterscheidung macht auch Manipulationsnachweise nützlicher. Eine Hashkette kann Änderungen am gespeicherten Auditmaterial aufdecken, aber kein Ereignis wiederherstellen, das nie dauerhaft gespeichert wurde. Verliert ein Rechner zwischen einem ausgehenden Aufruf und dem Anhängen eines Protokolleintrags den Strom, kann eine intakte Kette sauber vor dem Ergebnis der Aktion enden. Das bedeutet nicht unbedingt, dass die Kette beschädigt ist. Es ist eine Lücke, die einen Abgleich benötigt.
Sallyport erzeugt seine Sessions- und Aktivitätsjournale aus einem schreibblinden, verschlüsselten und hashverketteten Auditprotokoll. sp audit verify prüft diese Kette offline über dem Chiffretext. Das gibt Ermittlern eine starke Möglichkeit zu prüfen, ob der erhaltene lokale Verlauf verändert wurde. Das entfernte Ergebnis muss bei Bedarf weiterhin durch entfernte Belege geklärt werden.
Halte Autorisierungsbelege von Ergebnisbelegen getrennt. Eine Freigabe zeigt, dass ein Mensch oder eine konfigurierte Kontrolle eine Aktion erlaubt hat. Sie zeigt nicht, dass die Aktion abgeschlossen wurde. Wer diese Aussagen vermischt, meldet eine genehmigte, aber unterbrochene Produktionsänderung fälschlich als abgeschlossene Änderung.
Dasselbe gilt für Zeitstempel. Wandzeitstempel helfen beim Abgleich von Systemen, stellen aber keine globale Reihenfolge her, wenn Rechner voneinander abweichen oder Puffer Schreibvorgänge verzögern. Wenn die Reihenfolge wichtig ist, speichere Sequenznummern innerhalb jedes Journals, bewahre entfernte Quittungs-IDs auf und erfasse beim Abgleich die Zeitstempel des Dienstes selbst.
Netzwerkaufrufe brauchen einen entfernten Abgleich, keinen Optimismus
Wenn eine HTTP-Anfrage ihre Antwort verliert, ist das Ziel normalerweise die maßgebliche Quelle dafür, ob sich der angeforderte Zustand geändert hat. Frage es vor einer Wiederholung ab, und mache die Abfrage spezifisch genug, um diese Operation von ähnlicher Arbeit zu unterscheiden.
Die sicherste Reihenfolge für den Abgleich lautet:
- Suche die Operations-ID oder den Idempotenzschlüssel beim Ziel.
- Liefert das Ziel eine abgeschlossene Operation, vergleiche Ressourcen-IDs und Nutzdaten-Digest mit der ursprünglichen Absicht.
- Liefert es eine gespeicherte Ablehnung, bewahre diese Antwort als Fehlerbeleg auf.
- Gibt es keinen Datensatz, prüfe vor einer Wiederholung, ob die API verzögerte Verarbeitung, asynchrone Warteschlangen oder eine verzögerte Erstellung von Datensätzen dokumentiert.
- Wiederhole nur, wenn Semantik des Endpunkts und Belege die Wiederholung sicher machen.
Verwechsle eine GET-Anfrage nicht mit einer harmlosen Prüfung, nur weil sie eine sichere Methode verwendet. Manche APIs verbergen Arbeit hinter einem Leseendpunkt, und manche Antwort-Caches hinken dem Schreibpfad hinterher. Prüfe den Vertrag des Anbieters und rufe nach Möglichkeit die konkrete erstellte Ressource oder den Operationsdatensatz ab, statt eine breite Liste nach Zeit zu durchsuchen.
HTTP-Methoden helfen bei der Einordnung, entscheiden das Verhalten der Anwendung aber nicht. Ein PUT kann auf HTTP-Ebene idempotent sein, während der Server bei jedem Empfang doppelte E-Mails sendet, Nutzung berechnet oder einen Deployment-Hook auslöst. RFC 9110 weist ausdrücklich darauf hin, dass sich Idempotenz auf die angeforderte Wirkung bezieht, während ein Server weiterhin separate Protokolle führen oder andere Nebenwirkungen erzeugen kann. Deshalb ist die dokumentierte Operationsidentität des API-Betreibers wichtiger als ein Verb in einer Clientbibliothek.
Eine verbreitete, aber schlechte Empfehlung lautet: «Wiederhole jedes Timeout zweimal.» Sie klingt praktisch, weil viele Timeouts vorübergehend sind. Ist der Endpunkt nicht sicher wiederholbar, macht sie aus einem vorübergehenden Transportproblem doppelte Geldbewegungen, doppelte Kontoerstellungen oder zwei Produktions-Releases. Eine Wiederholungsrichtlinie muss Operationstyp, Idempotenzmechanismus, maximale Verzögerung und die für die Wiederholung erforderlichen Belege nennen.
Bietet ein entfernter Dienst weder Abfragen noch Idempotenzunterstützung, kann die ehrliche Antwort lauten, dass sich das Ergebnis nicht automatisch auflösen lässt. Baue um diese Einschränkung einen Ausgleichsprozess, etwa eine Warteschlange für menschliche Prüfungen mit dem exakten Anfrage-Fingerabdruck und einem schreibgeschützten Konto zur Prüfung des betroffenen Zustands.
SSH-Befehle brauchen Belege vom entfernten Host
Eine unterbrochene SSH-Sitzung lässt oft mehr Unklarheit zurück als ein API-Aufruf, weil der Befehl auf der anderen Seite noch ausgeführt werden kann, nachdem der Client verschwunden ist. Ein verlorener Exit-Status bedeutet nicht, dass der Befehl fehlgeschlagen ist. Es bedeutet, dass eine Beobachtung fehlt.
Vermeide eine einzige große Shell-Zeile mit mehreren Änderungen und ohne Prüfpunkte. Teile die entfernte Arbeit in Operationen mit eigenen IDs und dauerhaftem Zustand auf. Ein Deployment-Wrapper kann etwa für eine Operations-ID die Zustände received, validated, applied und completed speichern und anschließend einen schreibgeschützten Statusbefehl bereitstellen.
/usr/local/bin/release-status \
--operation-id 8b4dbdb6-61e1-49ea-a5b5-9ae225eb2af1
Der Wrapper sollte seinen Status speichern, bevor er eine nicht wiederholbare Aktion startet, nicht danach. Reserviert er eine Cloud-Ressource, veröffentlicht er ein Paket oder schaltet er Datenverkehr um, muss er die Quittung des Anbieters unter derselben Operations-ID aufbewahren. Ist das nicht möglich, sollte die Operation über eine entfernte Warteschlange laufen, die dies kann.
Sei bei Shell-Cleanup-Traps als Wiederherstellungsbeleg misstrauisch. Ein lokaler Trap läuft nach einem abrupten Stromausfall nicht. Ein entfernter Trap läuft nach einem erzwungenen Kill möglicherweise nicht, oder er läuft, während ein Kindprozess weiterarbeitet. Aufräumlogik kann das Chaos verringern, beweist aber nicht den Endzustand.
Verwende eine entfernte Markierung nur, wenn zwischen Markierung und Nebenwirkung eine sinnvolle Beziehung besteht. Eine an /tmp/action-done angehängte Zeile beweist nicht, dass eine Datenbankmigration festgeschrieben wurde. Ein Migrationstabelleneintrag in derselben Transaktion ist ein besserer Beleg. Ein vom Deployment-Controller erstellter Deploymentdatensatz ist noch besser.
Sallyport leitet SSH über seinen zustandslosen sp-ssh-Helfer weiter. Die gleiche Regel gilt jedoch hier: Der lokale Aktionsdatensatz kann belegen, was das Gateway versucht und beobachtet hat. Nur der entfernte Host oder das vom Befehl geänderte System kann ein unbeobachtetes entferntes Ergebnis klären.
Führe einen Ermittler durch ein unterbrochenes Release
Nehmen wir an, ein Agent fordert über einen HTTP-Endpunkt ein Produktions-Release an. Das Gateway speichert eine autorisierte Absicht mit der Aktions-ID act_01JX8F3Z6Z, der Operations-ID 8b4d..., dem Artefakt-Digest 3c1f... und einer Sitzungsfreigabe. Es beginnt mit der Anfrage. Der Release-Dienst schreibt das Release fest und weist die Quittung rel_4921 zu. Bevor die Antwort das Gateway erreicht, verliert der Laptop den Strom.
Nach dem Neustart meldet das Transkript des Agenten einen Timeout. Der lokale Audit-Trail endet bei transport_started. Wer diese Zeile als Beweis für einen Fehler behandelt, sendet dasselbe Release mit einer neuen Operations-ID erneut. Der Dienst erstellt ein zweites Release. Aktiviert der Endpunkt sofort, ist die zweite Anfrage vielleicht nur störend. Löst sie jedoch eine irreversible Migration aus, kann sie teuer werden.
Die richtige Untersuchung beginnt damit, automatische Wiederholungen für act_01JX8F3Z6Z einzufrieren. Prüfe die lokale Auditkette. Notiere das letzte erhaltene Ereignis, die Belege für die Beendigung des lokalen Prozesses, das Ziel, den Nutzdaten-Digest und die Operations-ID. Frage anschließend den Release-Dienst nach 8b4d... ab.
Drei Ergebnisse sind besonders hilfreich:
- Der Dienst liefert
rel_4921mit dem Artefakt-Digest3c1f.... Ordne die ursprüngliche Aktion nach dem Abgleich als bestätigten Erfolg ein. Der fehlende lokale Abschluss bleibt eine Auditlücke und ist kein Grund, das Release erneut auszuführen. - Der Dienst liefert eine dauerhafte, an
8b4d...gebundene Ablehnung. Ordne die Aktion als bestätigten Fehler ein. Bewahre den Ablehnungsgrund auf, bevor du über eine korrigierte Anfrage entscheidest. - Der Dienst liefert keinen Datensatz. Prüfe, ob er Anfragen vor dem Erstellen von Operationsdatensätzen in eine Warteschlange stellt und ob sein Abfragepfad verzögert ist. Kann er verzögerte Arbeit nicht ausschließen, bleibt das Ergebnis unbekannt. Eskaliere, statt blind zu wiederholen.
Entscheidend sind nicht das Timeout des Agenten, das Beenden des Gateway-Prozesses oder die Tatsache, dass ein Mensch die Aktion genehmigt hat. Diese Fakten sind wichtig, aber keiner von ihnen verwaltet den Release-Zustand.
Das Beispiel zeigt außerdem eine Designanforderung. Kann das Ziel nicht nach der Operations-ID suchen, muss das Gateway entweder unbeaufsichtigte, nicht wiederholbare Aktionen gegen dieses Ziel vermeiden oder einen menschlichen Abgleich verlangen. Gute Auditqualität kann eine API nicht ersetzen, die keine dauerhafte Möglichkeit bietet, ihre eigenen Nebenwirkungen zu identifizieren.
Wiederholungsregeln müssen eng genug sein, um schlechte Tage zu überstehen
Eine Wiederholungsrichtlinie sollte mehr sagen als «bei Netzwerkfehlern wiederholen». Schreibe sie als Entscheidungstabelle, der sowohl Implementierer als auch Mitarbeiter bei Vorfällen folgen können.
| Aktionstyp | Beleg nach einer Unterbrechung | Automatisch wiederholen? | Erforderliche Absicherung |
|---|---|---|---|
| Nur lesende Abfrage | Keine Antwort | Meistens ja | Begrenzte Wiederholungen und Zeitlimits des Ziels |
| Idempotente Änderung | Keine Antwort | Ja, wenn das Ziel eine stabile Identität berücksichtigt | Dieselbe Ressourcenidentität und derselbe Anfrageinhalt |
| Erstellen oder Auslösen einer Aktion | Keine Antwort | Erst nach Abgleich oder mit dokumentierter Idempotenz | Suche beim Ziel nach der Operations-ID |
| Geldbewegung oder zerstörerische Änderung | Keine Antwort | Nein | Menschliche Prüfung und Abgleich mit dem maßgeblichen Zustand |
| SSH-Befehl mit Nebenwirkungen | Sitzung verloren | Nein | Status der entfernten Operation und Ablehnung von Duplikaten |
Lass Agenten bei der Wiederherstellung keine neue Operations-ID erfinden. Das erzeugt auf subtile Weise Duplikate. Ist eine Wiederholung zulässig, verwende dieselbe vom Ziel erkannte Identität und belege, dass die Nutzdaten der ursprünglichen Absicht entsprechen. Hat sich die gewünschte Änderung geändert, handelt es sich um eine neue Aktion, die eine neue Autorisierungsentscheidung verdient.
Lege einen Endzustand für ungelöste Aktionen fest. «Unbekannt, Abgleich ausstehend» ist besser als ein Auftrag, der für immer wiederholt wird, weil die Zustandsmaschine keine Unsicherheit zulässt. Gib diesem Zustand einen Verantwortlichen, eine Frist und einen Eskalationsweg. Andernfalls wird eine alte unklare Aktion Wochen später mit unvollständigen entfernten Protokollen zur Überraschung.
Bewahre Belege, bevor Systeme die Antwort verlieren
Die erste Stunde nach einer Unterbrechung ist die Zeit, in der entfernte Dienste noch Anfrage-Traces, Warteschlangeneinträge und den frischen Kontext der Bediener haben. Sichere die Fakten, bevor Aufbewahrungsfristen, Cache-Räumungen oder ein weiteres Deployment sie entfernen.
Bewahre das lokale Auditmaterial in seiner ursprünglichen Form auf und prüfe es, bevor du Auszüge in ein Ticket kopierst. Notiere Aktions-ID, Operations-ID, Ziel, Nutzdaten-Digest, Autorisierungsdatensatz, letztes lokales Ereignis und Zeitpunkt des lokalen Neustarts. Sammle anschließend den entfernten Operationsdatensatz, die Ressourcenrevision, die Anfrage-ID des Anbieters und die für die Antwort verwendete Zeitquelle des Dienstes.
Repariere den Verlauf nicht, indem du ein gefälschtes Abschlussereignis hinzufügst. Füge stattdessen ein späteres Abgleichsereignis hinzu, das Quelle und Belege nennt. Ermittler müssen die ursprüngliche Grenze sehen, weil diese Grenze zeigt, was das System zu diesem Zeitpunkt wusste.
Die dauerhafte Lehre ist unangenehm, aber einfach: Eine geprüfte Aktion kann gut autorisiert und sorgfältig protokolliert sein und nach einem Stromausfall trotzdem ein unbekanntes entferntes Ergebnis haben. Baue Aktionsidentitäten, entfernte Quittungen und Abgleichswege ein, bevor du einem autonomen Agenten Arbeit überlässt, die nicht sicher zweimal ausgeführt werden kann. Wenn im falschen Moment das Licht ausgeht, entscheiden diese Vorkehrungen darüber, ob dein Team eine Lücke untersucht oder einen zweiten Vorfall erzeugt.
FAQ
Bedeutet ein fehlender Abschlussdatensatz im Auditprotokoll, dass die Agentenaktion fehlgeschlagen ist?
Nein. Ein fehlender Erfolgsdatensatz kann bedeuten, dass der Prozess starb, bevor er den Datensatz schrieb, nachdem das entfernte System die Anfrage angenommen hatte oder während der Datensatz noch in flüchtigen Puffern lag. Behandle das Ergebnis als unbekannt, bis eine Quelle, die den betroffenen Zustand verwaltet, etwas anderes bestätigt.
Ist kill -9 eine gute Simulation eines Stromausfalls?
Normalerweise nicht. kill -9 beendet einen lokalen Prozess ohne Zeit für Aufräumarbeiten. Das ist nützlich, um Absturzgrenzen zu testen. Es trennt jedoch nicht die Stromversorgung der Speicherhardware und macht keine Arbeit rückgängig, die ein entfernter Dienst bereits angenommen hat. Allein damit lässt sich das Verhalten bei Stromausfall daher nicht nachweisen.
Wie kann ich einen API-Aufruf nach einem Timeout sicher wiederholen?
Verwende einen Idempotenzschlüssel, wenn die entfernte API ihn unterstützt, und frage den Anbieter anschließend mit diesem Schlüssel oder der ID der erstellten Ressource ab. Wenn beides nicht vorhanden ist, führe vor dem erneuten Aufruf eine Abgleichsabfrage durch. Eine zweite Anfrage kann sonst eine zweite Nebenwirkung erzeugen.
Was ist ein Idempotenzschlüssel, und verhindert er doppelte Aktionen?
Ein Idempotenzschlüssel ermöglicht es einem Dienst, zwei Übermittlungen als dieselbe beabsichtigte Operation zu erkennen. Er schützt nur, wenn der entfernte Dienst ihn für den betreffenden Endpunkt, den Zeitraum und die Anfrageidentität speichert und durchsetzt. Ein Header, den nur dein eigener Client protokolliert und den der Server ignoriert, ändert nichts.
Kann ein manipulationssicheres Auditprotokoll beweisen, dass eine entfernte Aktion erfolgreich war?
Nein. Eine Hashkette kann zeigen, ob erhaltene Auditdatensätze verändert, aus der Mitte entfernt oder in erkennbarer Weise neu angeordnet wurden. Sie kann nicht beweisen, dass eine entfernte Zahlung, ein Deployment oder ein SSH-Befehl abgeschlossen wurde, wenn der lokale Rechner vor dem Speichern der letzten Belege den Strom verlor.
Was ist der Unterschied zwischen einer Aktions-ID und einem entfernten Beleg?
Eine Aktions-ID benennt den Versuch in deinem eigenen System. Ein entfernter Beleg wird vom System ausgestellt, das das Ergebnis verwaltet, etwa als Deployment-ID, Transaktions-ID, Revisionsnummer oder Provider-Anfrage-ID. Ermittler brauchen beides, weil die IDs unterschiedliche Fragen beantworten.
Kann ich dem Exit-Code eines SSH-Befehls nach einem Verbindungsabbruch vertrauen?
Der SSH-Exit-Status ist nur aussagekräftig, wenn der Client ihn empfangen und dauerhaft aufgezeichnet hat. Bricht die Verbindung ab, nachdem der entfernte Rechner den Befehl gestartet hat, kann der Befehl beendet werden, fehlschlagen oder nach dem Verschwinden des Clients weiterlaufen. Gib dem entfernten Befehl eine eindeutige Operations-ID und prüfe die entfernten Protokolle oder den resultierenden Zustand.
Was sollte ein Auditdatensatz enthalten, bevor eine Agentenaktion beginnt?
Ein dauerhafter Intent-Datensatz sollte eine eindeutige Aktions-ID, die Identität des Aufrufers, das Ziel, den Operationstyp, einen Digest oder eine sichere Darstellung der Parameter, die Autorisierungsentscheidung und den Zeitpunkt enthalten, zu dem das Gateway die Verantwortung übernommen hat. Schreibe keine Zugangsdaten oder sensiblen Anfrageinhalte in den Datensatz, nur um ihn vollständiger zu machen.
Kann ich eine POST-Anfrage nach einem unterbrochenen Netzwerkaufruf wiederholen?
Ein POST ist nur dann ein guter Kandidat für eine Wiederholung, wenn die Anwendung ihn mit einer Operations-ID oder einem Idempotenzmechanismus idempotent macht. HTTP-Methodennamen beschreiben die Standardsemantik, aber der Betreiber des Endpunkts entscheidet, ob wiederholte Anfragen doppelte Nebenwirkungen erzeugen.
Was sollte ein Ermittler zuerst tun, nachdem eine Agentenaktion unterbrochen wurde?
Bewahre das lokale Auditmaterial auf, notiere die Rechner- und Dienstzeiten, stoppe automatische Wiederholungen für diese Aktion und frage das maßgebliche entfernte System ab. Ordne die Aktion anschließend als bestätigten Erfolg, bestätigten Fehler oder unbekanntes Ergebnis ein und dokumentiere die dafür verwendeten Belege.