docs: Systemanforderungen und journald-Abhaengigkeit dokumentieren (v0.6.3)
Aus den Testlaeufen auf Debian 12 (CT 200) und Debian 13 (CT 201): - Systemanforderungen: mindestens 2 GB RAM. Eine einzelne A4-Seite in 300 dpi mit deskew=true hat auf einem 512-MB-Container den OOM-Killer ausgeloest (anon-rss:489676kB). Dazu der Zusammenhang RAM <-> max_workers x jobs x Aufloesung, wie sich ein OOM-Kill aeussert und wie man ihn nachweist (/sys/fs/cgroup/memory.events, dmesg auf dem Host). - Troubleshooting: kaputtes systemd-journald ist ein blinder Fleck, weil der Dienst seit v0.4.1 nur dorthin loggt. Symptom, erste Pruefung und ein Vordergrund-Notbehelf. Auf einem von zwei Testcontainern aufgetreten — kein generelles LXC-Muster. Nebenbei korrigiert: toter Anker in docs/INSTALLATION.md (#3-ocr-sprachen -> #4-ocr-sprachen) und eine veraltete Stelle im Briefing, die requirements.txt noch als "ocrmypdf 16.x" beschrieb. Reine Doku-Version, 152 Tests unveraendert gruen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+137
-1
@@ -12,6 +12,7 @@ Verwandte Dokumente: [README](../README.md) · [Update](UPDATE.md) · [Debian-Ma
|
||||
|-------|-------------|
|
||||
| Betriebssystem | Debian 12 (bookworm) oder Debian 13 — systemd wird vorausgesetzt |
|
||||
| Python | 3.11+ (wegen `tomllib` aus der stdlib); kommt aus der Distribution |
|
||||
| Arbeitsspeicher | **mindestens 2 GB** für den produktiven Betrieb — siehe [Systemanforderungen](#systemanforderungen) |
|
||||
| Rechte | `root` (`sudo ./install.sh`) |
|
||||
| Netz | apt-Zugriff für die System-Pakete, PyPI-Zugriff für die venv |
|
||||
| Repo | muss dauerhaft liegen bleiben — `update.sh` kopiert daraus (s. [UPDATE.md](UPDATE.md)) |
|
||||
@@ -29,7 +30,7 @@ ca-certificates curl
|
||||
```
|
||||
|
||||
Weitere Tesseract-Sprachpakete installiert der Installer bei Bedarf pro Instanz
|
||||
nach (siehe [OCR-Sprachen](#3-ocr-sprachen)).
|
||||
nach (siehe [OCR-Sprachen](#4-ocr-sprachen)).
|
||||
|
||||
Die Python-Abhängigkeiten stehen **fest gepinnt** in `requirements.txt`
|
||||
(ocrmypdf, watchdog, requests, paramiko). Warum das so ist und wie man die Pins
|
||||
@@ -37,6 +38,92 @@ anhebt: [OS-UPGRADE.md](OS-UPGRADE.md#pins-in-requirementstxt).
|
||||
|
||||
---
|
||||
|
||||
## Systemanforderungen
|
||||
|
||||
CPU und Platte sind unkritisch — **der Arbeitsspeicher ist es nicht.** OCR
|
||||
rastert jede Seite in voller Auflösung ins RAM; der Spitzenbedarf hängt an der
|
||||
Seitengröße, nicht an der Dateigröße der PDF.
|
||||
|
||||
**Empfehlung: mindestens 2 GB RAM.** Für Mehr-Instanz-Betrieb oder
|
||||
`max_workers > 2` entsprechend mehr.
|
||||
|
||||
### Warum 512 MB nachweislich nicht reichen
|
||||
|
||||
Gemessen auf einem LXC-Container mit **512 MB RAM + 512 MB Swap**, Debian 13,
|
||||
Ghostscript 10.05.1:
|
||||
|
||||
| Vorgang | Ergebnis |
|
||||
|---------|----------|
|
||||
| eine einzelne **A4-Seite in 300 dpi**, `deskew = true` | cgroup-Limit gerissen, Dienst vom **OOM-Killer** beendet |
|
||||
| dieselbe Verarbeitung mit einer kleineren Seite (850 × 1100 px) | läuft sauber durch, ca. 19 s |
|
||||
|
||||
Beleg aus dem `dmesg` des LXC-Hosts:
|
||||
|
||||
```
|
||||
oom-kill:constraint=CONSTRAINT_MEMCG, oom_memcg=/lxc/201, task=python
|
||||
total-vm:1168764kB, anon-rss:489676kB
|
||||
```
|
||||
|
||||
Eine Seite, ein Worker — und schon knapp 500 MB anonymer Speicher. 512 MB sind
|
||||
damit für 300-dpi-Scans keine knappe, sondern eine unzureichende Dimensionierung.
|
||||
|
||||
### RAM ↔ `max_workers` × `jobs` × Auflösung
|
||||
|
||||
Der Spitzenbedarf multipliziert sich über drei Config-Werte aus
|
||||
[`[ocr]`](#ocr):
|
||||
|
||||
| Key | Default | Wirkung auf den Speicher |
|
||||
|-----|---------|--------------------------|
|
||||
| `max_workers` | `2` | **so viele PDFs gleichzeitig** — jede mit eigenem Seitenpuffer. Der direkte Multiplikator |
|
||||
| `jobs` | `4` | Threads **innerhalb** einer PDF; mehrere Seiten gleichzeitig im Speicher |
|
||||
| `oversample` | `300` | Auflösung gerasterter Seiten — der Bedarf wächst quadratisch mit der dpi |
|
||||
|
||||
Der Default `max_workers = 2` erlaubt also, dass **zwei** solcher Seiten
|
||||
parallel verarbeitet werden. Wer knapp dimensioniert, zieht zuerst
|
||||
`max_workers` auf `1` herunter, danach `jobs`. `oversample` unter 300 zu
|
||||
drücken, spart zwar Speicher, kostet aber Erkennungsqualität — das ist der
|
||||
letzte Hebel, nicht der erste.
|
||||
|
||||
### Wie sich ein OOM-Kill äußert
|
||||
|
||||
Von außen sieht ein OOM-Kill wie ein Anwendungsfehler aus — er ist keiner:
|
||||
|
||||
- Der Dienst ist **weg** bzw. wurde von systemd neu gestartet
|
||||
(`Restart=on-failure`); `systemctl show -p NRestarts` steigt.
|
||||
- Im journal bricht die Verarbeitung **mitten in der Datei** ab, ohne
|
||||
Python-Traceback und ohne `ERROR`-Zeile aus dem Tool.
|
||||
- Die betroffene PDF bleibt in `working/` liegen.
|
||||
|
||||
### Wie man ihn nachweist
|
||||
|
||||
**Im Container:**
|
||||
|
||||
```bash
|
||||
cat /sys/fs/cgroup/memory.events
|
||||
# oom_kill 1 <- alles über 0 ist ein Treffer
|
||||
```
|
||||
|
||||
**Auf dem LXC-Host** (im Container zeigt `dmesg` diese Zeilen nicht):
|
||||
|
||||
```bash
|
||||
dmesg -T | grep -i oom-kill
|
||||
```
|
||||
|
||||
Diese Prüfung gehört an den **Anfang** der Fehlersuche, wenn Dateien
|
||||
unerklärlich in `working/` liegen bleiben: ohne sie sucht man den Fehler in
|
||||
ocrmypdf, Tesseract oder der Config, wo keiner ist.
|
||||
|
||||
### Datenverlust ist abgefangen, der OOM bleibt
|
||||
|
||||
Seit **v0.6.0** greift der Dienst beim nächsten Start auf, was in `working/`
|
||||
liegen geblieben ist (siehe [UPDATE.md](UPDATE.md#wiederaufnahme-aus-working)).
|
||||
Eine vom OOM-Killer unterbrochene Datei geht also nicht verloren. Behoben ist
|
||||
damit aber nur die Folge: bei unveränderter Dimensionierung läuft dieselbe Datei
|
||||
nach dem Neustart erneut in denselben OOM — bis `max_workers` sinkt oder das
|
||||
System mehr RAM bekommt.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
@@ -480,6 +567,55 @@ cd /opt/pdf-ocr-hotfolder && sudo ./venv/bin/python -m pdf_ocr_hotfolder \
|
||||
Der Interpreter der venv ist weg — fast immer nach einem Distributions-Upgrade.
|
||||
Siehe [OS-UPGRADE.md](OS-UPGRADE.md).
|
||||
|
||||
### Keine Logs: "No journal files were found"
|
||||
|
||||
**Symptom:** `journalctl -u pdf-ocr-hotfolder@<instanz>` bleibt leer oder meldet
|
||||
`No journal files were found.` — auch dann, wenn der Dienst nachweislich läuft
|
||||
und Dateien verarbeitet.
|
||||
|
||||
**Erste Prüfung:**
|
||||
|
||||
```bash
|
||||
systemctl status systemd-journald
|
||||
```
|
||||
|
||||
Ist `systemd-journald.service` selbst `failed` (beobachtet mit
|
||||
`status=243/CREDENTIALS`), gibt es schlicht kein journal, in das geschrieben
|
||||
werden könnte.
|
||||
|
||||
**Einordnung.** Der Dienst loggt seit v0.4.1 **ausschließlich** nach journald —
|
||||
es gibt bewusst kein eigenes Logfile und kein Logverzeichnis. Ein kaputtes
|
||||
journald ist damit ein blinder Fleck: jede Fehlersuche läuft ins Leere, und der
|
||||
Ausfall sieht aus wie ein stummer Dienst. **Deshalb vor jeder Fehlersuche
|
||||
zuerst journald prüfen**, nicht erst, wenn nichts anderes mehr passt.
|
||||
|
||||
Das ist **kein** generelles LXC-Muster. Von zwei Testcontainern war genau einer
|
||||
betroffen; auf dem zweiten lief journald einwandfrei. Es handelt sich um einen
|
||||
Schaden auf dieser einen Maschine, nicht um eine Eigenschaft von Containern.
|
||||
|
||||
**Notbehelf, solange journald nicht zu retten ist:** die Instanz einmal im
|
||||
Vordergrund laufen lassen — dann geht die Ausgabe direkt ins Terminal, am
|
||||
journal vorbei.
|
||||
|
||||
```bash
|
||||
sudo systemctl stop pdf-ocr-hotfolder@<instanz>
|
||||
cd /opt/pdf-ocr-hotfolder && sudo -u pdfocr ./venv/bin/python -m pdf_ocr_hotfolder \
|
||||
--config /etc/pdf-ocr-hotfolder/<instanz>.toml
|
||||
```
|
||||
|
||||
Das `cd` ist zwingend: das Paket wird nicht pip-installiert, sondern nach
|
||||
`/opt/pdf-ocr-hotfolder` kopiert und nur über das Arbeitsverzeichnis gefunden
|
||||
(ohne `cd` gibt es `No module named pdf_ocr_hotfolder`, v0.6.2). Beenden mit
|
||||
`Strg+C`, danach `sudo systemctl start pdf-ocr-hotfolder@<instanz>`. Wer nur den
|
||||
Bestand abarbeiten und dann aussteigen will, hängt `--once` an (siehe
|
||||
[Manueller Lauf](#manueller-lauf-one-shot)).
|
||||
|
||||
### Dienst bricht mitten in der Verarbeitung weg
|
||||
|
||||
Datei bleibt in `working/`, kein Traceback, `NRestarts` steigt: das ist fast
|
||||
immer der OOM-Killer, kein Anwendungsfehler. Nachweis und Dimensionierung unter
|
||||
[Systemanforderungen](#wie-sich-ein-oom-kill-äußert).
|
||||
|
||||
---
|
||||
|
||||
## Manueller Lauf (One-Shot)
|
||||
|
||||
Reference in New Issue
Block a user