feat: Wiederaufnahme aus working/, --check-config, feldtauglicher Updater (v0.6.0)
Datenverlust behoben: - Nach hartem Stopp blieb das Original in working/ liegen und wurde nie wieder angefasst (_scan_existing sah nur incoming/). Es wird jetzt beim Start an Ort und Stelle wieder aufgegriffen, mit Kollisionsschutz gegen gleichnamige neue Scans; angefangene __ocr_-Fragmente werden geloescht. - TimeoutStopSec 30 -> 300, damit laufendes OCR zu Ende laufen darf. Config-Drift sichtbar gemacht: - Neues --check-config (Exit 0 sauber / 1 Warnungen / 2 Fehler), das update.sh vor dem Neustart ueber alle Instanz-Configs laufen laesst. - Warnungen fuer [ocr].timeout >= 900 (seit 0.4.0 pro SEITE) und gesetztes pdfa_level, beim Dienststart wie im Check. - Unbekannte Config-Keys werden nicht mehr still verworfen, sondern genannt. Updater feldtauglich: - venv-Health-Check erkennt toten Symlink UND Versions-Drift gegen das System-Python; --rebuild-venv als ausdruecklicher Weg nach einem Debian- Major-Upgrade. Neubau ist ganz-oder-gar-nicht mit Rollback. - apt-Pakete werden auch beim Update synchronisiert (Quelle: install.sh). - Instanz-Erfassung inkl. activating/failed, Verifikation prueft is-failed und NRestarts statt sleep 1 + is-active. - Backup enthaelt Configs, Unit, Drop-ins und pip-freeze.txt, liegt auf 0600 und rotiert auf 5; schlaegt es fehl, bricht das Update vorher ab. - ERR-Trap faehrt die vorher laufenden Instanzen wieder hoch. - lxc-compat.conf wird beim Update nachgezogen. - requirements.txt gepinnt (ocrmypdf 16.13.0, geprueft fuer Python 3.11+3.13). Doku in Installation / Update / OS-Upgrade aufgeteilt (docs/). 135 Tests gruen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,464 @@
|
||||
# Installation
|
||||
|
||||
Erstinstallation und Anlage von Hotfolder-Instanzen mit `install.sh`.
|
||||
|
||||
Verwandte Dokumente: [README](../README.md) · [Update](UPDATE.md) · [Debian-Major-Upgrade](OS-UPGRADE.md)
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
| Punkt | Anforderung |
|
||||
|-------|-------------|
|
||||
| Betriebssystem | Debian 12 (bookworm) oder Debian 13 — systemd wird vorausgesetzt |
|
||||
| Python | 3.11+ (wegen `tomllib` aus der stdlib); kommt aus der Distribution |
|
||||
| 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)) |
|
||||
|
||||
Die System-Pakete installiert der Installer selbst. Die Liste steht als
|
||||
einzige Quelle in `install.sh` (Funktion `pdf_ocr_apt_packages()`, zwischen den
|
||||
Marken `# --- BEGIN apt-packages` / `# --- END apt-packages`) und wird von
|
||||
`update.sh` von dort ausgelesen:
|
||||
|
||||
```
|
||||
python3 python3-venv python3-pip
|
||||
tesseract-ocr tesseract-ocr-deu tesseract-ocr-eng
|
||||
ghostscript qpdf unpaper pngquant icc-profiles-free
|
||||
ca-certificates curl
|
||||
```
|
||||
|
||||
Weitere Tesseract-Sprachpakete installiert der Installer bei Bedarf pro Instanz
|
||||
nach (siehe [OCR-Sprachen](#3-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
|
||||
anhebt: [OS-UPGRADE.md](OS-UPGRADE.md#pins-in-requirementstxt).
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
git clone gitea@gitea.sonith.de:sonith_ug/pdf-ocr-hotfolder.git
|
||||
cd pdf-ocr-hotfolder
|
||||
sudo ./install.sh
|
||||
```
|
||||
|
||||
`install.sh` ist **Installer und Instanz-Manager in einem** und idempotent —
|
||||
jeder weitere Aufruf überspringt, was schon steht.
|
||||
|
||||
### Basis-Install vs. Instanz-Anlage
|
||||
|
||||
Der Installer unterscheidet zwei Ebenen:
|
||||
|
||||
| Ebene | Wann | Was passiert |
|
||||
|-------|------|--------------|
|
||||
| **Basis-Install** | einmalig; erkannt an `venv` + Template-Unit | System-Pakete, Ghostscript-Check, Container-Erkennung, Default-User `pdfocr`, Code nach `/opt/pdf-ocr-hotfolder/`, venv, systemd-Template-Unit |
|
||||
| **Instanz-Anlage** | bei jedem Lauf, beliebig oft | Abfragen pro Instanz, Datenverzeichnisse, `<instanz>.toml`, optionales User-Drop-in, `enable --now` |
|
||||
|
||||
Ist die Basis-Installation vorhanden, aber die venv passt nicht mehr zum
|
||||
System-Python (typisch nach einem Distributions-Upgrade), läuft der Basis-Install
|
||||
**zur Reparatur erneut**: die alte venv wird nach `venv.old-<timestamp>`
|
||||
weggesichert und neu gebaut. Für den geplanten Weg über ein Debian-Major-Upgrade
|
||||
ist aber `update.sh --rebuild-venv` gedacht, siehe [OS-UPGRADE.md](OS-UPGRADE.md).
|
||||
|
||||
Beim Erstlauf ist mindestens **eine** Instanz Pflicht. Danach fragt der
|
||||
Installer in der Schleife `Weitere Instanz anlegen? [j/N]:`.
|
||||
|
||||
---
|
||||
|
||||
## Die Abfragen pro Instanz
|
||||
|
||||
`create_instance()` stellt fünf Fragen. Alle Antworten gelten **nur für diese
|
||||
Instanz** — nichts davon ist global.
|
||||
|
||||
### 1. Instanz-Name
|
||||
|
||||
```
|
||||
Instanz-Name (nur a-z, 0-9, -):
|
||||
```
|
||||
|
||||
Muster `^[a-z0-9][a-z0-9-]*$`. Der Name wird zum Unit-Suffix
|
||||
(`pdf-ocr-hotfolder@<name>.service`) und zum Config-Dateinamen
|
||||
(`/etc/pdf-ocr-hotfolder/<name>.toml`). Existiert die Config schon, bricht die
|
||||
Anlage ab — ein versehentliches Überschreiben gibt es nicht.
|
||||
|
||||
### 2. Basis-Pfad für die Daten
|
||||
|
||||
```
|
||||
Basis-Pfad für Daten [/var/lib/pdf-ocr-hotfolder/<name>]:
|
||||
```
|
||||
|
||||
Darunter entstehen `incoming/`, `outgoing/`, `working/`, `error/` und werden auf
|
||||
den Service-User gechownt.
|
||||
|
||||
### 3. Service-User
|
||||
|
||||
```
|
||||
Service-User [pdfocr]:
|
||||
```
|
||||
|
||||
- **Existiert der User** (lokal oder als **AD-User via SSSD/Winbind**), wird er
|
||||
übernommen; die primäre Gruppe ermittelt der Installer per `id -gn`.
|
||||
- **Existiert er nicht**, bietet der Installer an, ihn lokal als System-User
|
||||
anzulegen. Wird das abgelehnt, bricht die Instanz-Anlage ab — der User muss
|
||||
dann erst über AD/SSSD bereitstehen.
|
||||
- Ist der gewählte User **nicht** `pdfocr`, legt der Installer das Drop-in
|
||||
`/etc/systemd/system/pdf-ocr-hotfolder@<instanz>.service.d/user.conf` mit
|
||||
`User=`/`Group=` an.
|
||||
|
||||
Bei AD-Usern mit lokaler UID werden die Datei-Berechtigungen über die UID
|
||||
gesetzt — das läuft transparent.
|
||||
|
||||
### 4. OCR-Sprachen
|
||||
|
||||
```
|
||||
Tesseract-Sprachen [deu+eng]:
|
||||
```
|
||||
|
||||
Die Sprachen werden bewusst **je Instanz** abgefragt: ein Hotfolder
|
||||
`buchhaltung` sieht nur deutsche Belege, ein Hotfolder `export`
|
||||
internationale Korrespondenz.
|
||||
|
||||
```toml
|
||||
# /etc/pdf-ocr-hotfolder/buchhaltung.toml
|
||||
languages = "deu"
|
||||
|
||||
# /etc/pdf-ocr-hotfolder/export.toml
|
||||
languages = "deu+eng+fra"
|
||||
```
|
||||
|
||||
**Die Liste so eng wie möglich halten.** Jede zusätzliche Sprache kostet
|
||||
Laufzeit *und* Erkennungsqualität: Tesseract wägt mehr Modelle gegeneinander ab
|
||||
und verwechselt dabei Wörter, die in einer Sprache eindeutig wären.
|
||||
`deu+eng+fra` auf reinen Deutsch-Scans ist kein Sicherheitsnetz, sondern ein
|
||||
Rückschritt.
|
||||
|
||||
Was der Installer damit macht:
|
||||
|
||||
1. **Format prüfen** — Sprachcodes mit `+` verbunden
|
||||
(`^[a-z]{3}(_[A-Za-z]+)?(\+…)*$`), also `deu`, `deu+eng`, `chi_sim+eng`.
|
||||
Bei Unsinn wird erneut gefragt, nicht abgebrochen.
|
||||
2. **Jeden Code gegen `tesseract --list-langs` prüfen.** Fehlt eine
|
||||
Sprachdatei, bietet er das passende apt-Paket an: `tesseract-ocr-<code>`,
|
||||
Unterstrich wird zum Bindestrich (`chi_sim` → `tesseract-ocr-chi-sim`).
|
||||
3. **Lehnt man ab oder scheitert die Installation**, warnt er, dass OCR mit
|
||||
dieser Sprache **bei jeder Datei** scheitern würde, und fragt die Sprachen
|
||||
erneut ab — die fehlende Sprache kann man dann einfach weglassen.
|
||||
4. Ist `tesseract` gar nicht aufrufbar, wird die Prüfung übersprungen und die
|
||||
Eingabe unverändert übernommen.
|
||||
|
||||
### 5. Original archivieren?
|
||||
|
||||
```
|
||||
Original nach erfolgreichem OCR archivieren? [j/N]:
|
||||
```
|
||||
|
||||
- **Nein** (Default) → `original_on_success = "delete"`, das Original wird nach
|
||||
erfolgreichem OCR gelöscht.
|
||||
- **Ja** → `original_on_success = "archive"`, danach:
|
||||
|
||||
```
|
||||
Archiv-Verzeichnis [<basis>/archive]:
|
||||
```
|
||||
|
||||
Der Pfad muss **absolut** sein und darf **nicht** `incoming/`, `outgoing/`,
|
||||
`working/` oder `error/` der Instanz sein — im Eingang würde das Original sonst
|
||||
endlos neu aufgegriffen, in den übrigen kollidiert es mit der Verarbeitung. Das
|
||||
Verzeichnis wird angelegt und auf den Service-User gechownt; innerhalb des
|
||||
Basis-Pfads erledigt das bestehende `chown -R` das mit, ein Archiv **außerhalb**
|
||||
bekommt ein eigenes.
|
||||
|
||||
### Was danach passiert
|
||||
|
||||
Die Instanz-Config entsteht per `sed` aus `config.example.toml`. Substituiert
|
||||
werden die vier `[paths]`-Zeilen sowie `[ocr].languages`,
|
||||
`[output].original_on_success` und `[output].archive_dir`. Anschließend liest
|
||||
der Installer diese drei Keys aus der erzeugten Datei zurück und vergleicht sie
|
||||
mit der Eingabe; erst wenn das passt, nennt die Zusammenfassung Sprachen und
|
||||
Archiv-Verzeichnis. Sonst gibt es eine Warnung mit der Bitte, die Config von
|
||||
Hand nachzuziehen.
|
||||
|
||||
Die Config bekommt `chmod 640` und `chown root:<service-gruppe>`, das
|
||||
Verzeichnis `/etc/pdf-ocr-hotfolder` selbst `750 root:pdfocr` — in den
|
||||
Instanz-Configs stehen **Klartext-Passwörter** für SMTP, Nextcloud und SFTP.
|
||||
|
||||
Zum Schluss: `daemon-reload` und `systemctl enable --now
|
||||
pdf-ocr-hotfolder@<instanz>.service`.
|
||||
|
||||
### Test
|
||||
|
||||
```bash
|
||||
cp irgendein-scan.pdf /var/lib/pdf-ocr-hotfolder/<instanz>/incoming/
|
||||
journalctl -u pdf-ocr-hotfolder@<instanz> -f
|
||||
```
|
||||
|
||||
Nach wenigen Sekunden liegt das OCR-PDF im `outgoing/` der Instanz.
|
||||
|
||||
---
|
||||
|
||||
## Multi-Instanz-Betrieb
|
||||
|
||||
Das Tool arbeitet komplett instanzbasiert über die systemd-Template-Unit
|
||||
`pdf-ocr-hotfolder@<name>.service`. Jede Instanz hat eigene Config, eigene
|
||||
Datenverzeichnisse, eigene Unit, optional eigenen Service-User — und eigene
|
||||
OCR-Sprachen und Original-Behandlung.
|
||||
|
||||
```bash
|
||||
sudo ./install.sh # legt z.B. kunde-a, kunde-b, buchhaltung an
|
||||
|
||||
systemctl status 'pdf-ocr-hotfolder@*'
|
||||
journalctl -u pdf-ocr-hotfolder@kunde-a -f
|
||||
```
|
||||
|
||||
Der Code unter `/opt/pdf-ocr-hotfolder/` (inkl. venv) ist für **alle** Instanzen
|
||||
gemeinsam. Ein Update trifft damit immer alle Instanzen auf einmal — siehe
|
||||
[UPDATE.md](UPDATE.md).
|
||||
|
||||
Das vollständige Verzeichnis-Layout steht im
|
||||
[README](../README.md#verzeichnisse).
|
||||
|
||||
---
|
||||
|
||||
## LXC/Container: Error 226/NAMESPACE
|
||||
|
||||
In LXC-Containern schlagen die systemd-Hardening-Optionen der Unit
|
||||
(`PrivateTmp`, `ProtectSystem`, `ProtectKernelTunables`, …) fehl; systemd
|
||||
quittiert das mit `Error 226/NAMESPACE`.
|
||||
|
||||
Der Installer erkennt Container über `systemd-detect-virt --container` und
|
||||
bietet das Drop-in automatisch an. Manuell:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/systemd/system/pdf-ocr-hotfolder@.service.d/
|
||||
sudo cp /opt/pdf-ocr-hotfolder/systemd/lxc-compat.conf \
|
||||
/etc/systemd/system/pdf-ocr-hotfolder@.service.d/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart 'pdf-ocr-hotfolder@*'
|
||||
```
|
||||
|
||||
Das Drop-in setzt alle betroffenen Hardening-Schalter auf `false`. Es liegt auf
|
||||
Template-Ebene (`pdf-ocr-hotfolder@.service.d/`) und gilt damit für alle
|
||||
Instanzen. Ist es installiert, zieht `update.sh` es bei jedem Update aus dem
|
||||
Repo nach, damit ein neu ergänzter Hardening-Schalter nicht alle
|
||||
Container-Instanzen reißt.
|
||||
|
||||
---
|
||||
|
||||
## Ghostscript-Bug auf Debian 12
|
||||
|
||||
Ghostscript 10.0.0 bis einschließlich 10.02.0 — der **Debian-12-Default** —
|
||||
zerschießt OCR in der Kombination `[ocr].pdfa_level` + `skip_text = true`:
|
||||
ocrmypdf blockiert komplett.
|
||||
|
||||
Deshalb:
|
||||
|
||||
- `pdfa_level = ""` ist der sichere Default (kein PDF/A-Output).
|
||||
- Der Preflight beim Dienststart bricht mit **Exit 2** ab, wenn `pdfa_level`
|
||||
gesetzt **und** die installierte Ghostscript-Version betroffen ist.
|
||||
- `--check-config` meldet ein gesetztes `pdfa_level` als Warnung (siehe
|
||||
[UPDATE.md](UPDATE.md#config-prüfung-per---check-config)).
|
||||
|
||||
Der Installer erkennt betroffene Versionen und bietet auf Debian 12
|
||||
bookworm-backports an. Manuell:
|
||||
|
||||
```bash
|
||||
echo 'deb http://deb.debian.org/debian bookworm-backports main' | \
|
||||
sudo tee /etc/apt/sources.list.d/bookworm-backports.list
|
||||
sudo apt update && sudo apt install -t bookworm-backports ghostscript
|
||||
```
|
||||
|
||||
Ab Ghostscript 10.02.1 ist alles in Ordnung; PDF/A kann dann eingeschaltet
|
||||
werden.
|
||||
|
||||
---
|
||||
|
||||
## Instanz manuell löschen
|
||||
|
||||
Der Installer legt Instanzen an, löscht aber keine. Von Hand:
|
||||
|
||||
```bash
|
||||
sudo systemctl disable --now pdf-ocr-hotfolder@<name>
|
||||
sudo rm /etc/pdf-ocr-hotfolder/<name>.toml
|
||||
sudo rm -rf /etc/systemd/system/pdf-ocr-hotfolder@<name>.service.d
|
||||
sudo systemctl daemon-reload
|
||||
# Datenverzeichnis /var/lib/pdf-ocr-hotfolder/<name> manuell aufräumen
|
||||
```
|
||||
|
||||
Das Datenverzeichnis bleibt **bewusst** liegen: dort können noch unverarbeitete
|
||||
PDFs in `incoming/`, Fehlerfälle in `error/` oder Originale im Archiv liegen.
|
||||
Erst hineinsehen, dann löschen.
|
||||
|
||||
Solange die Config unter `/etc/pdf-ocr-hotfolder/` liegt, zählt `update.sh` die
|
||||
Instanz weiter mit — auch wenn sie gestoppt ist.
|
||||
|
||||
---
|
||||
|
||||
## Konfigurationsreferenz
|
||||
|
||||
Vollständiges, kommentiertes Beispiel: [`config.example.toml`](../config.example.toml).
|
||||
Jede Instanz hat ihre eigene Kopie unter `/etc/pdf-ocr-hotfolder/<instanz>.toml`.
|
||||
|
||||
Unbekannte Keys werden beim Laden ignoriert, aber **gemeldet** — beim
|
||||
Dienststart im Log und von `--check-config`. Ein Tippfehler wie
|
||||
`[ocr].langauges` fällt damit auf.
|
||||
|
||||
### `[paths]` — Pflicht
|
||||
|
||||
| Key | Bedeutung |
|
||||
|-----|-----------|
|
||||
| `incoming` | Eingang, hier schreibt der Scanner hinein |
|
||||
| `outgoing` | Ausgang, fertige OCR-PDFs |
|
||||
| `working` | Arbeitsverzeichnis während der Verarbeitung |
|
||||
| `error` | fehlgeschlagene PDFs |
|
||||
|
||||
Fehlt die Sektion oder einer der vier Einträge, gibt es eine deutsche
|
||||
`ConfigError`-Meldung mit Datei- und Key-Nennung und **Exit 2** — der Dienst
|
||||
startet nicht.
|
||||
|
||||
### `[ocr]`
|
||||
|
||||
| Key | Default | Bedeutung |
|
||||
|-----|---------|-----------|
|
||||
| `languages` | `"deu+eng"` | Tesseract-Sprachen; der Installer fragt sie pro Instanz ab |
|
||||
| `jobs` | `4` | Threads, die ocrmypdf innerhalb **einer** PDF nutzt |
|
||||
| `skip_text` | `true` | Seiten, die schon Text haben, nicht neu OCRen |
|
||||
| `oversample` | `300` | Auflösung für gerasterte Seiten |
|
||||
| `pdfa_level` | `""` | `"1"`, `"2"`, `"3"` oder leer für reines PDF — leer wegen des [Ghostscript-Bugs](#ghostscript-bug-auf-debian-12) |
|
||||
| `deskew` | `true` | schiefe Scans begradigen |
|
||||
| `clean` | `false` | Hintergrund säubern (unpaper) |
|
||||
| `max_workers` | `2` | wie viele PDFs **parallel** verarbeitet werden |
|
||||
| `timeout` | `300` | max. Sekunden, die Tesseract **pro Seite** laufen darf; `0` = kein eigenes Limit |
|
||||
|
||||
**`timeout` ist ein Seiten-Timeout, kein Gesamt-Timeout.** Der Wert geht als
|
||||
`tesseract_timeout` an ocrmypdf; ein Dokument-Timeout kennt ocrmypdf nicht. Wer
|
||||
noch den alten Default `1800` aus einer Config vor 0.4.0 stehen hat, gibt
|
||||
Tesseract 30 Minuten **je Seite** — Richtwert ist 300. Läuft eine Seite in den
|
||||
Timeout, landet sie ohne Textebene im Ergebnis, die übrigen Seiten laufen
|
||||
weiter. Ein durchgereichtes `0` würde ocrmypdf dazu bringen, OCR **still zu
|
||||
überspringen**, deshalb wird `0` (oder negativ) gar nicht erst übergeben und der
|
||||
ocrmypdf-Default greift. Siehe auch
|
||||
[Config-Drift](UPDATE.md#config-drift-nach-einem-update).
|
||||
|
||||
### `[output]`
|
||||
|
||||
| Key | Default | Bedeutung |
|
||||
|-----|---------|-----------|
|
||||
| `name_mode` | `"prefix"` | `prefix` → `OCR_scan.pdf`, `suffix` → `scan_OCR.pdf` (vor der Extension), `none` → unverändert |
|
||||
| `name_tag` | `"OCR_"` | verbatim eingefügter String; leer wirkt wie `none` |
|
||||
| `original_on_success` | `"delete"` | `delete` oder `archive` — Installer fragt das ab |
|
||||
| `archive_dir` | `""` | absoluter Pfad, **Pflicht** bei `archive`; Namenskollision → Zeitstempel-Suffix |
|
||||
|
||||
Ein Tippfehler in `name_mode` oder `original_on_success` führt beim Start zum
|
||||
Abbruch mit **Exit 2**, nicht erst bei der ersten Datei.
|
||||
|
||||
### `[verapdf]`
|
||||
|
||||
| Key | Default | Bedeutung |
|
||||
|-----|---------|-----------|
|
||||
| `enabled` | `false` | PDF/A-Validierung per veraPDF-CLI |
|
||||
| `binary` | `/opt/verapdf/verapdf` | Pfad zum veraPDF-Binary |
|
||||
| `flavour` | `"1b"` | PDF/A-Flavour |
|
||||
|
||||
veraPDF startet eine JVM und ist entsprechend teuer — nur einschalten, wenn die
|
||||
Validierung wirklich gebraucht wird. Bei FAIL wandert das OCR-Ergebnis nach
|
||||
`error/`; das Original folgt `original_on_success` (bei `archive` bleibt es also
|
||||
erhalten).
|
||||
|
||||
### `[upload.folder]` / `[upload.nextcloud]` / `[upload.sftp]`
|
||||
|
||||
Beliebig viele Ziele gleichzeitig aktivierbar. Sind alle aus, bleibt das fertige
|
||||
PDF einfach in `outgoing/` liegen.
|
||||
|
||||
| Sektion | Keys |
|
||||
|---------|------|
|
||||
| `[upload.folder]` | `enabled`, `target` — leer heißt `[paths].outgoing`, dann No-op |
|
||||
| `[upload.nextcloud]` | `enabled`, `url`, `username`, `password`, `remote_path`, `verify_ssl` |
|
||||
| `[upload.sftp]` | `enabled`, `host`, `port`, `username`, `key_file`, `password`, `remote_path` |
|
||||
|
||||
Schlägt mindestens ein Ziel fehl, zählt das als Fehler und die Mail geht als
|
||||
FEHLER raus — das PDF bleibt aber **bewusst in `outgoing/`** liegen, das OCR
|
||||
selbst war ja erfolgreich.
|
||||
|
||||
### `[notify.email]`
|
||||
|
||||
| Key | Default | Bedeutung |
|
||||
|-----|---------|-----------|
|
||||
| `enabled` | `false` | E-Mail-Benachrichtigung an/aus |
|
||||
| `smtp_host`, `smtp_port`, `smtp_user`, `smtp_password`, `use_starttls` | — | SMTP-Zugang |
|
||||
| `from_addr` | — | Absender |
|
||||
| `to_addrs` | `[]` | Empfängerliste |
|
||||
| `on` | `"errors"` | `always` \| `errors` \| `never` |
|
||||
|
||||
### `[logging]`
|
||||
|
||||
| Key | Default | Bedeutung |
|
||||
|-----|---------|-----------|
|
||||
| `level` | `"INFO"` | `DEBUG` \| `INFO` \| `WARNING` \| `ERROR` |
|
||||
|
||||
Der Dienst schreibt **kein eigenes Logfile** — alles geht nach stdout und damit
|
||||
ins journal.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tesseract findet die Sprache nicht
|
||||
|
||||
```bash
|
||||
sudo apt install tesseract-ocr-deu tesseract-ocr-eng
|
||||
```
|
||||
|
||||
Danach `[ocr].languages` prüfen. Der Installer nimmt einem das beim Anlegen
|
||||
einer Instanz ab, ein nachträglich in die Config geschriebener Sprachcode wird
|
||||
aber nicht geprüft — `--check-config` zeigt die eingestellten Sprachen an.
|
||||
|
||||
### "PriorOcrFoundError"
|
||||
|
||||
ocrmypdf erkennt bereits vorhandenen OCR-Text. `skip_text = true` in der Config
|
||||
setzen (Default).
|
||||
|
||||
### Berechtigungsprobleme bei AD-User
|
||||
|
||||
Der Service-User braucht **rw** auf alle vier Verzeichnisse der Instanz (und auf
|
||||
das Archiv, falls konfiguriert):
|
||||
|
||||
```bash
|
||||
sudo chown -R DOMAIN\\scanuser:DOMAIN\\scangroup /var/lib/pdf-ocr-hotfolder/<instanz>
|
||||
```
|
||||
|
||||
### veraPDF-Validierung schlägt immer fehl
|
||||
|
||||
`[verapdf].binary` prüfen. Wenn die Validierung nicht zwingend gebraucht wird:
|
||||
`enabled = false`.
|
||||
|
||||
### Dienst startet nicht (Exit 2)
|
||||
|
||||
Exit 2 heißt immer: Config oder Preflight. Die Ursache steht im journal und
|
||||
ausführlicher in:
|
||||
|
||||
```bash
|
||||
sudo /opt/pdf-ocr-hotfolder/venv/bin/python -m pdf_ocr_hotfolder \
|
||||
--check-config --config /etc/pdf-ocr-hotfolder/<instanz>.toml
|
||||
```
|
||||
|
||||
### Dienst startet nicht (203/EXEC)
|
||||
|
||||
Der Interpreter der venv ist weg — fast immer nach einem Distributions-Upgrade.
|
||||
Siehe [OS-UPGRADE.md](OS-UPGRADE.md).
|
||||
|
||||
---
|
||||
|
||||
## Manueller Lauf (One-Shot)
|
||||
|
||||
Bestehende PDFs einer Instanz einmalig verarbeiten und beenden — greift auch
|
||||
Dateien auf, die in `working/` liegen geblieben sind:
|
||||
|
||||
```bash
|
||||
sudo -u pdfocr /opt/pdf-ocr-hotfolder/venv/bin/python -m pdf_ocr_hotfolder \
|
||||
--config /etc/pdf-ocr-hotfolder/kunde-a.toml --once
|
||||
```
|
||||
|
||||
Exit-Code: `0` = alles verarbeitet (auch "nichts da"), `1` = mindestens eine
|
||||
Datei fehlgeschlagen, `2` = Config- oder Preflight-Fehler.
|
||||
Reference in New Issue
Block a user