#!/bin/bash # Dell N2048 Switch FTP Backup Script mit expect # Automatisches Backup der startup-config oder running-config auf FTP-Server via SSH #=========================================== # KONFIGURATION #=========================================== # Switch-Zugangsdaten SWITCH_IP="10.10.11.51" SWITCH_USER="switch-backup" SWITCH_PASSWORD="password" # FTP-Server-Details (basierend auf Ihrem Beispiel) FTP_SERVER="10.10.11.45" FTP_USER="switch-backup" FTP_PASSWORD="password" FTP_PATH="switch-backup" # BACKUP-KONFIGURATION CONFIG_TYPE="startup-config" # "startup-config" oder "running-config" MAX_BACKUPS=10 # Anzahl Backups die behalten werden sollen SKIP_SSH_TEST=true # SSH-Test überspringen für bessere Performance # Backup-Einstellungen (max 32 Zeichen für Dateiname) SWITCH_NAME="cube" # Kurzer Switch-Name CONFIG_PREFIX="sc" # "sc" für startup-config, "rc" für running-config if [ "$CONFIG_TYPE" = "running-config" ]; then CONFIG_PREFIX="rc" fi # Dateiname: cube_sc_20250625_0021.cfg = 24 Zeichen (max 32) TIMESTAMP=$(date +"%Y%m%d_%H%M") BACKUP_FILENAME="${SWITCH_NAME}_${CONFIG_PREFIX}_${TIMESTAMP}.cfg" # Logging LOG_FILE="$BACKUP_FILENAME.log" # Timeout-Werte (reduziert für bessere Performance) SSH_TIMEOUT=15 COMMAND_TIMEOUT=30 COPY_TIMEOUT=90 #=========================================== # FUNKTIONEN #=========================================== # Logging-Funktion log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" } # Prüfe ob expect installiert ist check_dependencies() { if ! command -v expect >/dev/null 2>&1; then log "FEHLER: expect ist nicht installiert." log "Installation: sudo apt-get install expect" exit 1 fi if ! command -v ftp >/dev/null 2>&1; then log "WARNUNG: ftp-client nicht installiert - FTP-Cleanup nicht möglich" log "Installation: sudo apt-get install ftp" fi } # Validiere Dateiname-Länge validate_filename() { if [ ${#BACKUP_FILENAME} -gt 32 ]; then log "FEHLER: Dateiname zu lang (${#BACKUP_FILENAME} > 32 Zeichen): $BACKUP_FILENAME" log "Kürzen Sie SWITCH_NAME oder CONFIG_PREFIX" exit 1 fi log "Dateiname-Länge OK: $BACKUP_FILENAME (${#BACKUP_FILENAME} Zeichen)" } # Teste SSH-Verbindung mit expect (optional für Performance) test_ssh_connection() { if [ "$SKIP_SSH_TEST" = "true" ]; then log "SSH-Test übersprungen (SKIP_SSH_TEST=true)" return 0 fi log "Teste SSH-Verbindung zu $SWITCH_IP..." expect << EOF >/dev/null 2>&1 set timeout $SSH_TIMEOUT spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $SWITCH_USER@$SWITCH_IP expect { "password:" { send "$SWITCH_PASSWORD\r" expect { ">" { send "exit\r" expect eof exit 0 } "#" { send "exit\r" expect eof exit 0 } timeout { exit 1 } eof { exit 1 } } } timeout { exit 1 } eof { exit 1 } } EOF local result=$? if [ $result -eq 0 ]; then log "SSH-Verbindung erfolgreich" return 0 else log "FEHLER: SSH-Verbindung fehlgeschlagen" return 1 fi } # FTP-Backup mit expect ausführen execute_ftp_backup() { log "Starte FTP-Backup: $CONFIG_TYPE -> ftp://$FTP_SERVER/$BACKUP_FILENAME" # FTP-Befehl OHNE Passwort im URL local ftp_command="copy $CONFIG_TYPE ftp://$FTP_USER@$FTP_SERVER/$FTP_PATH/$BACKUP_FILENAME" # Temporäre Datei für expect-Ausgabe local temp_output="/tmp/switch_backup_output_$$" expect << EOF > "$temp_output" 2>&1 set timeout $SSH_TIMEOUT log_user 0 spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $SWITCH_USER@$SWITCH_IP expect { "password:" { send "$SWITCH_PASSWORD\r" expect { ">" { # User-Mode, enable ausführen send "enable\r" expect { "#" { # Enable-Mode, copy-Befehl ausführen send "$ftp_command\r" expect { "Remote Password:" { # Switch fragt nach FTP-Passwort send "$FTP_PASSWORD\r" expect { "Are you sure you want to start? (y/n)" { # Bestätigung erforderlich send "y\r" set timeout $COPY_TIMEOUT expect { -re "(File transfer operation completed successfully|transfer.*completed|bytes transferred)" { send "exit\r" expect eof exit 0 } -re "(Error|Failed|failed|Timeout|timeout|Access denied|denied)" { send "exit\r" expect eof exit 2 } timeout { send "exit\r" expect eof exit 3 } } } -re "(Error|Failed|Invalid|Access denied)" { send "exit\r" expect eof exit 2 } timeout { send "exit\r" expect eof exit 3 } } } -re "(Error|Failed|Invalid|Access denied)" { send "exit\r" expect eof exit 2 } timeout { send "exit\r" expect eof exit 3 } } } "password:" { # Enable-Passwort erforderlich send "$SWITCH_PASSWORD\r" expect "#" send "$ftp_command\r" expect { "Remote Password:" { send "$FTP_PASSWORD\r" expect { "Are you sure you want to start? (y/n)" { send "y\r" set timeout $COPY_TIMEOUT expect { -re "(File transfer operation completed successfully|transfer.*completed|bytes transferred)" { send "exit\r" expect eof exit 0 } -re "(Error|Failed|failed|Timeout|timeout|Access denied|denied)" { send "exit\r" expect eof exit 2 } timeout { send "exit\r" expect eof exit 3 } } } timeout { exit 3 } } } timeout { exit 3 } } } timeout { exit 1 } } } "#" { # Bereits im Enable-Mode send "$ftp_command\r" expect { "Remote Password:" { send "$FTP_PASSWORD\r" expect { "Are you sure you want to start? (y/n)" { send "y\r" set timeout $COPY_TIMEOUT expect { -re "(File transfer operation completed successfully|transfer.*completed|bytes transferred)" { send "exit\r" expect eof exit 0 } -re "(Error|Failed|failed|Timeout|timeout|Access denied|denied)" { send "exit\r" expect eof exit 2 } timeout { send "exit\r" expect eof exit 3 } } } timeout { exit 3 } } } timeout { exit 3 } } } timeout { exit 1 } eof { exit 1 } } } timeout { exit 1 } eof { exit 1 } } EOF local result=$? local output=$(cat "$temp_output" 2>/dev/null) # Nur relevante Ausgabe loggen (verkürzt) local bytes_transferred=$(echo "$output" | grep "bytes transferred" | tail -1) if [ -n "$bytes_transferred" ]; then log "Transfer: $bytes_transferred" fi # Cleanup rm -f "$temp_output" # Ergebnis auswerten case $result in 0) log "FTP-Backup erfolgreich abgeschlossen" return 0 ;; 1) log "FEHLER: SSH-Verbindung oder Anmeldung fehlgeschlagen" return 1 ;; 2) log "FEHLER: FTP-Copy-Befehl fehlgeschlagen (Fehlermeldung erkannt)" return 1 ;; 3) log "FEHLER: Timeout beim FTP-Copy-Befehl" return 1 ;; *) log "FEHLER: Unbekannter Fehler (Exit-Code: $result)" return 1 ;; esac } # Alte Backups auf FTP-Server löschen cleanup_old_backups() { if ! command -v ftp >/dev/null 2>&1; then log "FTP-Client nicht verfügbar - Cleanup übersprungen" return 0 fi log "Bereinige alte Backups (behalte die neuesten $MAX_BACKUPS)..." # Temporäre Dateien local ftp_list="/tmp/ftp_list_$$" local files_to_delete="/tmp/files_to_delete_$$" # FTP-Verzeichnis auflisten ftp -n "$FTP_SERVER" << EOF > "$ftp_list" 2>/dev/null user $FTP_USER $FTP_PASSWORD cd $FTP_PATH ls ${SWITCH_NAME}_${CONFIG_PREFIX}_*.cfg quit EOF # Extrahiere nur Dateinamen und sortiere nach Datum (neueste zuerst) grep "\.cfg$" "$ftp_list" | awk '{print $NF}' | grep "^${SWITCH_NAME}_${CONFIG_PREFIX}_" | sort -r > "$files_to_delete" local total_files=$(wc -l < "$files_to_delete") if [ "$total_files" -gt "$MAX_BACKUPS" ]; then local files_to_remove=$((total_files - MAX_BACKUPS)) log "Gefunden: $total_files Backup-Dateien, lösche die ältesten $files_to_remove" # Die ältesten Dateien löschen (ab Zeile MAX_BACKUPS+1) tail -n +"$((MAX_BACKUPS + 1))" "$files_to_delete" | while read -r filename; do if [ -n "$filename" ]; then log "Lösche alte Backup-Datei: $filename" ftp -n "$FTP_SERVER" << EOF >/dev/null 2>&1 user $FTP_USER $FTP_PASSWORD cd $FTP_PATH delete $filename quit EOF fi done else log "Cleanup: $total_files Dateien gefunden, alle werden behalten (< $MAX_BACKUPS)" fi # Cleanup rm -f "$ftp_list" "$files_to_delete" } #=========================================== # HAUPTPROGRAMM #=========================================== log "==========================================" log "Dell N2048 FTP Backup gestartet (optimiert)" log "Switch: $SWITCH_IP" log "Config-Type: $CONFIG_TYPE" log "FTP-Server: $FTP_SERVER" log "Backup-Datei: $BACKUP_FILENAME" log "Max Backups: $MAX_BACKUPS" log "==========================================" # 1. Abhängigkeiten prüfen check_dependencies # 2. Dateiname validieren validate_filename # 3. SSH-Verbindung testen (optional) if ! test_ssh_connection; then log "Backup abgebrochen wegen SSH-Verbindungsproblem" exit 1 fi # 4. FTP-Backup ausführen backup_start_time=$(date +%s) if execute_ftp_backup; then backup_end_time=$(date +%s) backup_duration=$((backup_end_time - backup_start_time)) log "Backup-Dauer: ${backup_duration} Sekunden" # 5. Alte Backups bereinigen cleanup_old_backups log "==========================================" log "BACKUP ERFOLGREICH ABGESCHLOSSEN" log "Datei auf FTP-Server: $BACKUP_FILENAME" log "Backup-Dauer: ${backup_duration} Sekunden" log "==========================================" exit 0 else log "==========================================" log "BACKUP FEHLGESCHLAGEN" log "Prüfen Sie FTP-Server-Verbindung und Zugangsdaten" log "==========================================" exit 1 fi