#!/usr/bin/env bash # Konsistentes SQLite-Backup über die Python-Backup-API. Sichert NICHT master.key (separat aufbewahren). set -euo pipefail SELF=$(readlink -f "${BASH_SOURCE[0]}") # shellcheck source=lib/common.sh source "$(dirname "$SELF")/lib/common.sh" KEEP=${CHECKBOT_BACKUP_KEEP:-14} [[ $KEEP =~ ^[1-9][0-9]*$ ]] || die "CHECKBOT_BACKUP_KEEP muss eine positive Zahl sein." # Als root würden WAL-Dateien der Datenbank root-gehörig entstehen; daher immer als checkbot arbeiten. if [[ $EUID -eq 0 ]]; then exec runuser -u "$APP_USER" -- "$BASH" "$SELF" "$@" fi BACKUP_PY=' import os, sqlite3, sys src, dst = sys.argv[1:3] source = sqlite3.connect(src) target = sqlite3.connect(dst) try: source.backup(target) if target.execute("PRAGMA integrity_check").fetchone()[0] != "ok": raise SystemExit("Integritätsprüfung der Sicherung fehlgeschlagen") finally: target.close() source.close() ' prune_old() { local file while IFS= read -r file; do rm -f -- "$file" done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'checkbot-*.db' | sort -r | tail -n +$((KEEP + 1))) } main() { local db target partial db=$(db_file) [[ -f $db ]] || die "Datenbank $db nicht gefunden." [[ -d $BACKUP_DIR && -w $BACKUP_DIR ]] || die "Backup-Verzeichnis $BACKUP_DIR fehlt oder ist nicht beschreibbar." umask 077 target=$BACKUP_DIR/checkbot-$(date +%Y%m%d-%H%M%S).db partial=$target.part rm -f -- "$partial" if ! python3 -I -c "$BACKUP_PY" "$db" "$partial"; then rm -f -- "$partial" die "Backup fehlgeschlagen." fi chmod 0600 "$partial" mv -- "$partial" "$target" prune_old log "Backup angelegt: $target (aufbewahrt: bis zu $KEEP)." log "Hinweis: master.key und session.secret sind nicht enthalten und müssen separat gesichert werden." } main "$@"