# Debian-Major-Upgrade Wie der Hotfolder ein Distributions-Upgrade übersteht (12 → 13, später 13 → 14). Verwandte Dokumente: [README](../README.md) · [Installation](INSTALLATION.md) · [Update](UPDATE.md) --- ## Warum das ein eigener Ablauf ist Die venv unter `/opt/pdf-ocr-hotfolder/venv/` hängt an der **Python-Version der Distribution**. Ein `apt full-upgrade` von Debian 12 auf 13 tauscht Python 3.11 gegen 3.13 aus. Danach zeigt `venv/bin/python` auf einen Interpreter, den es so nicht mehr gibt — systemd quittiert den Start jeder Instanz mit `203/EXEC`, und auch wenn der Interpreter noch existiert, passen die installierten Pakete nicht mehr zum System-Python. **Die venv muss nach dem Sprung neu gebaut werden.** Ein normales `sudo ./update.sh` genügt dafür nicht sicher genug — es gibt den ausdrücklichen Schalter `--rebuild-venv`. --- ## Der Ablauf ### 1. Vorher updaten ```bash cd /pfad/zum/repo git pull sudo ./update.sh ``` Das bringt die Installation auf den aktuellen Stand und erzeugt vor allem ein **frisches Backup** inklusive `pip-freeze.txt` — die Liste der Paketversionen, die auf dem alten System liefen. Inhalt und Ort des Backups: [UPDATE.md](UPDATE.md#backup). ### 2. Instanzen stoppen ```bash sudo systemctl stop 'pdf-ocr-hotfolder@*' ``` Während des Upgrades darf kein OCR laufen: Ghostscript, Tesseract und die Python-Pakete werden mitten im Betrieb ausgetauscht. > **Geduld.** Die Unit hat `TimeoutStopSec=300`, damit ein laufendes OCR sauber > zu Ende kommt. **Ein Stop kann pro Instanz bis zu 5 Minuten dauern** — bei > mehreren Instanzen entsprechend länger. Nicht mit `kill -9` nachhelfen; ein > harter Stopp lässt das Original in `working/` liegen (der Dienst nimmt es beim > nächsten Start zwar wieder auf, aber der Durchlauf ist verloren). Prüfen, dass wirklich alles steht: ```bash systemctl status 'pdf-ocr-hotfolder@*' ``` ### 3. Distribution upgraden Der übliche Debian-Weg — Sources auf das neue Release umstellen, dann: ```bash sudo apt update sudo apt full-upgrade sudo reboot ``` Die Instanzen sind `enabled` und starten nach dem Reboot mit; mit der alten venv scheitern sie (`203/EXEC`). Das ist erwartet und wird im nächsten Schritt behoben. ### 4. venv neu bauen ```bash cd /pfad/zum/repo git pull sudo ./update.sh --rebuild-venv ``` `--rebuild-venv` erzwingt den Neubau. Der Rest des Updates läuft wie gewohnt (siehe [UPDATE.md](UPDATE.md#was-das-skript-tut--in-dieser-reihenfolge)) — die System-Pakete werden dabei ebenfalls abgeglichen, auch `python3-venv` für das neue Python. Der Neubau ist **ganz oder gar nicht**: 1. Die alte venv wird nach `venv.old-` verschoben. 2. `python3 -m venv` baut neu. 3. Die Requirements werden installiert. 4. **Erst bei Erfolg** wird die alte venv gelöscht. ### 5. Wenn ein Pin nicht mehr passt Scheitert `pip install` an einer gepinnten Version, bricht das Skript ab und sagt genau, was los ist: - die letzten 25 Zeilen der pip-Ausgabe, - das **gescheiterte Paket** ("Gescheitertes Paket: …"), - die Diagnose: "eine in requirements.txt fest gepinnte Version gibt es für Python \ nicht (mehr)", - den nächsten Schritt: **requirements.txt anheben** und `update.sh --rebuild-venv` erneut laufen lassen. **Die alte venv ist dann zurückgerollt** — es liegt keine halb gefüllte venv herum. Sie hängt zwar weiterhin am alten Interpreter und die Instanzen laufen damit nicht (das sagt das Skript auch), aber der Zustand ist eindeutig. Also: ```bash # im Repo, auf einer Testmaschine vim requirements.txt # Version des genannten Pakets anheben pytest # Suite muss grün bleiben git commit -am 'requirements: auf anheben' git push # auf dem Zielsystem git pull sudo ./update.sh --rebuild-venv ``` ### 6. `--rebuild-venv` vergessen? Halb so wild: `update.sh` prüft die venv auch ohne den Schalter und baut sie bei Versions-Drift von selbst neu. Geprüft wird - ob das Verzeichnis und `venv/bin/python` überhaupt existieren, - ob der Interpreter der venv noch **läuft** (toter Symlink nach dem Upgrade), - ob seine `major.minor` zum System-`python3` passt, - ob `pyvenv.cfg` dieselbe Version nennt wie der Interpreter. Stimmt eines davon nicht, nennt das Skript den Grund und baut neu. `--rebuild-venv` ist also nicht der einzige, aber der **ausdrückliche** Weg — und der, den man nach einem Distributions-Upgrade nimmt, statt sich auf die Erkennung zu verlassen. --- ## Danach prüfen **Laufen alle Instanzen?** ```bash systemctl status 'pdf-ocr-hotfolder@*' ``` `update.sh` hat das schon verifiziert (Wartezeit, `is-failed`, Crash-Loop) und in der Zusammenfassung Soll gegen Ist gestellt — ein Exit 0 heißt, dass jede Instanz, die vorher lief, auch wieder läuft. **Sind die Configs sauber?** ```bash for f in /etc/pdf-ocr-hotfolder/*.toml; do sudo /opt/pdf-ocr-hotfolder/venv/bin/python -m pdf_ocr_hotfolder \ --check-config --config "$f" done ``` Exit 0/1/2 und was bei Warnungen zu tun ist: [UPDATE.md](UPDATE.md#config-prüfung-per---check-config). **Läuft eine echte PDF durch?** ```bash cp test.pdf /var/lib/pdf-ocr-hotfolder//incoming/ journalctl -u pdf-ocr-hotfolder@ -f ``` Im `outgoing/` muss das OCR-PDF liegen, im Journal steht `OCR done`. Das ist der einzige Test, der die neue venv **und** die neuen System-Binaries (Tesseract, Ghostscript) wirklich anfasst — `systemctl status` sagt darüber nichts. **Ghostscript-Version auf dem neuen Release ansehen:** ```bash gs --version ``` Auf Debian 13 ist der Ghostscript-Bug aus Debian 12 kein Thema mehr; ein bookworm-backports-Eintrag unter `/etc/apt/sources.list.d/` gehört nach dem Upgrade entfernt. Hintergrund: [INSTALLATION.md](INSTALLATION.md#ghostscript-bug-auf-debian-12). --- ## Pins in `requirements.txt` Die Python-Abhängigkeiten sind **bewusst fest gepinnt**: ``` ocrmypdf==16.13.0 watchdog==6.0.0 requests==2.33.1 paramiko==4.0.0 ``` Ohne Pins würde ein `pip install --upgrade` bei jedem Update ungefragt eine neue Major-Version ziehen — ein Sprung von ocrmypdf **16 auf 17** reißt sonst alle Instanzen auf einmal, und zwar im Moment des Updates, nicht zu einem Zeitpunkt, den man sich ausgesucht hat. Die aktuellen Pins sind gegen Python 3.11 (Debian 12) und 3.13 (Debian 13) geprüft; für beide gibt es fertige Wheels, es wird nichts kompiliert. **Beim Anheben:** 1. **Testmaschine benutzen** — nie direkt auf dem produktiven Hotfolder. 2. Dort `update.sh --rebuild-venv` fahren, damit die Pakete wirklich frisch aufgelöst werden. 3. `pytest` muss grün bleiben (135 Tests). 4. Eine echte PDF durchschieben — die Test-Suite mockt ocrmypdf, ein Major-Sprung fällt dort also nicht auf. 5. Erst dann committen und auf die produktiven Systeme geben. Der ocrmypdf-Sprung 16 → 17 ist ein **Major-Sprung** und gehört in einen eigenen Vorgang mit eigenem Test, nicht in ein OS-Upgrade.