Files
PolyTraderSharp/docs/pruefplaene/BEFUND-Linux-Betrieb-2026-08-26.md
T
RichardandClaude Opus 5 83d49aa106
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s
A4a vollstaendig: PolyTrader laeuft als Dienst auf Linux; Testumgebung dokumentiert
Der Pruefplan ist abgearbeitet. Die Anwendung laeuft nicht nur, sie arbeitet:
Core-Hydration, MarketSyncService und 100 echte Maerkte von der Polymarket-API
in die Datenbank geschrieben - HTTP, TLS, JSON und DB-Zugriff funktionieren
unter Linux.

Ergebnisse im Einzelnen:
- MariaDB 11.8.6 auf der Test-VM, genau die in DatabaseServerVersion gepinnte
  Version. Alle fuenf DbContexts migriert, 21 Tabellen.
- systemd: active, Shutdown in 0,08 s (Grenze 45 s) ohne SIGKILL,
  Restart=on-failure greift nach kill -9.
- Der neue Exit-78-Schutz wirkt nachweislich: Verbindung entfernt -> Status
  failed, systemd meldet 78/CONFIG, KEINE Neustartschleife, verstaendliche
  Meldung im Journal.
- D-11 (WorkingDirectory-Falle) ist KEIN Problem: server_settings.xml wird aus
  /opt/polytrader gelesen, eine Suche ueber das ganze Dateisystem findet keine
  zweite Datei. Nebenbefund: die Datei wird beim Start gar nicht angelegt,
  erst beim Speichern von Einstellungen.
- Logrotate mit copytruncate rotiert beide Namensmuster, Dienst schreibt weiter.
- Alle neun Views konstruieren fehlerfrei, beide Farbschemata vollstaendig.

T2 ist belegt statt behauptet: Unter UTC meldet die Anwendung "Anzeige-Zeitzone:
Europe/Berlin" und stempelt in derselben Zeile mit 20:04 statt 22:04. Auf einem
UTC-Server zeigen damit alle Logs die falsche Zeit, zwischen Mitternacht und
2 Uhr sogar das falsche Datum.

Neuer Befund B-4: --smoke-ui scheitert ohne X-Server (XOpenDisplay failed),
obwohl es als CI-Werkzeug gedacht ist. "xvfb-run -a" loest es nachweislich -
relevant, sobald A2 wieder aufgenommen wird.

docs/TESTUMGEBUNG-Linux-VM.md neu: Anleitung fuer ALLE Projekte, die auf der VM
testen. Zugang per eigenem SSH-Schluessel je Projekt, eigene Datenbank je
Projekt (<projekt>_test samt eigenem Benutzer, nie eine fremde mitbenutzen),
eigenes Dienstkonto, Verzeichnis- und Portkonventionen, Belegungsliste und
Aufraeumbefehle. Kopie liegt auf der VM unter ~/TESTUMGEBUNG.md, wo jeder Agent
sie beim Verbinden findet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 22:09:09 +02:00

260 lines
13 KiB
Markdown

