Assistent mit Menuefuehrung, dazu zwei Haertungen

kerio_tui.py fuehrt durch Umbenennung und Uebernahme, ohne dass man
Parameter kennen muss: Benutzer und Domains kommen zur Auswahl, verwaiste
Mailbox-Verzeichnisse findet der Assistent selbst, und vor dem Ausfuehren
zeigt er den gleichwertigen Kommandozeilenaufruf. Nur curses aus der
Standardbibliothek, keine neue Abhaengigkeit.

Beim Durchfahren ueber ein PTY kamen zwei Dinge heraus:

keypad(True) loest die Pfeiltasten auf diesem Server nicht auf - getch()
liefert 27, 91, 66 statt KEY_DOWN, wofuer ein unpassendes terminfo
genuegt. Das fuehrende ESC haette als "zurueck" gegolten und den
Assistenten bei jedem Pfeildruck verlassen. Er loest die Sequenzen jetzt
selbst auf; ein einzelnes ESC wirkt weiterhin als Abbruch.

Und: Bricht die Verbindung weg, waehrend Kerio gestoppt ist, stirbt das
Script an SIGHUP und laesst den Dienst unten - genau so passiert, als der
Testtreiber die Verbindung schloss. ServiceController.abgesichert() faengt
SIGHUP, SIGTERM und SIGINT ab und startet den Dienst wieder, bevor der
Abbruch durchgereicht wird. Gegen den Testserver geprueft: Signal mitten
im Stopp-Fenster, Dienst kommt hoch, Daten unberuehrt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck
2026-08-07 14:54:33 +02:00
co-authored by Claude Opus 5
parent b9cbf65fac
commit 24070cba4e
5 changed files with 751 additions and 69 deletions
+33
View File
@@ -8,9 +8,11 @@ Gemeinsame Bausteine fuer die Kerio-Connect-Scripts:
from __future__ import annotations
import contextlib
import http.cookiejar
import json
import shutil
import signal
import ssl
import subprocess
import sys
@@ -282,6 +284,37 @@ class ServiceController:
f"Dienst '{self.name}' laeuft nach {self.wait_seconds}s immer noch. Abbruch."
)
@contextlib.contextmanager
def abgesichert(self, war_aktiv: bool):
"""Startet den Dienst wieder, wenn das Script abgeschossen wird.
Diese Scripts laufen ueblicherweise ueber SSH. Bricht die Verbindung
weg, kommt SIGHUP - und ohne Vorkehrung bliebe Kerio gestoppt
zurueck, weil der Prozess stirbt, bevor er ihn wieder starten kann.
Dasselbe gilt fuer SIGTERM und Strg-C.
"""
def behandle(signalnummer, _rahmen):
print(f"\n Signal {signalnummer} empfangen - Kerio wird wieder "
"gestartet, dann Abbruch.", file=sys.stderr)
if war_aktiv:
self.start()
raise SystemExit(130)
vorher = {}
for signalnummer in (signal.SIGHUP, signal.SIGTERM, signal.SIGINT):
try:
vorher[signalnummer] = signal.signal(signalnummer, behandle)
except (ValueError, OSError):
pass # z. B. wenn nicht im Hauptthread
try:
yield
finally:
for signalnummer, handler in vorher.items():
try:
signal.signal(signalnummer, handler)
except (ValueError, OSError):
pass
def start(self) -> None:
if self.mode == "none":
return