Befundbericht zum ersten Linux-Lauf
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s

PolyTrader laeuft auf Linux: Build 0 Fehler, 476 Tests gruen, Publish und Start
funktionieren - bei Build und Tests kein einziger Unterschied zu Windows.

Bestaetigt: --headless braucht keine nativen GUI-Bibliotheken (BuildAvaloniaApp
wird nie aufgerufen, Skia nie geladen), master.key bekommt unter Linux korrekt
0600, Zeitzone und Lizenz-Gate verhalten sich wie dokumentiert.

Drei Befunde festgehalten: B-1 (Absturz ohne Datenbank) ist behoben, B-2
(zwei Datumsformate in Logdateinamen) und B-3 (--smoke-ui verlangt jetzt eine
Datenbank; war vorher genauso, nur unsichtbar) sind offen und beschrieben.

Nicht geprueft und warum: systemd, Oberflaeche, SIGTERM und der T2-Nachweis
brauchen eine Testdatenbank und sudo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-26 21:48:59 +02:00
co-authored by Claude Opus 5
parent ad94f8c373
commit 4e9d7259c0
2 changed files with 146 additions and 1 deletions
@@ -0,0 +1,130 @@
# Befundbericht: Erster Linux-Lauf
**Datum: 26.08.2026** · Prüfplan: [PRUEFPLAN-Linux-Betrieb.md](./PRUEFPLAN-Linux-Betrieb.md) ·
Roadmap: [A4a](../ROADMAP.md)
**Testsystem:** Ubuntu 26.04 LTS, Kernel 7.0.0-30, x86_64, 31 GB RAM, 5 CPUs,
Zeitzone `Europe/Berlin`. .NET SDK 10.0.111 mit Runtime 10.0.11 bereits vorhanden.
Zugriff über SSH (WireGuard, Schlüssel-Authentifizierung).
> **Kernaussage: PolyTrader läuft auf Linux.** Build, Tests, Publish und Start funktionieren.
> Ein echter Fehler wurde gefunden und behoben. Der Durchgang ist **nicht vollständig** — für
> systemd-Betrieb, Oberfläche und Zeitzonen-Nachweis fehlen eine Datenbank und `sudo`.
---
## 1. Was funktioniert
| Prüfpunkt | Ergebnis |
|---|---|
| **Build** | `dotnet build -c Release`: **0 Fehler**, 15 Warnungen — exakt dieselben wie unter Windows. Keine plattformbedingte Abweichung |
| **Tests** | **476 von 476 grün**, 3 s Laufzeit — identisch zu Windows |
| **Publish** | `linux-x64`, framework-abhängig: 121 Dateien, 41 MB. Ausführbare Datei trägt bereits das Ausführungsrecht |
| **Start** | Die Anwendung startet mit `--headless` und durchläuft die komplette Startsequenz |
| **Native Abhängigkeiten** | **Keine nötig.** Die Vermutung aus dem Prüfplan ist bestätigt: `--headless` ruft `BuildAvaloniaApp()` nie auf, Skia und HarfBuzz werden nie geladen. `libfontconfig1` & Co. mussten **nicht** installiert werden |
| **Master-Key** | Wird beim ersten Start erzeugt und mit Rechten **`0600`** abgelegt — `FilePermissions` arbeitet unter Linux korrekt. AES-256-GCM meldet sich als aktiv |
| **Zeitzone** | `Europe/Berlin` wird korrekt erkannt und gemeldet |
| **Lizenz-Gate** | Verhält sich exakt wie dokumentiert: Warnung, „eingeschränkter Modus", **kein** Programmabbruch |
| **Logging** | `Logs/` wird angelegt und beschrieben |
**Bemerkenswert:** Zwischen Windows und Linux gibt es bei Build und Tests **keinen einzigen
Unterschied** — weder in der Fehler- noch in der Warnungszahl. Die Portierungsarbeit hat
gehalten.
---
## 2. Befunde
### B-1 · Absturz statt Fehlermeldung ohne Datenbank · **behoben**
**Beobachtet:** Ohne konfigurierten Connection-String lief die Anwendung an und starb tief im
DI-Aufbau:
```
Unhandled exception. System.ArgumentException: The string argument 'connectionString' cannot be empty.
at Microsoft.EntityFrameworkCore.Utilities.Check.NullButNotEmpty(...)
… rund 50 weitere Zeilen …
EXITCODE: 134 (SIGABRT)
```
**Warum das mehr ist als Kosmetik:** Für einen Serverbetrieb ist das doppelt schlecht. Der
Betreiber sieht nicht, *was* fehlt, und systemd startet den Dienst wegen `Restart=on-failure`
alle zehn Sekunden neu — im Journal stehen dann endlose Startversuche statt der Ursache. Und
genau dieser Zustand ist bei einer **Erstinstallation der wahrscheinlichste**: Software liegt da,
Zugangsdaten sind noch nicht gesetzt. Das betrifft direkt Schnitt D-5 (`setup.json`).
**Behoben** (Commit `Verstaendlicher Abbruch statt Absturz…`):
- `Program.Main` prüft die Verbindung, **bevor** der Host gebaut wird, und nennt Schlüssel,
Datei, Pfad und ein Beispiel — dazu den Hinweis, dass das Schema per
`dotnet ef database update` entsteht, weil die Anwendung nicht selbst migriert.
- Rückgabewert **78** (`EX_CONFIG` aus den BSD-sysexits) statt eines Absturzes.
- `deploy/polytrader.service` bekam **`RestartPreventExitStatus=78`** — ein Konfigurationsfehler
repariert sich durch Neustarts nicht, er wird dadurch nur unsichtbar.
- `AddCorePersistence` wirft als zweite Verteidigungslinie eine `InvalidOperationException` mit
derselben Aussage.
**Gegengeprüft auf der VM:** Verständliche Meldung, Exitcode 78, kein Stacktrace.
### B-2 · Zwei verschiedene Datumsformate in Logdateinamen · offen, klein
Im selben Lauf entstanden nebeneinander:
```
2026-08-26.jsonl ← ISO, yyyy-MM-dd
26-08-2026-Info.log ← dd-MM-yyyy
26-08-2026-Warning.log
```
Zwei Logger-Pfade mit unterschiedlicher Namenskonvention. Praktische Folgen: Eine
Logrotate-Regel braucht zwei Muster, und beim Sortieren im Dateimanager landen die `.log`-Dateien
in willkürlicher Reihenfolge, weil der Tag vorn steht. Kein Fehler, aber ein Stolperstein im
Betrieb — sinnvollerweise mit **T2** (TerminalLogger-Umbau) zusammen zu erledigen.
### B-3 · `--smoke-ui` verlangt jetzt eine Datenbank · offen, entscheidungsbedürftig
Die neue Prüfung aus B-1 läuft vor dem Host-Aufbau und trifft damit **auch** die
Konstruktionsprüfung `--smoke-ui`. Die ist als CI-Werkzeug gedacht, und ein Build-Server hat
typischerweise keine Datenbank.
**Wichtig: Das ist keine Verschlechterung.** Vorher scheiterte `--smoke-ui` ohne Datenbank
genauso — nur mit dem Stacktrace aus B-1 statt mit einer Meldung. Der Befund war vorher bloß
unsichtbar.
Sauber lösen ließe sich das, indem `--smoke-ui` die Persistenzschicht überspringt oder gegen
EF-InMemory baut (wie die Tests). Das ist ein eigener Schnitt und hängt daran, ob die CI diesen
Modus überhaupt nutzen soll — deshalb hier nur vermerkt, nicht gebaut.
---
## 3. Nicht geprüft — und warum
| Prüfpunkt | Fehlt |
|---|---|
| Betrieb **mit** Datenbank, Migrationen | Auf der VM läuft **keine** MySQL; der Datenbankhost ist nicht bekannt |
| systemd-Dienst, `WorkingDirectory`-Falle (D-11) | Braucht `sudo`; Passwörter gebe ich nicht ein |
| SIGTERM-Shutdown, `Restart=on-failure` | Setzt den laufenden Dienst voraus |
| **Zeitzonen-Nachweis (T2)** | Die VM steht auf `Europe/Berlin`; der Effekt zeigt sich erst unter **UTC**. Umstellen braucht `sudo` |
| Logrotate | Braucht `sudo` |
| Oberfläche unter Linux | Braucht eine Datenbank (siehe B-3) — die VM hat aber einen Desktop, der Test ist also möglich |
**Zum Weitermachen wird gebraucht:**
1. Eine **Testdatenbank** — entweder Adresse und Zugang zu einer bestehenden MySQL, oder
MariaDB lokal auf der VM installieren (`sudo`). **Nicht die Produktivdatenbank:** Der
`MarketSyncService` schreibt als Hintergrunddienst hinein.
2. Für die `sudo`-Schritte: Entweder Richard führt sie aus, oder er richtet für die Dauer des
Tests passwortloses `sudo` für sein Konto ein.
---
## 4. Nebenbefunde
- **Rider-Konfiguration im Repo:** Mit einem `git add -A` waren vier `.idea/`-Dateien in einen
Commit gerutscht. Sie blockierten den `git pull` auf der VM, wo Rider dieselben Dateien lokal
anlegt. Entfernt, `.idea/` steht jetzt in `.gitignore`.
- **Verbindungs-Multiplexing (`ControlMaster`) funktioniert nicht** — Windows-OpenSSH
unterstützt es nicht. Aus der SSH-Konfiguration entfernt; stattdessen werden mehrere
Prüfschritte pro Aufruf gebündelt.
- **Speicher ist reichlich vorhanden** (31 GB, davon 25 GB frei). Die Vermutung, der
Claude-Desktop-Absturz auf der VM könnte an Speichermangel liegen, ist damit **widerlegt**.