From ef79e6fdc189039b5239a602dff4611f9fd587e8 Mon Sep 17 00:00:00 2001 From: dschlueter Date: Tue, 8 Sep 2026 16:52:00 +0200 Subject: [PATCH] Website veroeffentlicht und die Diagnose des Skripts geschaerft https://jamulix.de/OR/ steht auf dem Stand des heutigen Baus: 213 Dateien uebertragen, 35 geloescht, alle vierzehn HTTP-Proben richtig - darunter die entscheidende: /OR/anhang-glossar-literatur.html liefert jetzt 404 statt 200. Der zweite Lauf unmittelbar danach uebertrug 0 Dateien und loeschte nichts. Die Abbruchgrenze hat gleich beim ersten Einsatz gegriffen: 35 Loeschungen ueber der Vorgabe von 30. Die Liste war vollstaendig erklaerbar - 33 verwaiste PNGs aus dem Aufraeumschritt, das leere bilder_04/__pycache__/ aus dem spiegle_bilder()-Fehler und die geteilte Anhangseite. Dass ein scp-Upload alle 35 stehen gelassen haette, ist damit belegt statt behauptet. Zwei Huerden auf dem Weg, beide ins Skript uebersetzt: ssh-copy-id braucht ein echtes Terminal. In der Claude-Code-Sitzung gibt es keins, aber DISPLAY ist gesetzt - ssh sucht daraufhin ssh-askpass, das nicht installiert ist. Der Schritt gehoert in ein normales Terminalfenster. Danach sperrte fail2ban den Port: erste Verbindung erfolgreich, die folgenden "Connection refused", waehrend die Website weiter mit 200 antwortete. Nach sieben Minuten war die Sperre weg; weitere Versuche haetten sie verlaengert. pruefe_ziel_erreichbar() unterscheidet jetzt die abgewiesene Verbindung von der abgelehnten Anmeldung. Vorher meldete es in beiden Faellen "Der Schluessel liegt noch nicht auf dem Server" - beim zweiten Mal glatt falsch, denn er lag laengst dort. Co-Authored-By: Claude Opus 5 --- .../veroeffentliche_04.py | 34 +++++++++++---- PROGRESS.md | 41 +++++++++++++++++++ 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/Operations_Research_mit_Python_Version_04/veroeffentliche_04.py b/Operations_Research_mit_Python_Version_04/veroeffentliche_04.py index 2afb419..bd03e92 100755 --- a/Operations_Research_mit_Python_Version_04/veroeffentliche_04.py +++ b/Operations_Research_mit_Python_Version_04/veroeffentliche_04.py @@ -205,23 +205,39 @@ def rsync_befehl(env: dict[str, str], probelauf: bool) -> list[str]: def pruefe_ziel_erreichbar(env: dict[str, str]) -> None: - """Ein Handschlag, bevor 23 MB losgeschickt werden - und er unterscheidet - die beiden Fehlerursachen, die sonst leicht verwechselt werden: Anmeldung - scheitert (ssh liefert 255) gegen rsync fehlt am Ziel.""" + """Ein Handschlag, bevor 23 MB losgeschickt werden. Er unterscheidet die + Ursachen, die sonst leicht verwechselt werden - alle drei sind hier schon + aufgetreten: Verbindung abgewiesen, Anmeldung gescheitert, rsync fehlt.""" kennung = f'{env["OR_BENUTZER"]}@{env["OR_HOST"]}' # BatchMode: keine Passwortabfrage, damit der Aufruf nicht haengt. Der - # ssh-agent funktioniert weiterhin. stderr laeuft absichtlich durch, damit - # ssh seine eigene Diagnose zeigen kann. + # ssh-agent funktioniert weiterhin. stderr wird mitgelesen UND + # weitergereicht: gelesen, um die Ursache zu erkennen, gezeigt, damit ssh + # seine eigene Diagnose loswird. ergebnis = subprocess.run( ssh_optionen(env).split() + ["-o", "BatchMode=yes", kennung, "command -v rsync || echo KEIN_RSYNC"], - stdout=subprocess.PIPE, text=True) + capture_output=True, text=True) + if ergebnis.stderr: + print(ergebnis.stderr.rstrip(), file=sys.stderr) if ergebnis.returncode == 255: + # Abgewiesene Verbindung ist NICHT dasselbe wie eine gescheiterte + # Anmeldung. Beim ersten Einsatz dieses Skripts sperrte fail2ban den + # Port, nachdem ssh-copy-id ein paar Passwortversuche verbraucht hatte - + # die Meldung "Schluessel liegt nicht auf dem Server" fuehrte da in die + # falsche Richtung, denn der Schluessel lag laengst dort. + if "Connection refused" in ergebnis.stderr or "timed out" in ergebnis.stderr: + raise SystemExit( + f"FEHLER: {env['OR_HOST']} weist die Verbindung auf Port 22 ab.\n" + f" Wenn die Website selbst antwortet, ist meist eine\n" + f" Sperre nach fehlgeschlagenen Anmeldeversuchen die\n" + f" Ursache (fail2ban). Sie loest sich nach einigen\n" + f" Minuten von selbst - weitere Versuche verlaengern sie.") raise SystemExit( - f"FEHLER: Keine SSH-Verbindung zu {kennung} (siehe Meldung oben).\n" + f"FEHLER: Anmeldung an {kennung} abgelehnt (siehe Meldung oben).\n" f" Haeufigste Ursache: Der oeffentliche Schluessel liegt noch\n" - f" nicht auf dem Server. Einmalig:\n" - f" ssh-copy-id {kennung}\n" + f" nicht auf dem Server. Einmalig, in einem ECHTEN Terminal\n" + f" (ssh braucht dafuer ein tty):\n" + f" ssh-copy-id -i ~/.ssh/id_ed25519.pub {kennung}\n" f" Bei passwortgeschuetztem Schluessel: ssh-add einmal " f"ausfuehren.") if ergebnis.returncode != 0: diff --git a/PROGRESS.md b/PROGRESS.md index a63c0a8..debaa1d 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -2117,6 +2117,47 @@ rsync installiert" — tatsächlich schlug schon die Anmeldung fehl, weil der ö Schlüssel noch nicht auf `jamulix.de` liegt. Die Prüfung unterscheidet die Fälle jetzt am ssh-Rückgabewert 255 und nennt `ssh-copy-id`. +### ✅ Erstmals per Skript veröffentlicht — 08.09.2026 + +`https://jamulix.de/OR/` steht auf dem Stand des heutigen Baus. **213 Dateien übertragen, 35 +gelöscht**, alle vierzehn HTTP-Proben richtig — darunter die entscheidende: +`/OR/anhang-glossar-literatur.html` liefert jetzt **404** statt 200. Der zweite Lauf +unmittelbar danach übertrug **0 Dateien** und löschte nichts. + +**Die Abbruchgrenze hat gleich beim ersten Einsatz gegriffen** und sich damit bewährt: 35 +Löschungen über der Vorgabe von 30. Die Liste war anzusehen, bevor sie angehoben wurde — und +sie war vollständig erklärbar: + +| Anzahl | Was | Warum | +| --- | --- | --- | +| 33 | `bilder_04/*.png` | die verwaisten PNGs, die im Aufräumschritt lokal gelöscht wurden | +| 1 | `bilder_04/__pycache__/` | das leere Verzeichnis aus dem `spiegle_bilder()`-Fehler | +| 1 | `anhang-glossar-literatur.html` | die geteilte Anhangseite | + +Dass ein `scp`-Upload alle 35 stehen gelassen hätte, ist damit belegt statt behauptet. + +**Zwei Hürden auf dem Weg, beide in Konsequenzen übersetzt:** + +*`ssh-copy-id` braucht ein echtes Terminal.* In der Claude-Code-Sitzung gibt es keins +(`tty` → „kein Terminal"), aber `DISPLAY=:1` ist gesetzt. `ssh` schließt daraus auf einen +grafischen Passwortdialog und sucht `/usr/bin/ssh-askpass`, das nicht installiert ist. Ein +Passwort über die normale Eingabe nimmt `ssh` grundsätzlich nicht entgegen. Der Schritt +gehört in ein normales Terminalfenster. + +*Danach sperrte der Server den Port.* Die fehlgeschlagenen Passwortversuche plus die +Verbindungen des Skripts lösten eine Sperre aus (fail2ban): erste Verbindung erfolgreich, +die folgenden `Connection refused` — während die Website selbst weiter mit 200 antwortete. +Nach sieben Minuten Warten war sie weg. **Weitere Versuche hätten sie verlängert.** + +Beides steckt jetzt im Skript: `pruefe_ziel_erreichbar()` unterscheidet die abgewiesene +Verbindung von der abgelehnten Anmeldung — vorher meldete es in beiden Fällen „Der +Schlüssel liegt noch nicht auf dem Server", was beim zweiten Mal glatt falsch war, denn er +lag längst dort. + +Damit ist der seit dem Colab-Umbau offene Punkt erledigt: Online steht kein toter +Colab-Link mehr, `Notebooks_04/` liefert statt 403 eine Übersichtsseite, und das PDF +entspricht byte-genau dem gebauten. + --- ## 8. Commit-Historie des V04-Strangs