# 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 — als Dienst, mit Datenbank, mit echten Marktdaten.**
> Der Prüfplan ist **vollständig abgearbeitet** (Nachtrag ab Abschnitt 5). Drei Fehler gefunden,
> einer davon behoben. Offen bleibt nur die Sichtprüfung der Oberfläche, die einen Menschen am
> Bildschirm braucht.
---
## 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
> **Überholt.** Dieser Abschnitt beschreibt den Zwischenstand, bevor MariaDB und `sudo`
> verfügbar waren. Alles hier Aufgeführte wurde im **Nachtrag ab Abschnitt 5** nachgeholt —
> bis auf die Sichtprüfung der Oberfläche. Der Abschnitt bleibt als Verlaufsspur stehen.
| 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**.
---
# Nachtrag: vollständiger Durchgang
Nach Einrichtung von MariaDB und befristetem passwortlosem `sudo` wurde der Rest des Prüfplans
abgearbeitet.
## 5. Betrieb mit Datenbank
| Prüfpunkt | Ergebnis |
|---|---|
| **MariaDB** | 11.8.6 installiert — **genau die Version**, die in `DatabaseServerVersion` gepinnt ist. Datenbank `polytrader_test` mit eigenem Benutzer angelegt |
| **Migrationen** | Alle fünf DbContexts (Core, CopyTrading, ResolutionFarming, Supervisor, Accounting) melden „Done.". **21 Tabellen** mit den Präfixen `core_`, `ct_`/`mod_copytrading_`, `rf_`, `acc_` |
| **Start mit Datenbank** | Läuft vollständig durch: Core-Hydration abgeschlossen, `MarketSyncService` gestartet |
| **Echter Datenverkehr** | **100 Märkte von der Polymarket-API geholt und geschrieben**, beim zweiten Lauf 100 aktualisiert. HTTP, TLS, JSON-Verarbeitung und Datenbankzugriff funktionieren unter Linux |
> Das ist der eigentliche Beweis: Die Anwendung *arbeitet* auf Linux, sie startet nicht nur.
## 6. Dienstbetrieb (systemd)
| Prüfpunkt | Ergebnis |
|---|---|
| **Dienst** | `active (running)`, 71,6 MB Speicher, 20 Tasks. Startet automatisch mit dem System |
| **`WorkingDirectory`-Falle (D-11)** | ✅ **Kein Problem.** Gezielt geprüft: `server_settings.xml` in `/opt/polytrader` mit Testzeitzone `America/New_York` angelegt — die Anwendung meldete genau diese Zone. Eine `find`-Suche über das gesamte Dateisystem fand **keine zweite** Datei. Die Unit setzt `WorkingDirectory` korrekt |
| **Nebenbefund** | `server_settings.xml` wird beim Start **nicht angelegt** — erst beim Speichern von Einstellungen. Ein frisch installierter Dienst läuft also mit Standardwerten und ohne Konfigurationsdatei |
| **Shutdown (SIGTERM)** | ✅ **0,08 Sekunden** — weit unter `TimeoutStopSec=45`. „Deactivated successfully", **kein `SIGKILL`** im gesamten Journal |
| **Neustart nach Absturz** | ✅ `kill -9` auf den Hauptprozess → `Restart=on-failure` greift, neue PID nach ~10 s |
| **Neustartschutz bei Konfigurationsfehler** | ✅ Verbindung entfernt → Status `failed`, **Exit-Code 78**, systemd meldet ihn als `78/CONFIG`. **Keine Neustartschleife.** Die verständliche Meldung steht im Journal. Damit wirkt der Fix aus B-1 im Dienstbetrieb nachweislich |
| **Dateirechte** | `master.key` `0600`, Eigentümer `polytrader` |
## 7. Logrotate
Regel mit **zwei Mustern** (wegen B-2) und `copytruncate` eingerichtet. Erzwungener Lauf: alle drei
Logdateien rotiert und komprimiert, Originale auf 0 Bytes gesetzt, **Dienst schreibt ohne
Unterbrechung weiter**.
`copytruncate` ist hier zwingend: Die Anwendung hält die Logdatei offen und bekommt ein Umbenennen
nicht mit — sie würde sonst in die rotierte Datei weiterschreiben.
## 8. Zeitzonen-Befund T2 — **belegt**
Bisher nur behauptet, jetzt bewiesen. Systemzeitzone auf UTC gestellt, App-Anzeigezone auf
`Europe/Berlin`:
```
System UTC : 2026-08-26 20:04:51
Berlin : 2026-08-26 22:04:51
Logzeile: [20:04:39] [Info] Anzeige-Zeitzone: Europe/Berlin
JSON-Zeile: {"ts":"2026-08-26T20:04:39.398+00:00", …}
```
**Der Widerspruch steht in derselben Zeile:** Die Anwendung meldet Berlin als Anzeigezone und
stempelt gleichzeitig mit UTC.
**Betriebliche Folge:** Auf einem UTC-Server — dem Normalfall — zeigen alle Logs UTC, während die
Oberfläche Berliner Zeit anzeigt. Wer einen Vorfall von „22:30" sucht, findet ihn unter 20:30, und
zwischen Mitternacht und 2 Uhr sogar in der Datei des **Vortags**. Das macht Fehlersuche im
Ernstfall unnötig schwer.
**Nicht behoben** — gehört zu T2 (Umstellung auf `Microsoft.Extensions.Logging`) und ist ein
eigener Schnitt. Die Systemzeitzone wurde nach dem Test auf `Europe/Berlin` zurückgestellt.
## 9. Oberfläche unter Linux
**Alle Fenster konstruieren fehlerfrei** (`--smoke-ui` unter `xvfb-run`):
```
[OK] core.start, core.dashboard, core.settings, core.jobs, core.terminal
[OK] copytrading.main, resolutionfarming.main, supervisor.main, accounting.main
[OK] ShellWindow konstruiert
[OK] ShutdownConfirmWindow konstruiert
[OK] Einstellungs-Editor: 7 Abschnitte, 17 Felder
[OK] Farbschema „Light": alle 27 Farben vorhanden
[OK] Farbschema „Dark": alle 27 Farben vorhanden
```
### B-4 · `--smoke-ui` braucht einen X-Server · offen
Ohne Display scheitert die Konstruktionsprüfung mit `System.Exception: XOpenDisplay failed` aus
`AvaloniaX11Platform.Initialize`. Sie ist aber als **CI-Werkzeug** gedacht, und ein Build-Server
hat typischerweise keinen Bildschirm.
**Zwei Wege:**
1. **`xvfb-run -a` vorschalten** — funktioniert nachweislich (siehe oben), erfordert nur das Paket
`xvfb` im Build-Image. Ein Einzeiler im CI-Workflow.
2. `Avalonia.Headless` verwenden statt des X11-Backends. Sauberer, aber eine Codeänderung.
Empfehlung: Weg 1, wenn A2 (CI-Runner) wieder aufgenommen wird — dann `xvfb` ins Image und
`--smoke-ui` als zusätzlichen Prüfschritt aufnehmen. Der Nutzen wäre erheblich: Die
Konstruktionsprüfung deckt neun Views und beide Farbschemata ab.
### Noch offen: Sichtprüfung
Die Anwendung wurde **nicht mit sichtbarem Fenster** geprüft — das braucht jemanden am Bildschirm
der VM. Schriftrendering, Spaltenbreiten und Dunkelmodus sehen unter GTK erfahrungsgemäß anders
aus als unter Windows. Das ist der verbleibende Rest von A1 auf der Zielplattform.
---
## 10. Zustand der VM nach dem Durchgang
**Bewusst stehen geblieben** (damit weitergetestet werden kann):
- MariaDB 11.8.6 mit Datenbank `polytrader_test`
- Dienst `polytrader.service` unter `/opt/polytrader`, aktiv
- Logrotate-Regel `/etc/logrotate.d/polytrader`
- Xvfb (allgemein nützlich)
- Anleitung `~/TESTUMGEBUNG.md`
**Zurückgestellt:** Systemzeitzone wieder `Europe/Berlin`.
**Noch offen:** Die befristete `sudo`-Freigabe `/etc/sudoers.d/99-testing` ist **aktiv** und sollte
entfernt werden, sobald nicht mehr getestet wird:
```bash
sudo rm /etc/sudoers.d/99-testing
```
Vollständige Aufräumbefehle: [TESTUMGEBUNG-Linux-VM.md](../TESTUMGEBUNG-Linux-VM.md) §7.