Files
ninlight-w600/tools/station/ninlight-station.service
T
Michael Sauer 1c077a15d0 fix(station): RuntimeDirectory-Race, Statusphase, off/ap_switch-Nachpruefung, Pi-Bestandskonfiguration
Fixrunde 1 zu Task 4:

- C1 (kritisch): die Unit leerte /run/ninlight-station bei jedem
  systemctl restart, weil RuntimeDirectoryPreserve fehlte - genau der
  Neustart, mit dem migrate/recovery on den Dienst hochfahren, wischte
  die eben geschriebene Modus-/Steuerdatei wieder weg, und der Server
  fiel still auf den Recovery-Default zurueck. Unit bekommt
  RuntimeDirectoryPreserve=restart, und start_and_verify() prueft nach
  dem Neustart zusaetzlich ausdruecklich nach, dass Modus und Phase noch
  stimmen.
- I1: status las die Phase aus status.json, die arm/listen (die den
  Dienst bewusst nicht neu starten) nie aktualisieren - jetzt kommt sie
  aus control.json.
- I2: off pruefte nach dem Herunterfahren nichts nach und konnte
  "Station aus" melden, waehrend ein Profil wegen haengendem
  NetworkManager weiterhin aktiv war - ap_switch() verifiziert das jetzt
  auch im Aus-Fall.
- I3: der Fehlerzweig von ap_switch (Mismatch nach dem Umschalten) war
  im bisherigen Test nie erreichbar; der nmcli-Stub kann das jetzt
  erzwingen.
- I4: neue Pflichtschluessel blockierten jeden Unterbefehl auf einem
  bereits eingerichteten Pi. setup_pi.sh ergaenzt fehlende Schluessel in
  einer bestehenden Konfiguration jetzt einzeln, statt sie unangetastet
  zu lassen; dafuer musste das Skript per bash-s-Heredocs und
  ueberschreibbaren Pfadvariablen erst testbar gemacht werden (neuer
  test_setup_pi.sh).

Dazu vier kleinere Punkte aus derselben Review: grep -Fqx statt grep -qx
fuer Profilnamen, install-Stub durch tee+chmod ersetzt (POSIX, kein
Sonderfall mehr fuer macOS), Rechtepruefung auf control.json in den
arm/listen-Testfaellen, stderr sauber von stdout getrennt in den
Warnungs-/Fehlerfaellen.
2026-09-13 19:04:23 +02:00

53 lines
2.5 KiB
Desktop File

[Unit]
Description=ninlight recovery station (HTTP image server)
# Ohne den Zugangspunkt hat der Server beim Start keine Adresse zum Binden.
# Bewusst kein BindsTo=NetworkManager.service: ein dadurch ausgeloester Stop
# gilt fuer systemd als sauber und wuerde von KEINER Restart=-Politik erneut
# gestartet - ein NetworkManager-Neustart wuerde den Server dann still und
# dauerhaft mitreissen. Stattdessen nur Start-Reihenfolge vorgeben und den
# Prozess bei jedem Absturz (z.B. Bind-Fehler nach einem NM-Neustart) per
# Restart=always in kurzen Abstaenden neu versuchen lassen.
After=network.target NetworkManager.service
# Steht der Zugangspunkt nicht, kann server.py 192.168.8.1 nicht binden und
# stirbt sofort; Restart=always versucht es alle RestartSec=2 erneut. Damit
# das nicht endlos das Journal flutet, sondern nach kurzer Zeit ehrlich
# aufgibt (und ninlight-station dann mit einer klaren Fehlermeldung reagieren
# kann statt in einer stillen Neustartschleife zu haengen), hier explizit
# gedeckelt statt sich auf systemds Vorgabewerte zu verlassen.
StartLimitIntervalSec=30
StartLimitBurst=5
[Service]
Type=simple
EnvironmentFile=/etc/ninlight-station.conf
ExecStart=/usr/bin/python3 /opt/ninlight-station/server.py --image-dir ${IMAGE_DIR} --mode-file /run/ninlight-station/mode
Restart=always
RestartSec=2
# Laeuft als root: Port 80 und - fuer 4c - die DHCP-Leases in
# /var/lib/NetworkManager (Verzeichnis 0700 root:root) sind sonst nicht erreichbar.
# Gegengewicht:
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
RuntimeDirectory=ninlight-station
# Ohne dies leert systemd /run/ninlight-station bei JEDEM Stop und Neustart, nicht
# nur beim allerersten Start - und ninlight-station (das CLI) schreibt mode/
# control.json immer VOR dem "systemctl restart", mit dem migrate/recovery on den
# Dienst (neu) starten. Ohne RuntimeDirectoryPreserve=restart wischt genau dieser
# Neustart die beiden gerade geschriebenen Dateien wieder weg, bevor der neue
# Serverprozess sie lesen kann - der Dienst faellt dann still auf den
# Recovery-Default zurueck (server.py resolve_mode()/read_control()), und ein
# ausdrueckliches "migrate on --listen" wird zu "Rettungsmodus" bzw. "auto"
# (Fixrunde 1, C1). "restart" (nicht "yes") reicht: das Verzeichnis muss nur einen
# Neustart ueberleben, nicht dauerhaft bestehen bleiben, wenn der Dienst regulaer
# gestoppt wird.
RuntimeDirectoryPreserve=restart
ReadWritePaths=/run/ninlight-station
RestrictAddressFamilies=AF_INET AF_UNIX
MemoryMax=128M
[Install]
WantedBy=multi-user.target