Compare commits
4 Commits
codex/tome
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a4d84e5dd | ||
|
|
e939ceec7a | ||
|
|
841eedfe2f | ||
|
|
4c7efb05c8 |
@@ -1,11 +1,16 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Tomedo-only Backup:
|
# MAIN-HINWEIS: Diese Version ist nun inkl. Tomedo-Backup.
|
||||||
# WireGuard hoch, CIFS mounten (inkl. Stale-Handle-Fix),
|
# Robust: WireGuard hoch, CIFS mounten (inkl. Stale-Handle-Fix), rsync,
|
||||||
# danach nur Tomedo Snapshot + Tomedo Files per 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.
|
# Zusätzlich: Pushover-Benachrichtigung bei Erfolg/Fehler.
|
||||||
# Wenn wg0 schon aktiv ist, wird es nicht erneut gestartet und beim Cleanup
|
# Fix: Wenn wg0 schon aktiv ist, wird es nicht erneut gestartet und beim Cleanup
|
||||||
# nur dann beendet, wenn dieses Skript es selbst hochgebracht hat.
|
# nur dann beendet, wenn dieses Skript es selbst hochgebracht hat.
|
||||||
# Schutz gegen parallele Ausführung per flock.
|
# Zusätzlich: Schutz gegen parallele Ausführung per flock.
|
||||||
|
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
@@ -21,6 +26,16 @@ LOCK_FILE="/var/lock/agathe_backup.lock"
|
|||||||
CIFS_SHARE="//10.202.101.10/nchsdhg"
|
CIFS_SHARE="//10.202.101.10/nchsdhg"
|
||||||
CIFS_MOUNTPOINT="/mnt/nchsdhg_agathe"
|
CIFS_MOUNTPOINT="/mnt/nchsdhg_agathe"
|
||||||
|
|
||||||
|
DEST_GROOT="${CIFS_MOUNTPOINT}/groot_mobile/"
|
||||||
|
DEST_ANMELDUNG="${CIFS_MOUNTPOINT}/Anmeldung/"
|
||||||
|
DEST_PAPERLESS_BACKUP="${CIFS_MOUNTPOINT}/paperless-backup/"
|
||||||
|
|
||||||
|
SRC_GROOT="/mnt/groot/"
|
||||||
|
SRC_ANMELDUNG="/mnt/Anmeldung/"
|
||||||
|
SRC_PAPERLESS_BACKUP="/mnt/paperless-backup/daily/"
|
||||||
|
|
||||||
|
PAPERLESS_CONSUME="/mnt/paperless-consume"
|
||||||
|
|
||||||
CIFS_USER="nchsdhg"
|
CIFS_USER="nchsdhg"
|
||||||
CIFS_PASS="mugkeN-zexdab-9gyfky"
|
CIFS_PASS="mugkeN-zexdab-9gyfky"
|
||||||
CIFS_CRED_FILE="" # z.B. "/etc/samba/cred_nchsdhg"
|
CIFS_CRED_FILE="" # z.B. "/etc/samba/cred_nchsdhg"
|
||||||
@@ -32,6 +47,40 @@ PUSHOVER_USER_TOKEN="uFBKJ1LmL3eMUbHZs2ktLjSH8RyJ2Z"
|
|||||||
PUSHOVER_API_TOKEN="a3xzevfk8vwpbj6wp6duzbwy43pcmx"
|
PUSHOVER_API_TOKEN="a3xzevfk8vwpbj6wp6duzbwy43pcmx"
|
||||||
PUSHOVER_TITLE="nchsdhg"
|
PUSHOVER_TITLE="nchsdhg"
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Borg (lokal + Mirror auf CIFS)
|
||||||
|
# -----------------------------
|
||||||
|
LOCAL_BORG_REPO="/var/backups/borg/agathe"
|
||||||
|
LOCAL_BORG_BASE="/var/backups/borg"
|
||||||
|
REMOTE_BORG_MIRROR="${CIFS_MOUNTPOINT}/borg-mirror/agathe"
|
||||||
|
|
||||||
|
BORG_PASSPHRASE_FILE="/root/.config/borg/passphrase"
|
||||||
|
BORG_LOCK_WAIT="120"
|
||||||
|
|
||||||
|
KEEP_DAILY=7
|
||||||
|
KEEP_WEEKLY=4
|
||||||
|
KEEP_MONTHLY=6
|
||||||
|
|
||||||
|
# Mirror: Ziel exakt wie Quelle (löscht auf Ziel, was lokal nicht mehr existiert)
|
||||||
|
MIRROR_DELETE="1"
|
||||||
|
|
||||||
|
# Optional: nach jedem Lauf borg check machen (kostet Zeit)
|
||||||
|
BORG_CHECK="0"
|
||||||
|
|
||||||
|
# rsync Optionen (CIFS-freundlich: kein owner/group/perms setzen)
|
||||||
|
# Zusätzlich: --temp-dir=/tmp -> rsync mkstemp NICHT auf CIFS (hilft bei CIFS-Reconnect/Timeouts)
|
||||||
|
RSYNC_OPTS=(-rltvh --info=progress2 --no-owner --no-group --no-perms --temp-dir=/tmp)
|
||||||
|
RSYNC_EXCLUDES=(--exclude="#recycle/" --exclude=".DS_Store" --exclude="._*" --exclude="Thumbs.db")
|
||||||
|
|
||||||
|
# Paperless Backup: echtes Sync (LÖSCHT auf Ziel, was in Quelle nicht mehr existiert)
|
||||||
|
RSYNC_DELETE_OPTS=(--delete --delete-delay)
|
||||||
|
|
||||||
|
# Optional: Testlauf für delete (auf "1" setzen um erstmal nur zu sehen, was gelöscht würde)
|
||||||
|
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 Backup
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
@@ -40,6 +89,8 @@ TOMEDO_LAST_FILE="${TOMEDO_SRC_ROOT}/lastFilesBackup"
|
|||||||
TOMEDO_DEST_ROOT="${CIFS_MOUNTPOINT}/TomedoBackup"
|
TOMEDO_DEST_ROOT="${CIFS_MOUNTPOINT}/TomedoBackup"
|
||||||
TOMEDO_MACOS_EXCLUDES="${TOMEDO_DEST_ROOT}/macos.excludes"
|
TOMEDO_MACOS_EXCLUDES="${TOMEDO_DEST_ROOT}/macos.excludes"
|
||||||
TOMEDO_FILES_EXCLUDES="${TOMEDO_DEST_ROOT}/files.excludes"
|
TOMEDO_FILES_EXCLUDES="${TOMEDO_DEST_ROOT}/files.excludes"
|
||||||
|
TOMEDO_RSYNC_MAX_RETRIES=3
|
||||||
|
TOMEDO_RSYNC_RETRY_SLEEP=5
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
# Hilfsfunktionen
|
# Hilfsfunktionen
|
||||||
@@ -88,7 +139,7 @@ cleanup() {
|
|||||||
set +e
|
set +e
|
||||||
log "== Cleanup =="
|
log "== Cleanup =="
|
||||||
|
|
||||||
if mountpoint -q "$CIFS_MOUNTPOINT"; then
|
if is_cifs_mounted; then
|
||||||
log "Unmount: $CIFS_MOUNTPOINT"
|
log "Unmount: $CIFS_MOUNTPOINT"
|
||||||
umount "$CIFS_MOUNTPOINT" 2>/dev/null || umount -l "$CIFS_MOUNTPOINT" || true
|
umount "$CIFS_MOUNTPOINT" 2>/dev/null || umount -l "$CIFS_MOUNTPOINT" || true
|
||||||
else
|
else
|
||||||
@@ -125,7 +176,7 @@ trap 'on_error $LINENO' ERR
|
|||||||
trap on_exit EXIT
|
trap on_exit EXIT
|
||||||
|
|
||||||
check_deps() {
|
check_deps() {
|
||||||
local deps=(wg-quick wg mount rsync ping mountpoint umount date sleep id mkdir rm dirname curl hostname flock cat)
|
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
|
for d in "${deps[@]}"; do
|
||||||
command -v "$d" >/dev/null 2>&1 || { echo "Fehlt: $d"; exit 1; }
|
command -v "$d" >/dev/null 2>&1 || { echo "Fehlt: $d"; exit 1; }
|
||||||
done
|
done
|
||||||
@@ -167,10 +218,14 @@ _mount_cifs_with_opts() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_cifs_mounted() {
|
||||||
|
awk -v mp="$CIFS_MOUNTPOINT" '$2 == mp && $3 == "cifs" { found=1 } END { exit(found ? 0 : 1) }' /proc/mounts
|
||||||
|
}
|
||||||
|
|
||||||
mount_cifs() {
|
mount_cifs() {
|
||||||
log "== CIFS mount: $CIFS_SHARE -> $CIFS_MOUNTPOINT =="
|
log "== CIFS mount: $CIFS_SHARE -> $CIFS_MOUNTPOINT =="
|
||||||
|
|
||||||
if mountpoint -q "$CIFS_MOUNTPOINT"; then
|
if is_cifs_mounted; then
|
||||||
log "Mountpoint ist gemountet -> versuche umount"
|
log "Mountpoint ist gemountet -> versuche umount"
|
||||||
umount "$CIFS_MOUNTPOINT" 2>/dev/null || umount -l "$CIFS_MOUNTPOINT" || true
|
umount "$CIFS_MOUNTPOINT" 2>/dev/null || umount -l "$CIFS_MOUNTPOINT" || true
|
||||||
fi
|
fi
|
||||||
@@ -190,34 +245,189 @@ mount_cifs() {
|
|||||||
_mount_cifs_with_opts "$opts_robust"
|
_mount_cifs_with_opts "$opts_robust"
|
||||||
local rc=$?
|
local rc=$?
|
||||||
set -e
|
set -e
|
||||||
if [[ $rc -eq 0 ]]; then
|
if [[ $rc -eq 0 ]] && is_cifs_mounted; then
|
||||||
log "OK gemountet (robust)."
|
log "OK gemountet (robust)."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if [[ $rc -eq 0 ]]; then
|
||||||
|
log "WARNUNG: mount meldet Erfolg, aber CIFS ist nicht stabil eingehängt."
|
||||||
|
fi
|
||||||
|
|
||||||
log "WARNUNG: CIFS mount (robust) fehlgeschlagen (rc=$rc). Fallback auf Basis-Optionen."
|
log "WARNUNG: CIFS mount (robust) fehlgeschlagen (rc=$rc). Fallback auf Basis-Optionen."
|
||||||
set +e
|
set +e
|
||||||
_mount_cifs_with_opts "$opts_base"
|
_mount_cifs_with_opts "$opts_base"
|
||||||
rc=$?
|
rc=$?
|
||||||
set -e
|
set -e
|
||||||
if [[ $rc -eq 0 ]]; then
|
if [[ $rc -eq 0 ]] && is_cifs_mounted; then
|
||||||
log "OK gemountet (base)."
|
log "OK gemountet (base)."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if [[ $rc -eq 0 ]]; then
|
||||||
|
log "WARNUNG: mount (base) meldet Erfolg, aber CIFS ist nicht stabil eingehängt."
|
||||||
|
fi
|
||||||
|
|
||||||
log "FEHLER: CIFS mount fehlgeschlagen (rc=$rc)."
|
log "FEHLER: CIFS mount fehlgeschlagen (rc=$rc)."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_cifs() {
|
ensure_cifs() {
|
||||||
if ! mountpoint -q "$CIFS_MOUNTPOINT"; then
|
local attempt
|
||||||
log "WARNUNG: CIFS nicht gemountet -> remount"
|
for ((attempt=1; attempt<=3; attempt++)); do
|
||||||
|
if is_cifs_mounted; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "WARNUNG: CIFS nicht gemountet -> remount (Versuch ${attempt}/3)"
|
||||||
mount_cifs
|
mount_cifs
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
if is_cifs_mounted; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log "FEHLER: CIFS Remount fehlgeschlagen."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
run_rsync_with_cifs_retry() {
|
||||||
|
local label="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
local attempt rc=0
|
||||||
|
for ((attempt=1; attempt<=TOMEDO_RSYNC_MAX_RETRIES; attempt++)); do
|
||||||
|
ensure_cifs
|
||||||
|
log "rsync ${label}: Versuch ${attempt}/${TOMEDO_RSYNC_MAX_RETRIES}"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
rsync "$@"
|
||||||
|
rc=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$rc" -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$rc" -eq 11 || "$rc" -eq 12 || "$rc" -eq 30 || "$rc" -eq 35 ]]; then
|
||||||
|
if [[ "$attempt" -lt "$TOMEDO_RSYNC_MAX_RETRIES" ]]; then
|
||||||
|
log "WARNUNG: rsync ${label} fehlgeschlagen (rc=$rc). Remount und Retry in ${TOMEDO_RSYNC_RETRY_SLEEP}s."
|
||||||
|
if is_cifs_mounted; then
|
||||||
|
umount "$CIFS_MOUNTPOINT" 2>/dev/null || umount -l "$CIFS_MOUNTPOINT" || true
|
||||||
|
fi
|
||||||
|
sleep "$TOMEDO_RSYNC_RETRY_SLEEP"
|
||||||
|
mount_cifs
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
log "FEHLER: rsync ${label} nach ${TOMEDO_RSYNC_MAX_RETRIES} Versuchen fehlgeschlagen (rc=$rc)."
|
||||||
|
return "$rc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "FEHLER: rsync ${label} fehlgeschlagen (rc=$rc)."
|
||||||
|
return "$rc"
|
||||||
|
done
|
||||||
|
|
||||||
|
return "$rc"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_to_paperless_flat_if_allowed_ext() {
|
||||||
|
local src="$1"
|
||||||
|
local rel="$2"
|
||||||
|
local base
|
||||||
|
base="$(basename "$src")"
|
||||||
|
|
||||||
|
[[ "$base" == ._* ]] && return 0
|
||||||
|
[[ ! "$base" =~ $CONSUME_EXT_REGEX ]] && return 0
|
||||||
|
|
||||||
|
mkdir -p "$PAPERLESS_CONSUME"
|
||||||
|
local dst="$PAPERLESS_CONSUME/$base"
|
||||||
|
|
||||||
|
if [[ -e "$dst" ]]; then
|
||||||
|
local ts name ext
|
||||||
|
ts="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
name="${base%.*}"
|
||||||
|
ext="${base##*.}"
|
||||||
|
if [[ "$base" == *.* && "$ext" != "$base" ]]; then
|
||||||
|
dst="$PAPERLESS_CONSUME/${name}_${ts}.${ext}"
|
||||||
|
else
|
||||||
|
dst="$PAPERLESS_CONSUME/${base}_${ts}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if ! mountpoint -q "$CIFS_MOUNTPOINT"; then
|
|
||||||
log "FEHLER: CIFS Remount fehlgeschlagen."
|
log "Paperless copy: $rel -> $(basename "$dst")"
|
||||||
|
cp --preserve=mode,timestamps -- "$src" "$dst" || {
|
||||||
|
log "WARNUNG: cp fehlgeschlagen: '$src' -> '$dst' (mache weiter)"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rsync_and_copy_to_consume_flat() {
|
||||||
|
local SRC="$1"
|
||||||
|
local DEST="$2"
|
||||||
|
local LABEL="$3"
|
||||||
|
|
||||||
|
ensure_cifs
|
||||||
|
|
||||||
|
log "== rsync ${LABEL}: $SRC -> $DEST =="
|
||||||
|
mkdir -p "$DEST"
|
||||||
|
|
||||||
|
local tmpfile rc
|
||||||
|
tmpfile="$(mktemp)"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
rsync "${RSYNC_OPTS[@]}" "${RSYNC_EXCLUDES[@]}" --out-format='%i %n' "$SRC" "$DEST" | tee "$tmpfile"
|
||||||
|
rc=${PIPESTATUS[0]}
|
||||||
|
set -e
|
||||||
|
|
||||||
|
log "rsync(${LABEL}) Exit-Code: $rc"
|
||||||
|
|
||||||
|
if [[ "$rc" -ne 0 && "$rc" -ne 23 && "$rc" -ne 24 ]]; then
|
||||||
|
log "FEHLER: rsync (${LABEL}) Exit-Code $rc"
|
||||||
|
exit "$rc"
|
||||||
|
fi
|
||||||
|
if [[ "$rc" -ne 0 ]]; then
|
||||||
|
log "WARNUNG: rsync (${LABEL}) Exit-Code $rc (mache trotzdem weiter)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "== Kopiere zusätzlich (${LABEL}) (NUR erlaubte Endungen, OHNE GIF) flach nach: $PAPERLESS_CONSUME =="
|
||||||
|
|
||||||
|
awk '
|
||||||
|
$1 !~ /^\./ && $1 ~ /^.[f]/ {
|
||||||
|
$1=""; sub(/^ /,""); print
|
||||||
|
}
|
||||||
|
' "$tmpfile" | while IFS= read -r rel; do
|
||||||
|
local local_src="${SRC}${rel}"
|
||||||
|
|
||||||
|
if [[ ! -f "$local_src" ]]; then
|
||||||
|
log "WARNUNG: Quelle nicht gefunden (überspringe): $local_src"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
copy_to_paperless_flat_if_allowed_ext "$local_src" "$rel"
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
rsync_paperless_backup() {
|
||||||
|
ensure_cifs
|
||||||
|
|
||||||
|
log "== rsync Paperless Backup (SYNC mit delete): $SRC_PAPERLESS_BACKUP -> $DEST_PAPERLESS_BACKUP =="
|
||||||
|
|
||||||
|
if [[ -z "$DEST_PAPERLESS_BACKUP" || "$DEST_PAPERLESS_BACKUP" == "/" ]]; then
|
||||||
|
log "FEHLER: DEST_PAPERLESS_BACKUP ist unsicher gesetzt."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$DEST_PAPERLESS_BACKUP"
|
||||||
|
|
||||||
|
local extra=()
|
||||||
|
if [[ "$DRY_RUN_DELETE" == "1" ]]; then
|
||||||
|
extra+=(--dry-run)
|
||||||
|
log "HINWEIS: DRY RUN aktiv (es wird nichts wirklich gelöscht/kopiert)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rsync "${RSYNC_OPTS[@]}" "${RSYNC_EXCLUDES[@]}" "${RSYNC_DELETE_OPTS[@]}" "${extra[@]}" \
|
||||||
|
"$SRC_PAPERLESS_BACKUP" "$DEST_PAPERLESS_BACKUP"
|
||||||
}
|
}
|
||||||
|
|
||||||
rsync_tomedo_backup() {
|
rsync_tomedo_backup() {
|
||||||
@@ -264,15 +474,16 @@ rsync_tomedo_backup() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$dst_snapshot" "$dst_files"
|
mkdir -p "$dst_snapshot" "$dst_files"
|
||||||
|
local tomedo_rsync_opts=(-r -l -t -O --info=progress2 --temp-dir=/tmp)
|
||||||
|
|
||||||
log "== rsync Tomedo Snapshot: $src_snapshot -> $dst_snapshot =="
|
log "== rsync Tomedo Snapshot: $src_snapshot -> $dst_snapshot =="
|
||||||
rsync -r -l -t -O --info=progress2 \
|
run_rsync_with_cifs_retry "Tomedo Snapshot" "${tomedo_rsync_opts[@]}" \
|
||||||
--exclude-from "$TOMEDO_MACOS_EXCLUDES" \
|
--exclude-from "$TOMEDO_MACOS_EXCLUDES" \
|
||||||
"$src_snapshot" \
|
"$src_snapshot" \
|
||||||
"$dst_snapshot"
|
"$dst_snapshot"
|
||||||
|
|
||||||
log "== rsync Tomedo Files: $src_files -> $dst_files =="
|
log "== rsync Tomedo Files: $src_files -> $dst_files =="
|
||||||
rsync -r -l -t -O --info=progress2 \
|
run_rsync_with_cifs_retry "Tomedo Files" "${tomedo_rsync_opts[@]}" \
|
||||||
--exclude-from "$TOMEDO_MACOS_EXCLUDES" \
|
--exclude-from "$TOMEDO_MACOS_EXCLUDES" \
|
||||||
--exclude-from "$TOMEDO_FILES_EXCLUDES" \
|
--exclude-from "$TOMEDO_FILES_EXCLUDES" \
|
||||||
"$src_files" \
|
"$src_files" \
|
||||||
@@ -281,6 +492,107 @@ rsync_tomedo_backup() {
|
|||||||
log "== Tomedo Backup fertig: $last_backup =="
|
log "== Tomedo Backup fertig: $last_backup =="
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Borg: lokal sichern + Mirror auf CIFS
|
||||||
|
# -----------------------------
|
||||||
|
run_borg_allow_warning() {
|
||||||
|
local label="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
local rc
|
||||||
|
set +e
|
||||||
|
"$@"
|
||||||
|
rc=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$rc" -ge 2 ]]; then
|
||||||
|
log "FEHLER: ${label} fehlgeschlagen (Exit-Code ${rc})."
|
||||||
|
return "$rc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$rc" -eq 1 ]]; then
|
||||||
|
log "WARNUNG: ${label} mit Warnungen beendet (Exit-Code 1), mache weiter."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
borg_local_backup() {
|
||||||
|
log "== Borg lokal Backup -> $LOCAL_BORG_REPO =="
|
||||||
|
|
||||||
|
if [[ ! -d "$LOCAL_BORG_REPO" ]]; then
|
||||||
|
log "FEHLER: Lokales Borg Repo fehlt: $LOCAL_BORG_REPO (einmal borg init ausführen)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$BORG_PASSPHRASE_FILE" ]]; then
|
||||||
|
log "FEHLER: Passphrase-Datei fehlt: $BORG_PASSPHRASE_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export BORG_PASSPHRASE
|
||||||
|
BORG_PASSPHRASE="$(<"$BORG_PASSPHRASE_FILE")"
|
||||||
|
export BORG_LOCK_WAIT="$BORG_LOCK_WAIT"
|
||||||
|
|
||||||
|
local archive="agathe-$(hostname)-$(date +%F_%H%M%S)"
|
||||||
|
log "Platz lokal: $(df -h "$LOCAL_BORG_BASE" | tail -1)"
|
||||||
|
|
||||||
|
run_borg_allow_warning "borg create" borg create --stats --compression zstd,6 \
|
||||||
|
"$LOCAL_BORG_REPO::$archive" \
|
||||||
|
/ \
|
||||||
|
/boot \
|
||||||
|
/boot/efi \
|
||||||
|
--numeric-ids \
|
||||||
|
--one-file-system \
|
||||||
|
--exclude /proc \
|
||||||
|
--exclude /sys \
|
||||||
|
--exclude /dev \
|
||||||
|
--exclude /run \
|
||||||
|
--exclude /tmp \
|
||||||
|
--exclude /var/tmp \
|
||||||
|
--exclude /mnt \
|
||||||
|
--exclude /media \
|
||||||
|
--exclude /var/cache \
|
||||||
|
--exclude /var/lib/docker \
|
||||||
|
--exclude /var/lib/containerd \
|
||||||
|
--exclude /swapfile \
|
||||||
|
--exclude /mnt/paperless \
|
||||||
|
--exclude /mnt/paperless-consume \
|
||||||
|
--exclude /mnt/paperless-backup \
|
||||||
|
--exclude /mnt/nchsdhg_agathe \
|
||||||
|
--exclude /mnt/groot \
|
||||||
|
--exclude-caches
|
||||||
|
|
||||||
|
run_borg_allow_warning "borg prune" borg prune -v --list "$LOCAL_BORG_REPO" \
|
||||||
|
--keep-daily="$KEEP_DAILY" \
|
||||||
|
--keep-weekly="$KEEP_WEEKLY" \
|
||||||
|
--keep-monthly="$KEEP_MONTHLY" \
|
||||||
|
--prefix "agathe-$(hostname)-"
|
||||||
|
|
||||||
|
if [[ "$BORG_CHECK" == "1" ]]; then
|
||||||
|
run_borg_allow_warning "borg check" borg check -v --verify-data "$LOCAL_BORG_REPO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Lokales Borg Backup fertig: $archive"
|
||||||
|
}
|
||||||
|
|
||||||
|
rsync_borg_mirror_to_cifs() {
|
||||||
|
log "== Spiegel Borg Repo per rsync -> $REMOTE_BORG_MIRROR =="
|
||||||
|
|
||||||
|
ensure_cifs
|
||||||
|
mkdir -p "$REMOTE_BORG_MIRROR"
|
||||||
|
|
||||||
|
local extra=()
|
||||||
|
if [[ "$MIRROR_DELETE" == "1" ]]; then
|
||||||
|
extra+=(--delete --delete-delay)
|
||||||
|
log "Mirror: delete aktiv (Ziel wird an Quelle angepasst)."
|
||||||
|
else
|
||||||
|
log "Mirror: delete NICHT aktiv."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rsync -rltvh --info=progress2 --no-owner --no-group --no-perms --temp-dir=/tmp \
|
||||||
|
"${extra[@]}" \
|
||||||
|
"$LOCAL_BORG_REPO/" \
|
||||||
|
"$REMOTE_BORG_MIRROR/"
|
||||||
|
}
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
# Main
|
# Main
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
@@ -293,7 +605,14 @@ send_pushover "Backup START auf $(hostname) um $(ts_now)."
|
|||||||
bringup_wg
|
bringup_wg
|
||||||
mount_cifs
|
mount_cifs
|
||||||
|
|
||||||
|
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
|
rsync_tomedo_backup
|
||||||
|
|
||||||
|
borg_local_backup
|
||||||
|
rsync_borg_mirror_to_cifs
|
||||||
|
|
||||||
log "== Fertig. =="
|
log "== Fertig. =="
|
||||||
send_pushover "Backup ENDE auf $(hostname) um $(ts_now)."
|
send_pushover "Backup ENDE auf $(hostname) um $(ts_now)."
|
||||||
|
|||||||
Reference in New Issue
Block a user