Private
Public Access
145 lines
7.6 KiB
Markdown
145 lines
7.6 KiB
Markdown
# Versionierte Updates auf dem Raspberry Pi
|
|
|
|
`tools/upload_to_pi.sh` überträgt per SSH/rsync eine neue Version und richtet
|
|
bei jedem angewendeten Update den systemd-Autostart der WebUI ein. Ohne
|
|
`--apply` zeigt es nur eine lokale Vorschau und verbindet sich nicht zum Pi.
|
|
|
|
## Auf dem Laptop ausführen
|
|
|
|
Das folgende Beispiel verwendet den vom Nutzer bestätigten SSH-Benutzer,
|
|
Hostnamen und Projektordner. Der absolute Home-Pfad muss auf dem Pi stimmen:
|
|
|
|
```bash
|
|
bash tools/upload_to_pi.sh --user marcinator_2 --host raspi5wlan.local \
|
|
--remote-dir /home/marcinator_2/halloween --web-host 0.0.0.0
|
|
```
|
|
|
|
Zum tatsächlichen Update denselben Befehl mit `--apply` ausführen:
|
|
|
|
```bash
|
|
bash tools/upload_to_pi.sh --user marcinator_2 --host raspi5wlan.local \
|
|
--remote-dir /home/marcinator_2/halloween --web-host 0.0.0.0 --apply
|
|
```
|
|
|
|
`--web-host 0.0.0.0` ermöglicht den gewünschten Heimnetzzugriff auf
|
|
`http://raspi5wlan.local:8000`. Die WebUI hat noch keinen Login; keine
|
|
Router-Portfreigabe einrichten. Mit `--web-host 127.0.0.1` stattdessen den
|
|
SSH-Tunnel aus `SOFTWARE.md` verwenden. Ohne Angabe bleibt die gespeicherte
|
|
Wahl erhalten; beim ersten Update gilt Loopback. `--install-service` wird
|
|
weiterhin akzeptiert, ist aber nicht mehr erforderlich.
|
|
|
|
Autostart heißt: Der Webdienst startet beim Hochfahren des Pi. Ein Browser
|
|
auf dem Laptop wird dadurch nicht automatisch geöffnet.
|
|
|
|
## Voraussetzungen
|
|
|
|
- Laptop: `bash`, `python3`, `ssh`, `rsync`.
|
|
- Pi: `bash`, `rsync`, `flock`, `runuser` (util-linux), `python3-venv`,
|
|
`python3-picamera2`, systemd
|
|
und nutzbares `sudo` für den normalen SSH-Benutzer.
|
|
- Der Pi muss die Python-Pakete aus `requirements.txt` herunterladen können.
|
|
Pro Version wird eine eigene `.venv` mit Systempaketzugriff angelegt;
|
|
pip verwendet ausschließlich Wheels, keinen impliziten Quellbuild.
|
|
- Genug Speicher für neue Version, Python-Umgebung und vollständige Sicherung
|
|
von `data/`. Alte Versionen und Sicherungen werden nicht automatisch gelöscht.
|
|
- SSH-Hostschlüssel am eigenen Gerät prüfen; die Prüfung bleibt eingeschaltet.
|
|
- Eine mit Uvicorn manuell gestartete WebUI vor dem ersten Update mit `Strg+C`
|
|
beenden. Ein bestehender, vom Projekt verwalteter Dienst wird selbst gestoppt.
|
|
Eine fremde gleichnamige systemd-Unit wird abgelehnt.
|
|
|
|
## Passwortabfragen beim Update
|
|
|
|
Alle Upload-Schritte nutzen nun **eine gemeinsame SSH-Verbindung**. Mit korrekter
|
|
Passwortanmeldung ohne SSH-Schlüssel sind normalerweise insgesamt zwei Abfragen
|
|
nötig: einmal das SSH-Passwort für die Verbindung, einmal das sudo-Passwort für
|
|
den privilegierten Updateaufruf. Bei Schlüssel-/Agent-Anmeldung entfällt die
|
|
SSH-Passwortabfrage; bei gültigem sudo-Zeitstempel kann auch diese entfallen.
|
|
Ein erster Hostschlüssel-Dialog ist keine Passwortabfrage.
|
|
|
|
Der Verbindungssocket liegt in einem privaten temporären Ordner (0700) unter
|
|
`/tmp` auf dem Laptop. Ordneranlage, rsync und Aktivierung verwenden denselben
|
|
Socket. Am Ende oder bei Fehlern wird die Master-Verbindung geschlossen und der
|
|
Socketordner entfernt. Bei Verbindungsverlust fragen spätere Schritte nicht
|
|
erneut nach einem Passwort (`BatchMode=yes`), sondern brechen bei fehlender
|
|
Anmeldemöglichkeit ab. SSH-Konfiguration, Schlüssel und Passwörter werden nicht
|
|
neu gespeichert oder geändert. Die Vorschau öffnet keine Verbindung.
|
|
|
|
Das Uploadskript bereitet die neue Python-Umgebung als normaler Pi-Benutzer vor.
|
|
Danach läuft die Umschaltung mit **einem einzigen sudo-Aufruf**: Unitprüfung,
|
|
Dienststopp, Sicherung, Versionswechsel, Dienstneustart und gegebenenfalls Rückfall.
|
|
Bei gültiger sudo-Anmeldung entfällt die Frage; sonst ist für diesen Aufruf eine
|
|
Anmeldung nötig. Keine weitere Abfrage während Neustart oder Rückfall, auch bei
|
|
kurzem oder deaktiviertem sudo-Zeitstempel. SSH-Anmeldung ist davon getrennt.
|
|
|
|
Passwörter werden vom Skript weder gelesen noch gespeichert. Keine sudoers-
|
|
Ausnahme, kein Passwort per Kommandozeile/Pipe und keine Änderung der sudo-Frist.
|
|
Abhängigkeiten und Python-Prüfungen bleiben unprivilegiert; der privilegierte
|
|
Teil startet Python und den Unit-Renderer mit `runuser` als ursprünglichem
|
|
Pi-Benutzer. Auch der Webdienst behält diesen Benutzer. Die Updatesperre bleibt
|
|
im wartenden unprivilegierten Elternprozess über den ganzen sudo-Aufruf gehalten.
|
|
Eine abgelehnte sudo-Anmeldung lässt den aktiven Dienst und Datenbestand bestehen.
|
|
|
|
## Ablauf und Verzeichnisstruktur
|
|
|
|
1. Neue Dateien unter `releases/ZEITSTEMPEL-ZUFALL/` übertragen.
|
|
2. Mit einer Updatesperre parallele Aktivierung verhindern; neue Python-Umgebung
|
|
vorbereiten und Importe/Syntax prüfen, während die alte Version weiterläuft.
|
|
3. Dienst stoppen; Daten einschließlich SQLite-Dateien und Einstellungen unter
|
|
`backups/VERSION/data/` sichern. Keine laufende Datenbank kopieren.
|
|
4. `current` atomar auf die neue Version umschalten und die Unit aktualisieren.
|
|
`HALLOWEEN_STATE_DIR` verweist immer auf den gemeinsamen Basisordner `data/`.
|
|
5. Autostart aktivieren, Dienst neu starten, `/api/status` bis zu 30 Versuche
|
|
mit je einer Sekunde Pause abfragen und aktiven Dienststatus prüfen.
|
|
6. Bei einem Fehler während der Umschaltung Dienst stoppen, vorherige Version,
|
|
Daten und Unit wiederherstellen und den alten Dienst samt HTTP-Antwort prüfen.
|
|
Änderungen des fehlgeschlagenen Starts bleiben in `backups/VERSION/failed-data/`.
|
|
|
|
Die bisherige flache Installation mit `run.py` und `.venv` im Basisordner
|
|
bleibt beim ersten Update als Rückfallziel bestehen. Ohne vorherige Installation
|
|
kann ein fehlgeschlagener Erststart nur die Daten und den Zustand ohne neuen
|
|
Dienst wiederherstellen. Ein Fehlschlag liefert einen Fehlerstatus, auch wenn
|
|
der Rückfall gelungen ist. Ein unvollständiger Rückfall wird ausdrücklich gemeldet.
|
|
Abrupter Stromverlust/SIGKILL während des Updates ist nicht automatisch abgedeckt.
|
|
|
|
`data/` wird niemals vom Laptop übertragen: Datenbank, Bilder, Modelle,
|
|
Modus und Erkennungseinstellungen bleiben auf dem Pi. `.git`, `.venv`,
|
|
Vorschauen, Referenzen, `.env`, Schlüssel, Versionsordner und Sicherungen werden
|
|
ebenfalls ausgeschlossen. Eigene Dateien außerhalb von `data/` bleiben im
|
|
Basisordner, werden aber nicht automatisch in die neue Version übernommen.
|
|
Das Skript löscht keine alten Pi-Dateien. Systempakete werden nicht geändert.
|
|
Nach Start gelten die bisherigen Freigabe-/Resetbedingungen der Effektsteuerung.
|
|
|
|
## Auf dem Pi prüfen
|
|
|
|
```bash
|
|
systemctl status halloween-grab.service
|
|
systemctl is-enabled halloween-grab.service
|
|
readlink -f ~/halloween/current
|
|
sudo journalctl -u halloween-grab.service -n 80 --no-pager
|
|
```
|
|
|
|
Erkennung nach dem ersten Update bei Bedarf im aktiven Versionsordner einrichten:
|
|
|
|
```bash
|
|
cd ~/halloween/current
|
|
sudo apt update
|
|
sudo apt install python3-opencv python3-numpy
|
|
HALLOWEEN_STATE_DIR=/home/marcinator_2/halloween/data \
|
|
.venv/bin/python tools/install_detection_model.py
|
|
sudo systemctl restart halloween-grab.service
|
|
```
|
|
|
|
OpenCV mindestens 4.10 und das echte Kamera-/Erkennungsverhalten gemäß
|
|
`SOFTWARE.md` prüfen. Nachfolgende Versionsumgebungen nutzen dieselben Pi-Systempakete.
|
|
|
|
## Verifizierter Stand
|
|
|
|
Lokale Tests simulieren Python-Installation, systemd und HTTP-Prüfung und prüfen
|
|
Versionswechsel, Autostart-Unit, Datenbestand, Start-/HTTP-Fehler, Rückfall,
|
|
Erstinstallation, Altinstallation und Ablehnung fremder Units/manueller Server.
|
|
Sie bestätigen keine echte Pi-Installation, Kamera oder Neustartfestigkeit.
|
|
Der Nutzer hat das echte Livebild und anschließend den erfolgreichen
|
|
Updateaufruf bestätigt. Autostart nach einem tatsächlichen Pi-Neustart und
|
|
automatischer Rückfall bei einem Fehler sind noch am Gerät zu prüfen.
|
|
Die HTTP-Prüfung bestätigt die Status-API, nicht Bildqualität oder Aktoren.
|