feat: stille Datenverlust-Pfade geschlossen, gemeinsame Shell-Lib (v0.7.0)
Vor dem Rollout durchgesehen und die verbliebenen Stellen geschlossen, an denen etwas schiefgehen konnte, ohne dass es irgendwo sichtbar wurde. Datenverlust: - veraPDF: das in [verapdf].binary konfigurierte Programm wird im Preflight geprueft. Bisher galt bei falschem Pfad JEDE Datei als "nicht konform" — Ergebnis nach error/, Original geloescht (Default delete). run_verapdf() trennt jetzt ausserdem ein echtes FAIL-Urteil von einer Stoerung (VeraPdfUnavailable: nicht startbar, abgestuerzt, kein PASS/FAIL in der Ausgabe). Bei Stoerung wandern Original UND Ergebnis nach error/, das Original wird nicht entsorgt. - Gleichnamige Dateien wurden in outgoing/, error/ und beim Ordner-Upload mit abweichendem target kommentarlos ueberschrieben. Jetzt Zeitstempel daneben, mit Warnung; ProcessResult.output traegt den echten Pfad. Robustheit: - Kaputtes oder nicht lesbares TOML beim Start: Exit 2 statt Traceback. - RestartPreventExitStatus=2 in der Unit — Exit 2 (Config/Preflight) laeuft nicht mehr endlos neu, die Instanz bleibt sichtbar failed stehen. - Toter watchdog-Observer wird erkannt: Exit 3, systemd setzt den Watch neu auf. Vorher blieb die Unit "active" und verarbeitete nichts mehr. - Relative Pfade in [paths]/archive_dir/target sind ein Config-Fehler statt still unter /opt zu landen. - Fehler beim Archivieren entwertet den Durchlauf nicht mehr: Upload und Mail laufen, Sichtbarkeit ueber log.error + "OK mit Warnung"-Mail. - Nicht-PDFs in incoming/ werden beim Start-Scan gesammelt gemeldet. - Logging explizit nach stdout (die Doku versprach das schon). Struktur: - Neue lib/common.sh, von install.sh und update.sh gesourct. Die doppelte venv_is_healthy() gibt es nur noch einmal, in der gruendlichen Fassung — die schlanke in install.sh haette eine nach einem Distro-Sprung kaputte venv als gesund durchgewunken (nachgewiesen). - install.sh warnt in Containern, wenn systemd-journald nicht laeuft. Doku: Dateisystem-Festlegung (ext4/xfs/zfs, kein CIFS/NFS wegen inotify), Debian 13 in LXC auf Proxmox scheitert an journald (243/CREDENTIALS, AppArmor blockiert sd-mkdcreds) inkl. Abhilfe, echte Speicher-Messwerte, Exit-Code-Tabelle. 254 Tests gruen (vorher 152). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+53
-64
@@ -12,73 +12,32 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
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} $*"; }
|
||||
|
||||
if [ "${EUID}" -ne 0 ]; then
|
||||
log_error "Bitte als root ausführen: sudo ./install.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTALL_DIR="/opt/pdf-ocr-hotfolder"
|
||||
CONFIG_DIR="/etc/pdf-ocr-hotfolder"
|
||||
DATA_ROOT="/var/lib/pdf-ocr-hotfolder"
|
||||
SERVICE_TEMPLATE="pdf-ocr-hotfolder@.service"
|
||||
DEFAULT_USER="pdfocr"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$SCRIPT_DIR"
|
||||
|
||||
# ============================================================
|
||||
# Gemeinsame Funktionen (Logging, Pfade, venv-Pruefung, Paketliste)
|
||||
# ============================================================
|
||||
# Relativ zum Skript aufgeloest, nicht zum Arbeitsverzeichnis — install.sh
|
||||
# wird auch mit absolutem Pfad aufgerufen. Fehlt die Datei, ist hier Schluss;
|
||||
# ein "command not found" mitten im Lauf waere die schlechtere Nachricht.
|
||||
COMMON_LIB="$SCRIPT_DIR/lib/common.sh"
|
||||
if [ ! -r "$COMMON_LIB" ]; then
|
||||
echo "[ERROR] Gemeinsame Funktionsbibliothek nicht gefunden: $COMMON_LIB" >&2
|
||||
echo " install.sh braucht lib/common.sh aus demselben Repo." >&2
|
||||
echo " Repo vollstaendig auschecken und erneut ausfuehren." >&2
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck source=lib/common.sh
|
||||
. "$COMMON_LIB"
|
||||
|
||||
require_root "sudo ./install.sh"
|
||||
|
||||
if [ ! -f "$REPO_DIR/pdf_ocr_hotfolder/__init__.py" ]; then
|
||||
log_error "Repo-Layout nicht erkannt. install.sh aus dem Repo ausführen."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# System-Pakete — einzige Quelle der Wahrheit
|
||||
# ============================================================
|
||||
# Der folgende Block wird von update.sh aus dieser Datei herausgeschnitten
|
||||
# (sed auf die BEGIN/END-Marken) und dort ausgewertet, damit ein Update
|
||||
# neue Pakete nachzieht. Die Marken und der Funktionsname duerfen sich
|
||||
# deshalb nicht aendern, ohne update.sh anzupassen.
|
||||
# --- BEGIN apt-packages (wird von update.sh extrahiert) ---
|
||||
pdf_ocr_apt_packages() {
|
||||
cat <<'PKGLIST'
|
||||
python3
|
||||
python3-venv
|
||||
python3-pip
|
||||
tesseract-ocr
|
||||
tesseract-ocr-deu
|
||||
tesseract-ocr-eng
|
||||
ghostscript
|
||||
qpdf
|
||||
unpaper
|
||||
pngquant
|
||||
icc-profiles-free
|
||||
ca-certificates
|
||||
curl
|
||||
PKGLIST
|
||||
}
|
||||
# --- END apt-packages ---
|
||||
|
||||
# Prueft, ob die venv noch zum aktuellen System-Python passt.
|
||||
# Zwei Faelle: (1) der Interpreter der venv laeuft gar nicht mehr (toter
|
||||
# Symlink nach einem Distributions-Upgrade, systemd: 203/EXEC), (2) er laeuft
|
||||
# noch, ist aber eine andere Version als das System-Python (Debian 12 -> 13).
|
||||
# Beides heisst: neu bauen. Keine Versionsnummer ist hier hartcodiert.
|
||||
venv_is_healthy() {
|
||||
local venv="$1" venv_mm sys_mm
|
||||
[ -x "$venv/bin/python" ] || return 1
|
||||
venv_mm="$("$venv/bin/python" -c 'import sys; print("%d.%d" % sys.version_info[:2])' 2>/dev/null || true)"
|
||||
[ -n "$venv_mm" ] || return 1
|
||||
sys_mm="$(python3 -c 'import sys; print("%d.%d" % sys.version_info[:2])' 2>/dev/null || true)"
|
||||
[ -n "$sys_mm" ] || return 1
|
||||
[ "$venv_mm" = "$sys_mm" ]
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Basis-Installation (idempotent)
|
||||
# ============================================================
|
||||
@@ -137,12 +96,36 @@ install_base() {
|
||||
read -r -p "LXC-Kompatibilitäts-Drop-in installieren? [J/n]: " LXC_FIX
|
||||
LXC_FIX="${LXC_FIX:-J}"
|
||||
if [[ "$LXC_FIX" =~ ^[JjYy]$ ]]; then
|
||||
local LXC_DROPIN_DIR="/etc/systemd/system/pdf-ocr-hotfolder@.service.d"
|
||||
mkdir -p "$LXC_DROPIN_DIR"
|
||||
cp "$REPO_DIR/systemd/lxc-compat.conf" "$LXC_DROPIN_DIR/lxc-compat.conf"
|
||||
cp "$REPO_DIR/systemd/lxc-compat.conf" "$LXC_DROPIN"
|
||||
systemctl daemon-reload
|
||||
log_info "LXC-Kompatibilitäts-Drop-in installiert ✓"
|
||||
fi
|
||||
|
||||
# Der Dienst loggt ausschliesslich nach journald. Ist journald kaputt,
|
||||
# gibt es gar keine Logs — das faellt sonst erst bei der ersten
|
||||
# Fehlersuche auf. Bekannter Fall: Debian 13 (systemd >= 255) in einer
|
||||
# LXC auf Proxmox 8.4 — das AppArmor-Profil des Hosts blockiert den
|
||||
# Credential-Mount von (sd-mkdcreds), journald scheitert mit
|
||||
# 243/CREDENTIALS. Debian 12 (systemd 252) ist nicht betroffen.
|
||||
if ! systemctl is-active --quiet systemd-journald 2>/dev/null; then
|
||||
log_warn "ACHTUNG: systemd-journald laeuft nicht."
|
||||
log_warn "Der Dienst loggt NUR nach journald — es gaebe hier keine Logs."
|
||||
log_warn "Pruefen: systemctl status systemd-journald"
|
||||
log_warn "Scheitert es mit 243/CREDENTIALS (Debian 13 in LXC auf"
|
||||
log_warn "Proxmox), hilft ein Drop-in im Container:"
|
||||
log_warn " mkdir -p /etc/systemd/system/systemd-journald.service.d"
|
||||
log_warn " printf '[Service]\\nImportCredential=\\n' > \\"
|
||||
log_warn " /etc/systemd/system/systemd-journald.service.d/no-credentials.conf"
|
||||
log_warn " systemctl daemon-reload && systemctl restart systemd-journald"
|
||||
log_warn "Details: docs/INSTALLATION.md, Abschnitt Troubleshooting."
|
||||
read -r -p "Trotzdem fortfahren? [J/n]: " JOURNAL_GO
|
||||
JOURNAL_GO="${JOURNAL_GO:-J}"
|
||||
if [[ ! "$JOURNAL_GO" =~ ^[JjYy]$ ]]; then
|
||||
log_error "Abbruch. Erst journald reparieren, dann erneut starten."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
log_step "Default-User '$DEFAULT_USER' prüfen"
|
||||
@@ -161,6 +144,10 @@ install_base() {
|
||||
log_step "Code kopieren"
|
||||
rm -rf "$INSTALL_DIR/pdf_ocr_hotfolder"
|
||||
cp -r "$REPO_DIR/pdf_ocr_hotfolder" "$INSTALL_DIR/"
|
||||
# lib/ muss mit: update.sh sucht die gemeinsamen Funktionen zuerst neben
|
||||
# sich und danach in der Installation.
|
||||
rm -rf "${INSTALL_DIR:?}/lib"
|
||||
cp -r "$REPO_DIR/lib" "$INSTALL_DIR/"
|
||||
cp "$REPO_DIR/requirements.txt" "$INSTALL_DIR/"
|
||||
cp "$REPO_DIR/VERSION" "$INSTALL_DIR/"
|
||||
cp "$REPO_DIR/config.example.toml" "$INSTALL_DIR/"
|
||||
@@ -173,6 +160,7 @@ install_base() {
|
||||
local VENV_SAVED
|
||||
VENV_SAVED="$INSTALL_DIR/venv.old-$(date +%Y%m%d-%H%M%S)"
|
||||
log_warn "Vorhandene venv passt nicht mehr zum System-Python (Distributions-Upgrade?)."
|
||||
report_venv_issues
|
||||
log_warn "Sie wird gesichert nach: $VENV_SAVED"
|
||||
mv "$INSTALL_DIR/venv" "$VENV_SAVED"
|
||||
fi
|
||||
@@ -189,7 +177,7 @@ install_base() {
|
||||
log_info "venv ok ✓"
|
||||
|
||||
log_step "systemd Template-Unit installieren"
|
||||
cp "$REPO_DIR/systemd/$SERVICE_TEMPLATE" "/etc/systemd/system/$SERVICE_TEMPLATE"
|
||||
cp "$REPO_DIR/systemd/$SERVICE_TEMPLATE" "$SYSTEMD_DIR/$SERVICE_TEMPLATE"
|
||||
systemctl daemon-reload
|
||||
log_info "Template-Unit installiert ✓"
|
||||
|
||||
@@ -427,7 +415,7 @@ create_instance() {
|
||||
|
||||
# Drop-in für abweichenden Service-User
|
||||
if [ "$SVC_USER" != "$DEFAULT_USER" ]; then
|
||||
local DROPIN_DIR="/etc/systemd/system/pdf-ocr-hotfolder@${INST}.service.d"
|
||||
local DROPIN_DIR="$SYSTEMD_DIR/pdf-ocr-hotfolder@${INST}.service.d"
|
||||
mkdir -p "$DROPIN_DIR"
|
||||
cat > "$DROPIN_DIR/user.conf" <<EOF
|
||||
[Service]
|
||||
@@ -471,11 +459,12 @@ echo "=========================================="
|
||||
|
||||
# Auch eine vorhandene, aber kaputte venv loest die Basis-Installation aus
|
||||
# (sonst wuerde install.sh nach einem Distributions-Upgrade nichts reparieren).
|
||||
if [ ! -d "$INSTALL_DIR/venv" ] || [ ! -f "/etc/systemd/system/$SERVICE_TEMPLATE" ]; then
|
||||
if [ ! -d "$INSTALL_DIR/venv" ] || [ ! -f "$SYSTEMD_DIR/$SERVICE_TEMPLATE" ]; then
|
||||
log_step "Basis-Installation"
|
||||
install_base
|
||||
elif ! venv_is_healthy "$INSTALL_DIR/venv"; then
|
||||
log_warn "Basis-Installation vorhanden, aber die venv passt nicht mehr zum System-Python."
|
||||
report_venv_issues
|
||||
log_step "Basis-Installation wird zur Reparatur erneut ausgefuehrt"
|
||||
install_base
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user