From 1d17d6f8ff20bdaca7f58da9304601623a837af1 Mon Sep 17 00:00:00 2001 From: Hans-Chritian Payer Date: Tue, 28 Apr 2026 08:38:29 +0000 Subject: [PATCH] Neue Datei hochladen --- sicherung_robust.sh | 137 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 sicherung_robust.sh diff --git a/sicherung_robust.sh b/sicherung_robust.sh new file mode 100644 index 0000000..ede0abc --- /dev/null +++ b/sicherung_robust.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +######################################## +# Konfiguration +######################################## + +SRC="${HOME}/" +DEST_BASE="/run/media/hans/usbsicherung/jacboy_sicherung" +HOST="$(hostname -s)" +STAMP="$(date +%F_%H-%M-%S)" +SNAPSHOT_DIR="${DEST_BASE}/${HOST}/${STAMP}" +LAST_LINK="${DEST_BASE}/${HOST}/latest" +LOG_DIR="${DEST_BASE}/${HOST}/logs" +LOG_FILE="${LOG_DIR}/backup-${STAMP}.log" + +# Anzahl der aufzubewahrenden Snapshots +KEEP=30 + +######################################## +# Hilfsfunktionen +######################################## + +log() { + # Schreibt gleichzeitig auf stdout und ins Log (wenn LOG_FILE existiert) + local msg="[$(date +%F\ %T)] $*" + echo "${msg}" + if [[ -n "${LOG_FILE:-}" ]]; then + mkdir -p "$(dirname "${LOG_FILE}")" + echo "${msg}" >> "${LOG_FILE}" + fi +} + +fail() { + log "FEHLER: $*" + exit 1 +} + +######################################## +# Vorprüfungen +######################################## + +# 1. Zielbasis muss existieren und beschreibbar sein +if [[ ! -d "${DEST_BASE}" ]]; then + fail "Zielbasis ${DEST_BASE} existiert nicht oder ist nicht gemountet. Bitte USB-Laufwerk prüfen." +fi + +if [[ ! -w "${DEST_BASE}" ]]; then + fail "Zielbasis ${DEST_BASE} ist nicht beschreibbar. Rechte/Mount prüfen." +fi + +# 2. Snapshot- und Log-Verzeichnisse anlegen +mkdir -p "${SNAPSHOT_DIR}" "${LOG_DIR}" + +log "Starte Backup: ${SRC} -> ${SNAPSHOT_DIR}" + +######################################## +# rsync-Optionen +######################################## + +RSYNC_OPTS=( + -aHAXx + --numeric-ids + --delete + --delete-excluded + --info=stats2,progress2 + --human-readable + --partial +) + +EXCLUDES=( + --exclude=".cache/" + --exclude="Downloads/" + --exclude=".local/share/Trash/" + --exclude=".gvfs/" + --exclude=".dotnet/" + --exclude=".codegpt/" + --exclude=".copilot/" + --exclude=".var/" + --exclude=".vscode/" + #--exclude="temp/" +) + +# Wenn es bereits einen gültigen "latest"-Snapshot gibt, diesen als link-dest verwenden +if [[ -L "${LAST_LINK}" ]] && [[ -d "$(readlink -f "${LAST_LINK}")" ]]; then + RSYNC_OPTS+=(--link-dest="$(readlink -f "${LAST_LINK}")") + log "Verwende link-dest: $(readlink -f "${LAST_LINK}")" +else + log "Kein gültiger letzter Snapshot gefunden – es wird ein vollständiger Lauf erstellt." +fi + +######################################## +# rsync-Lauf +######################################## + +# Optional: Dry-Run zum Testen (auskommentieren, wenn du real sichern willst) +# RSYNC_OPTS+=(--dry-run) + +log "Starte rsync..." +if rsync "${RSYNC_OPTS[@]}" \ + "${EXCLUDES[@]}" \ + "${SRC}" "${SNAPSHOT_DIR}/" | tee -a "${LOG_FILE}" +then + log "rsync erfolgreich abgeschlossen." +else + fail "rsync ist mit einem Fehler beendet worden." +fi + +######################################## +# latest-Symlink aktualisieren +######################################## + +ln -sfn "${SNAPSHOT_DIR}" "${LAST_LINK}" +log "latest-Link zeigt jetzt auf ${SNAPSHOT_DIR}" + +######################################## +# Snapshot-Rotation +######################################## + +cd "${DEST_BASE}/${HOST}" + +# Nur Verzeichnisse mit Datum/Zeit-Präfix (Beginn mit '20') betrachten +SNAPS=(20*/) + +if (( ${#SNAPS[@]} > KEEP )); then + log "Rotationslauf: Es existieren ${#SNAPS[@]} Snapshots, KEEP=${KEEP}." + + # Sortiert nach Datum (neuestes zuerst), alle älteren als KEEP löschen + ls -1dt 20*/ | tail -n +$((KEEP + 1)) | while read -r old; do + log "Lösche alten Snapshot: ${old}" + rm -rf -- "${old}" + done +else + log "Rotationslauf: Es müssen keine alten Snapshots gelöscht werden (Anzahl: ${#SNAPS[@]}, KEEP=${KEEP})." +fi + +log "Backup abgeschlossen." \ No newline at end of file