diff --git a/scripts/agathe_backup.sh b/scripts/agathe_backup.sh index 070f7d4..f175bfb 100755 --- a/scripts/agathe_backup.sh +++ b/scripts/agathe_backup.sh @@ -1,9 +1,11 @@ #!/usr/bin/env bash +# MAIN-HINWEIS: Diese Version ist nun inkl. Tomedo-Backup. # Robust: WireGuard hoch, CIFS mounten (inkl. Stale-Handle-Fix), rsync, # nur erlaubte Dateitypen zusätzlich nach paperless-consume (flach, OHNE GIF), # Paperless-Backup rsync als echtes Sync (mit --delete), # Anmeldung ebenfalls sync + consume, # zusätzlich: Borg lokal (inkrementell, versioniert) + Mirror per rsync auf CIFS (mit delete), +# zusätzlich: Tomedo-Backup per rsync, # robust gegen CIFS-Aussetzer: ensure_cifs + rsync temp-dir lokal + Mount-Fallback. # Zusätzlich: Pushover-Benachrichtigung bei Erfolg/Fehler. # Fix: Wenn wg0 schon aktiv ist, wird es nicht erneut gestartet und beim Cleanup @@ -18,7 +20,6 @@ set -Eeuo pipefail WG_IF="wg0" VPN_TEST_IP="10.202.101.10" WG_WAS_STARTED_BY_SCRIPT=0 -PUSHOVER_FAILURE_SENT=0 LOCK_FILE="/var/lock/agathe_backup.lock" @@ -80,6 +81,15 @@ DRY_RUN_DELETE="0" # Welche Dateien nach paperless-consume? (OHNE GIF) CONSUME_EXT_REGEX='\.([Pp][Dd][Ff]|[Dd][Oo][Cc][Xx]?|[Xx][Ll][Ss][Xx]?|[Pp][Pp][Tt][Xx]?|[Oo][Dd][Tt]|[Oo][Dd][Ss]|[Oo][Dd][Pp]|[Rr][Tt][Ff]|[Tt][Xx][Tt]|[Cc][Ss][Vv]|[Mm][Dd]|[Hh][Tt][Mm][Ll]?|[Jj][Pp][Ee]?[Gg]|[Pp][Nn][Gg]|[Tt][Ii][Ff][Ff]?|[Ww][Ee][Bb][Pp]|[Hh][Ee][Ii][Cc])$' +# ----------------------------- +# Tomedo Backup +# ----------------------------- +TOMEDO_SRC_ROOT="/mnt/TomedoBackup" +TOMEDO_LAST_FILE="${TOMEDO_SRC_ROOT}/lastFilesBackup" +TOMEDO_DEST_ROOT="${CIFS_MOUNTPOINT}/TomedoBackup" +TOMEDO_MACOS_EXCLUDES="${TOMEDO_DEST_ROOT}/macos.excludes" +TOMEDO_FILES_EXCLUDES="${TOMEDO_DEST_ROOT}/files.excludes" + # ----------------------------- # Hilfsfunktionen # ----------------------------- @@ -91,27 +101,16 @@ send_pushover() { local priority="${2:-0}" if command -v curl >/dev/null 2>&1; then - local rc - set +e - curl -fsS --max-time 20 --retry 2 --retry-delay 2 \ + curl -s \ --form-string "token=${PUSHOVER_API_TOKEN}" \ --form-string "user=${PUSHOVER_USER_TOKEN}" \ --form-string "title=${PUSHOVER_TITLE}" \ --form-string "message=${message}" \ --form-string "priority=${priority}" \ - https://api.pushover.net/1/messages.json >/dev/null - rc=$? - set -e - if [[ "$rc" -ne 0 ]]; then - log "WARNUNG: Pushover konnte nicht gesendet werden (curl Exit-Code: $rc)." - return 1 - fi + https://api.pushover.net/1/messages.json >/dev/null || true else log "WARNUNG: curl fehlt, Pushover konnte nicht gesendet werden." - return 1 fi - - return 0 } need_root() { @@ -161,22 +160,13 @@ on_error() { local exit_code=$? local line_no="${1:-unknown}" log "FEHLER in Zeile ${line_no}, Exit-Code ${exit_code}" - if send_pushover "Backup FEHLER auf $(hostname): Zeile ${line_no}, Exit-Code ${exit_code}" 1; then - PUSHOVER_FAILURE_SENT=1 - fi + send_pushover "Backup FEHLER auf $(hostname): Zeile ${line_no}, Exit-Code ${exit_code}" 1 trap - EXIT cleanup exit "$exit_code" } on_exit() { - local exit_code=$? - if [[ "$exit_code" -ne 0 && "$PUSHOVER_FAILURE_SENT" -eq 0 ]]; then - log "WARNUNG: Abbruch ohne ERR-Notification erkannt (Exit-Code ${exit_code}), sende Fallback-Pushover." - if send_pushover "Backup FEHLER auf $(hostname): Exit-Code ${exit_code} (EXIT trap)." 1; then - PUSHOVER_FAILURE_SENT=1 - fi - fi cleanup } @@ -184,7 +174,7 @@ trap 'on_error $LINENO' ERR trap on_exit EXIT check_deps() { - local deps=(wg-quick wg mount rsync ping mountpoint umount awk cp date basename tee mktemp sleep id mkdir rm dirname borg df curl hostname flock) + local deps=(wg-quick wg mount rsync ping mountpoint umount awk cp date basename tee mktemp sleep id mkdir rm dirname borg df curl hostname flock cat) for d in "${deps[@]}"; do command -v "$d" >/dev/null 2>&1 || { echo "Fehlt: $d"; exit 1; } done @@ -380,6 +370,67 @@ rsync_paperless_backup() { "$SRC_PAPERLESS_BACKUP" "$DEST_PAPERLESS_BACKUP" } +rsync_tomedo_backup() { + ensure_cifs + + log "== Tomedo Backup starten ==" + + if [[ ! -f "$TOMEDO_LAST_FILE" ]]; then + log "FEHLER: Datei fehlt: $TOMEDO_LAST_FILE" + exit 1 + fi + + local last_backup + last_backup="$(cat "$TOMEDO_LAST_FILE")" + + if [[ -z "$last_backup" ]]; then + log "FEHLER: $TOMEDO_LAST_FILE ist leer" + exit 1 + fi + + local src_snapshot="${TOMEDO_SRC_ROOT}/${last_backup}/" + local dst_snapshot="${TOMEDO_DEST_ROOT}/${last_backup}" + local src_files="${TOMEDO_SRC_ROOT}/files/" + local dst_files="${TOMEDO_DEST_ROOT}/files" + + if [[ ! -d "$src_snapshot" ]]; then + log "FEHLER: Tomedo Snapshot-Ordner fehlt: $src_snapshot" + exit 1 + fi + + if [[ ! -d "$src_files" ]]; then + log "FEHLER: Tomedo files-Ordner fehlt: $src_files" + exit 1 + fi + + if [[ ! -f "$TOMEDO_MACOS_EXCLUDES" ]]; then + log "FEHLER: Exclude-Datei fehlt: $TOMEDO_MACOS_EXCLUDES" + exit 1 + fi + + if [[ ! -f "$TOMEDO_FILES_EXCLUDES" ]]; then + log "FEHLER: Exclude-Datei fehlt: $TOMEDO_FILES_EXCLUDES" + exit 1 + fi + + mkdir -p "$dst_snapshot" "$dst_files" + + log "== rsync Tomedo Snapshot: $src_snapshot -> $dst_snapshot ==" + rsync -r -l -t -O --info=progress2 \ + --exclude-from "$TOMEDO_MACOS_EXCLUDES" \ + "$src_snapshot" \ + "$dst_snapshot" + + log "== rsync Tomedo Files: $src_files -> $dst_files ==" + rsync -r -l -t -O --info=progress2 \ + --exclude-from "$TOMEDO_MACOS_EXCLUDES" \ + --exclude-from "$TOMEDO_FILES_EXCLUDES" \ + "$src_files" \ + "$dst_files" + + log "== Tomedo Backup fertig: $last_backup ==" +} + # ----------------------------- # Borg: lokal sichern + Mirror auf CIFS # ----------------------------- @@ -497,6 +548,7 @@ rsync_and_copy_to_consume_flat "$SRC_GROOT" "$DEST_GROOT" "GROOT" rsync_and_copy_to_consume_flat "$SRC_ANMELDUNG" "$DEST_ANMELDUNG" "ANMELDUNG" rsync_paperless_backup +rsync_tomedo_backup borg_local_backup rsync_borg_mirror_to_cifs