#!/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 "$@"