fix: Ghostscript-Angebot log nicht mehr, fehlende Voraussetzungen dokumentiert (v0.7.1)
Befunde aus dem ersten echten Erstinstallations-Test auf frischen Debian-12- und Debian-13-Containern. Der Weg selbst hat getragen (Basis-Install, Instanz-Anlage, zweite Instanz, Update mit Rauchtest, Rollback) — diese Stellen haben gelogen oder gefehlt: - Das Ghostscript-Backports-Angebot auf Debian 12 war ein garantierter Leerlauf, der "aktualisiert ✓" meldete: bookworm-backports enthaelt gar kein ghostscript (am Paketindex verifiziert). Die Routine sucht jetzt den echten Kandidaten, vergleicht vorher/nachher und raeumt eine nur zur Probe angelegte Quelle wieder weg. - Derselbe untaugliche Rat stand in der Preflight-Meldung, der pdfa_level-Warnung, config.example.toml und vier Doku-Dateien — ueberall ersetzt durch die echten Optionen. - Mehrzeilige Log-Hinweise waren durch "echo -e" zerrissen und nicht kopierbar; log_* nutzt jetzt printf mit %s. - pip-freeze.txt landete beim Rollback als /pip-freeze.txt im Wurzelverzeichnis, liegt jetzt unter opt/pdf-ocr-hotfolder/. - git und sudo fehlen auf dem Proxmox-Debian-Template; "sudo ./install.sh" scheitert dort. Beide Wege dokumentiert, git als Voraussetzung ergaenzt, HTTPS-Clone als Normalfall. - Rollback: systemctl start kann kein Glob. journald-Reparatur: Instanzen danach neu starten, sonst bleibt das Journal leer. 254 Tests gruen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+210
-4
@@ -27,10 +27,17 @@ PDF_OCR_COMMON_LOADED=1
|
||||
# ============================================================
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
||||
log_step() { echo -e "\n${BLUE}==>${NC} $*"; }
|
||||
|
||||
# Die Meldung selbst geht als %s durch, NICHT als %b (frueher: echo -e). Sonst
|
||||
# wird ein '\n' im Text — etwa in einem Befehl, den wir zum Kopieren anzeigen —
|
||||
# zu einem echten Zeilenumbruch: die Folgezeilen haetten dann kein [WARN] davor
|
||||
# und wer den Block kopiert, schleppt das Praefix mit. Nur die Farbcodes
|
||||
# brauchen %b. Eine Meldung pro Zeile — mehrzeilige Hinweise bitte als mehrere
|
||||
# Aufrufe schreiben.
|
||||
log_info() { printf '%b[INFO]%b %s\n' "$GREEN" "$NC" "$*"; }
|
||||
log_warn() { printf '%b[WARN]%b %s\n' "$YELLOW" "$NC" "$*"; }
|
||||
log_error() { printf '%b[ERROR]%b %s\n' "$RED" "$NC" "$*"; }
|
||||
log_step() { printf '\n%b==>%b %s\n' "$BLUE" "$NC" "$*"; }
|
||||
|
||||
# Bricht ab, wenn nicht root. $1 = der Aufruf, der gemeint ist.
|
||||
require_root() {
|
||||
@@ -50,6 +57,12 @@ require_root() {
|
||||
: "${SYSTEMD_DIR:=/etc/systemd/system}"
|
||||
: "${DEFAULT_USER:=pdfocr}"
|
||||
|
||||
# Systempfade, die nur die Ghostscript-Pruefung braucht. Ueberschreibbar,
|
||||
# damit sich die Pruefung gegen eine Fake-Umgebung testen laesst.
|
||||
: "${OS_RELEASE_FILE:=/etc/os-release}"
|
||||
: "${APT_SOURCES_LIST:=/etc/apt/sources.list}"
|
||||
: "${APT_SOURCES_DIR:=/etc/apt/sources.list.d}"
|
||||
|
||||
SERVICE_TEMPLATE="pdf-ocr-hotfolder@.service"
|
||||
LXC_DROPIN_DIR="$SYSTEMD_DIR/${SERVICE_TEMPLATE}.d"
|
||||
# shellcheck disable=SC2034 # wird von install.sh und update.sh genutzt
|
||||
@@ -88,6 +101,199 @@ PKGLIST
|
||||
}
|
||||
# --- END apt-packages ---
|
||||
|
||||
# ============================================================
|
||||
# Ghostscript
|
||||
# ============================================================
|
||||
# Ghostscript 10.0.0 bis 10.02.0 erzeugt fehlerhafte PDF/A-Ausgaben: zusammen
|
||||
# mit [ocr].pdfa_level UND skip_text = true scheitert ocrmypdf an jeder Datei.
|
||||
# Mit leerem pdfa_level (der Default) ist so ein Ghostscript voellig
|
||||
# unproblematisch — die Pruefung ist deshalb ein Hinweis, kein Abbruchgrund.
|
||||
|
||||
# Betroffen? $1 = Ausgabe von 'gs --version'.
|
||||
gs_version_affected() {
|
||||
case "$1" in
|
||||
10.0.0|10.00.0|10.01.*|10.02.0) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Version, die gs meldet; leer, wenn gs nicht aufrufbar ist.
|
||||
gs_version() {
|
||||
command -v gs >/dev/null 2>&1 || return 0
|
||||
gs --version 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Codename der Distribution (VERSION_CODENAME aus os-release); leer, wenn
|
||||
# unbekannt.
|
||||
os_codename() {
|
||||
[ -r "$OS_RELEASE_FILE" ] || return 0
|
||||
sed -n 's/^VERSION_CODENAME=//p' "$OS_RELEASE_FILE" | tr -d '"' | head -n1
|
||||
}
|
||||
|
||||
# Ist $1 (z.B. bookworm-backports) schon irgendwo als apt-Quelle eingetragen?
|
||||
apt_release_configured() {
|
||||
grep -RqsF -- "$1" "$APT_SOURCES_LIST" "$APT_SOURCES_DIR" 2>/dev/null
|
||||
}
|
||||
|
||||
# Installierte Paketversion laut dpkg; leer, wenn das Paket nicht da ist.
|
||||
apt_installed_version() {
|
||||
command -v dpkg-query >/dev/null 2>&1 || return 0
|
||||
dpkg-query -W -f '${Version}' "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Hoechste Version von Paket $1, die aus Release $2 (z.B. bookworm-backports)
|
||||
# zu haben ist — gelesen aus der Versionstabelle von 'apt-cache policy'.
|
||||
# Leer, wenn das Release das Paket nicht fuehrt. Bewusst nicht hart verdrahtet:
|
||||
# liefert Debian spaeter doch ein Backports-Ghostscript, greift der Pfad.
|
||||
apt_version_in_release() {
|
||||
local pkg="$1" release="$2"
|
||||
command -v apt-cache >/dev/null 2>&1 || return 0
|
||||
LC_ALL=C apt-cache policy "$pkg" 2>/dev/null | awk -v rel="$release" '
|
||||
$1 == "***" { ver = $2; next }
|
||||
NF == 2 && $1 ~ /^[0-9]/ { ver = $1; next }
|
||||
ver != "" && index($0, rel) { print ver; exit }
|
||||
'
|
||||
}
|
||||
|
||||
# Entfernt eine Quelle, die NUR fuer die Pruefung angelegt wurde ($2 = 1).
|
||||
# War sie vorher schon da, bleibt sie unangetastet — sie kann von etwas
|
||||
# anderem stammen.
|
||||
gs_drop_probe_source() {
|
||||
local list_file="$1" added="$2"
|
||||
[ "$added" = "1" ] || return 0
|
||||
rm -f "$list_file" 2>/dev/null || true
|
||||
log_info "Quelle wieder entfernt: $list_file (sie hat nichts gebracht)"
|
||||
apt-get update -qq || log_warn "'apt-get update' nach dem Aufraeumen schlug fehl."
|
||||
}
|
||||
|
||||
# Versucht, Ghostscript aus Release $1 zu aktualisieren. $2 = bisherige
|
||||
# gs-Version. Rueckgabe 0 NUR, wenn hinterher nachweislich eine andere,
|
||||
# nicht mehr betroffene Version laeuft.
|
||||
gs_try_release_upgrade() {
|
||||
local release="$1" old_ver="$2"
|
||||
local list_file="$APT_SOURCES_DIR/${release}.list"
|
||||
local added=0 cand installed new_ver new_installed
|
||||
|
||||
# Ohne apt-cache/dpkg laesst sich nicht feststellen, was dort ueberhaupt
|
||||
# liegt — dann wird auch nichts eingetragen.
|
||||
if ! command -v apt-cache >/dev/null 2>&1 || ! command -v dpkg >/dev/null 2>&1; then
|
||||
log_warn "apt-cache oder dpkg fehlt — der Paketstand von $release ist nicht pruefbar."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if apt_release_configured "$release"; then
|
||||
log_info "$release ist bereits eingetragen — die Quelle bleibt, wie sie ist."
|
||||
else
|
||||
log_info "Trage $release voruebergehend ein, um den Paketstand zu pruefen..."
|
||||
mkdir -p "$APT_SOURCES_DIR" 2>/dev/null || true
|
||||
if ! printf 'deb http://deb.debian.org/debian %s main\n' "$release" > "$list_file" 2>/dev/null; then
|
||||
log_warn "$list_file liess sich nicht schreiben — Pruefung nicht moeglich."
|
||||
return 1
|
||||
fi
|
||||
added=1
|
||||
if ! apt-get update -qq; then
|
||||
log_warn "'apt-get update' schlug fehl — $release nicht auswertbar."
|
||||
gs_drop_probe_source "$list_file" "$added"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
installed="$(apt_installed_version ghostscript)"
|
||||
cand="$(apt_version_in_release ghostscript "$release")"
|
||||
|
||||
if [ -z "$cand" ]; then
|
||||
log_warn "$release fuehrt gar kein Paket 'ghostscript' — von dort kommt nichts."
|
||||
gs_drop_probe_source "$list_file" "$added"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$installed" ] && ! dpkg --compare-versions "$cand" gt "$installed"; then
|
||||
log_warn "$release hat ghostscript $cand — nicht neuer als das installierte $installed."
|
||||
gs_drop_probe_source "$list_file" "$added"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "$release bietet ghostscript $cand (installiert: ${installed:-unbekannt}) — installiere..."
|
||||
if ! apt-get install -y -t "$release" ghostscript; then
|
||||
log_warn "Installation aus $release schlug fehl — Ghostscript bleibt, wie es war."
|
||||
gs_drop_probe_source "$list_file" "$added"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Erfolg wird NUR gemeldet, wenn sich die Version wirklich geaendert hat.
|
||||
new_ver="$(gs_version)"
|
||||
new_installed="$(apt_installed_version ghostscript)"
|
||||
if [ "$new_ver" = "$old_ver" ] && [ "$new_installed" = "$installed" ]; then
|
||||
log_warn "Ghostscript unveraendert: $old_ver (Paket ${installed:-unbekannt})."
|
||||
log_warn "Das Upgrade aus $release hat nichts bewirkt."
|
||||
gs_drop_probe_source "$list_file" "$added"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "Ghostscript: $old_ver -> $new_ver (Paket ${installed:-unbekannt} -> ${new_installed:-unbekannt})"
|
||||
if gs_version_affected "$new_ver"; then
|
||||
log_warn "Auch $new_ver liegt noch im betroffenen Bereich (10.0.0-10.02.0)."
|
||||
return 1
|
||||
fi
|
||||
log_info "Ghostscript ist jetzt frei vom PDF/A-Fehler ✓"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Sagt dem Admin, was wirklich zur Auswahl steht. Kein Verweis auf Wege, die
|
||||
# es nicht gibt.
|
||||
gs_report_options() {
|
||||
log_warn "Es bleibt bei der betroffenen Ghostscript-Version. Echte Optionen:"
|
||||
log_warn " 1. Nichts tun: [ocr].pdfa_level leer lassen (Default). Dann ist der"
|
||||
log_warn " Fehler folgenlos — die Ausgabe ist nur kein PDF/A."
|
||||
log_warn " 2. PDF/A wirklich noetig? Dann [ocr].skip_text = false setzen."
|
||||
log_warn " 3. Neuere Distribution: Debian 13 (trixie) liefert Ghostscript 10.05.1."
|
||||
log_warn "Die Installation laeuft normal weiter."
|
||||
}
|
||||
|
||||
# Vollstaendige Pruefung fuer den Installer. Gibt immer 0 zurueck: ein
|
||||
# betroffenes Ghostscript ist ein Hinweis, kein Abbruch.
|
||||
check_ghostscript() {
|
||||
local ver codename release answer
|
||||
|
||||
ver="$(gs_version)"
|
||||
if [ -z "$ver" ]; then
|
||||
log_warn "Ghostscript ist nicht aufrufbar — Versionspruefung uebersprungen."
|
||||
return 0
|
||||
fi
|
||||
log_info "Ghostscript: $ver"
|
||||
gs_version_affected "$ver" || return 0
|
||||
|
||||
echo
|
||||
log_warn "═══════════════════════════════════════════════════════════════"
|
||||
log_warn "Ghostscript $ver ist vom PDF/A-Fehler betroffen (10.0.0-10.02.0)."
|
||||
log_warn "Betroffen sind nur Instanzen mit [ocr].pdfa_level UND skip_text = true;"
|
||||
log_warn "mit leerem pdfa_level (Default) ist die Version unauffaellig."
|
||||
log_warn "═══════════════════════════════════════════════════════════════"
|
||||
echo
|
||||
|
||||
codename="$(os_codename)"
|
||||
if [ "$codename" = "bookworm" ]; then
|
||||
release="bookworm-backports"
|
||||
# Bewusst als Frage nach dem PRUEFEN formuliert: ob dort ueberhaupt ein
|
||||
# neueres Ghostscript liegt, steht erst nach 'apt-cache policy' fest.
|
||||
read -r -p "In $release nach einem neueren Ghostscript suchen? [J/n]: " answer || answer=""
|
||||
answer="${answer:-J}"
|
||||
if [[ "$answer" =~ ^[JjYy]$ ]]; then
|
||||
if gs_try_release_upgrade "$release" "$ver"; then
|
||||
echo
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
log_info "Uebersprungen."
|
||||
fi
|
||||
else
|
||||
log_warn "Kein Debian 12 (bookworm) erkannt${codename:+ (Codename: $codename)} — es gibt hier keinen Backports-Weg."
|
||||
fi
|
||||
|
||||
gs_report_options
|
||||
echo
|
||||
return 0
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Python / venv
|
||||
# ============================================================
|
||||
|
||||
Reference in New Issue
Block a user