Files
Homelab/backup-rdx.sh
2026-02-28 12:51:20 +00:00

194 lines
6.2 KiB
Bash

#!/bin/bash
# =============================================================================
# backup.sh - Automatisches Backup mit rsync und Auto-Mount
# =============================================================================
# --- Konfiguration -----------------------------------------------------------
# Quellordner die gesichert werden sollen (Leerzeichen-getrennt oder als Array)
SOURCE_DIRS=(
"/mnt/user/public"
"/mnt/user/nicole"
"/mnt/user/skylab"
)
# Label oder UUID der Ziel-Festplatte
# UUID ermitteln mit: blkid
# Label ermitteln mit: lsblk -o NAME,LABEL
TARGET_LABEL="" # Festplatten-Label (leer lassen wenn UUID genutzt)
TARGET_UUID="9ca4c5db-bcee-45df-ac5b-13210b4eae7d" # Backup-Festplatte
# Ziel-Verzeichnis auf der Backup-Festplatte
# Leer lassen = direkt ins Root der RDX kopieren
# Jeder Quellordner bekommt dort seinen eigenen Unterordner (z.B. /Dokumente, /Bilder ...)
BACKUP_DIR=""
# rsync Optionen
DELETED_DIR="/_deleted" # Ordner auf der RDX für gelöschte Dateien
DELETED_MAX_DAYS=30 # Nach wie vielen Tagen werden sie endgültig gelöscht
RSYNC_OPTS="-avh --progress --exclude='*.tmp' --exclude='.Trash*'"
# Mount-Punkt (wird automatisch erstellt falls nicht vorhanden)
MOUNT_POINT="/mnt/rdx"
# Log-Datei
LOG_FILE="$HOME/.backup_log"
# -----------------------------------------------------------------------------
# Farben
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log() { echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; }
info() { log "${GREEN}[INFO]${NC} $1"; }
warn() { log "${YELLOW}[WARN]${NC} $1"; }
error() { log "${RED}[ERROR]${NC} $1"; }
# --- Festplatte finden -------------------------------------------------------
find_device() {
local device=""
if [[ -n "$TARGET_UUID" ]]; then
device=$(blkid -U "$TARGET_UUID" 2>/dev/null)
elif [[ -n "$TARGET_LABEL" ]]; then
device=$(blkid -L "$TARGET_LABEL" 2>/dev/null)
fi
if [[ -z "$device" ]]; then
error "Festplatte nicht gefunden! Überprüfe UUID/Label in der Konfiguration."
error "Verfügbare Geräte:"
lsblk -o NAME,LABEL,UUID,SIZE,TYPE | grep -v "loop" | tee -a "$LOG_FILE"
exit 1
fi
echo "$device"
}
# --- Festplatte mounten ------------------------------------------------------
mount_drive() {
local device="$1"
# Prüfen ob bereits gemountet
if mount | grep -q "$device"; then
MOUNT_POINT=$(mount | grep "$device" | awk '{print $3}' | head -1)
info "Gerät $device ist bereits gemountet unter $MOUNT_POINT"
return 0
fi
# Mount-Punkt erstellen
if [[ ! -d "$MOUNT_POINT" ]]; then
info "Erstelle Mount-Punkt: $MOUNT_POINT"
sudo mkdir -p "$MOUNT_POINT" || { error "Mount-Punkt konnte nicht erstellt werden."; exit 1; }
fi
# Mounten
info "Mounte $device nach $MOUNT_POINT ..."
sudo mount "$device" "$MOUNT_POINT" || { error "Mount fehlgeschlagen!"; exit 1; }
info "Erfolgreich gemountet."
}
cleanup_deleted() {
local deleted_base="${MOUNT_POINT}${DELETED_DIR}"
if [[ ! -d "$deleted_base" ]]; then
return 0
fi
info "Räume /_geloescht auf: Einträge älter als ${DELETED_MAX_DAYS} Tage werden gelöscht ..."
find "$deleted_base" -mindepth 1 -maxdepth 3 -type d -mtime +${DELETED_MAX_DAYS} | while read -r old_dir; do
info "Lösche altes Backup-Verzeichnis: $old_dir"
rm -rf "$old_dir"
done
find "$deleted_base" -mindepth 1 -type d -empty -delete 2>/dev/null
info "Aufräumen abgeschlossen."
}
# --- Backup durchführen ------------------------------------------------------
run_backup() {
# Basis-Ziel: Root der RDX (oder Unterordner falls BACKUP_DIR gesetzt)
local base="${MOUNT_POINT}${BACKUP_DIR:+/$BACKUP_DIR}"
info "Starte Backup nach: $base"
echo "-----------------------------------------------------------" | tee -a "$LOG_FILE"
local errors=0
for src in "${SOURCE_DIRS[@]}"; do
if [[ ! -d "$src" ]]; then
warn "Quellordner existiert nicht, überspringe: $src"
continue
fi
# Ordnername extrahieren (z.B. /home/user/Dokumente → Dokumente)
local folder_name
folder_name=$(basename "$src")
# Jeder Ordner bekommt seinen eigenen Unterordner auf der RDX
local dest="$base/$folder_name"
mkdir -p "$dest" || { error "Zielverzeichnis konnte nicht erstellt werden: $dest"; ((errors++)); continue; }
info "Synchronisiere: $src$dest"
local deleted_dest="${MOUNT_POINT}${DELETED_DIR}/${folder_name}/$(date '+%Y-%m-%d')"
rsync $RSYNC_OPTS --delete --backup --backup-dir="$deleted_dest" "$src/" "$dest/" 2>&1 | tee -a "$LOG_FILE"
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
error "rsync fehlgeschlagen für: $src"
((errors++))
else
info "Fertig: $src$dest"
fi
done
cleanup_deleted
echo "-----------------------------------------------------------" | tee -a "$LOG_FILE"
if [[ $errors -eq 0 ]]; then
info "Backup erfolgreich abgeschlossen!"
else
warn "Backup abgeschlossen mit $errors Fehler(n). Siehe Log: $LOG_FILE"
fi
}
# --- Aufräumen ---------------------------------------------------------------
eject_drive() {
if mount | grep -q "$MOUNT_POINT"; then
info "Werfe RDX aus ..."
# Gerät VOR dem umount ermitteln
local device
device=$(mount | grep "$MOUNT_POINT" | awk '{print $1}')
info "Gerät: $device"
sudo umount "$MOUNT_POINT" || { warn "umount fehlgeschlagen!"; return 1; }
sudo eject "$device" && info "RDX erfolgreich ausgeworfen." || warn "eject fehlgeschlagen."
fi
}
# --- Hauptprogramm -----------------------------------------------------------
main() {
info "=== Backup gestartet ==="
# Root-Rechte prüfen (für mount)
if ! sudo -n true 2>/dev/null; then
warn "Sudo-Passwort wird für mount/umount benötigt."
fi
local device
device=$(find_device)
info "Festplatte gefunden: $device"
mount_drive "$device"
run_backup
# Optional: Festplatte nach Backup aushängen (auskommentieren zum Deaktivieren)
eject_drive
info "=== Backup beendet ==="
}
main "$@"