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 <noreply@anthropic.com>
This commit is contained in:
parent
d566cf8dac
commit
ef79e6fdc1
2 changed files with 66 additions and 9 deletions
|
|
@ -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:
|
||||
|
|
|
|||
41
PROGRESS.md
41
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue