diff --git a/backup-rdx.sh b/backup-rdx.sh new file mode 100644 index 0000000..f0cdbb4 --- /dev/null +++ b/backup-rdx.sh @@ -0,0 +1,194 @@ +#!/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 "$@" \ No newline at end of file