DellSwitchBackup/ftp_backup.sh

482 lines
16 KiB
Bash

#!/bin/bash
# Dell N2048 Switch FTP Backup Script mit externer Konfiguration
# Aufruf: ./switch_backup.sh <konfig_name>
# Konfiguration: /etc/switchbackup/<konfig_name>.cfg
#===========================================
# GRUNDKONFIGURATION
#===========================================
# Pfad zu den Konfigurationsdateien
CONFIG_DIR="/etc/switchbackup"
SCRIPT_NAME=$(basename "$0")
# Logging
LOG_FILE="/var/log/dell_switch_backup.log"
#===========================================
# PARAMETER PRÜFUNG
#===========================================
if [ $# -eq 0 ]; then
echo "FEHLER: Keine Konfiguration angegeben!"
echo ""
echo "Verwendung: $SCRIPT_NAME <konfig_name>"
echo ""
echo "Beispiele:"
echo " $SCRIPT_NAME switch01"
echo " $SCRIPT_NAME datacenter-core"
echo ""
echo "Konfigurationsdateien unter: $CONFIG_DIR/"
echo "Verfügbare Konfigurationen:"
if [ -d "$CONFIG_DIR" ]; then
ls -1 "$CONFIG_DIR"/*.cfg 2>/dev/null | sed 's|.*/||; s|\.cfg$||' | sed 's/^/ - /' || echo " (keine gefunden)"
else
echo " (Verzeichnis $CONFIG_DIR existiert nicht)"
fi
exit 1
fi
CONFIG_NAME="$1"
CONFIG_FILE="$CONFIG_DIR/${CONFIG_NAME}.cfg"
#===========================================
# KONFIGURATION LADEN
#===========================================
# Prüfe ob Konfigurationsdatei existiert
if [ ! -f "$CONFIG_FILE" ]; then
echo "FEHLER: Konfigurationsdatei nicht gefunden: $CONFIG_FILE"
echo ""
echo "Verfügbare Konfigurationen:"
if [ -d "$CONFIG_DIR" ]; then
ls -1 "$CONFIG_DIR"/*.cfg 2>/dev/null | sed 's|.*/||; s|\.cfg$||' | sed 's/^/ - /' || echo " (keine gefunden)"
else
echo " (Verzeichnis $CONFIG_DIR existiert nicht)"
echo ""
echo "Erstellen Sie das Verzeichnis mit:"
echo " sudo mkdir -p $CONFIG_DIR"
fi
exit 1
fi
# Konfiguration laden
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') [$CONFIG_NAME] - $1" | tee -a "$LOG_FILE"
}
log "Lade Konfiguration: $CONFIG_FILE"
# Source die Konfigurationsdatei
source "$CONFIG_FILE"
# Validiere erforderliche Parameter
required_vars="SWITCH_IP SWITCH_USER SWITCH_PASSWORD FTP_SERVER FTP_USER FTP_PASSWORD"
missing_vars=""
for var in $required_vars; do
if [ -z "${!var}" ]; then
missing_vars="$missing_vars $var"
fi
done
if [ -n "$missing_vars" ]; then
log "FEHLER: Fehlende Parameter in $CONFIG_FILE:$missing_vars"
exit 1
fi
# Setze Standardwerte falls nicht definiert
CONFIG_TYPE="${CONFIG_TYPE:-startup-config}"
MAX_BACKUPS="${MAX_BACKUPS:-10}"
SKIP_SSH_TEST="${SKIP_SSH_TEST:-true}"
SWITCH_NAME="${SWITCH_NAME:-${CONFIG_NAME}}"
FTP_PATH="${FTP_PATH:-switch-backup}"
# Config-Prefix ableiten
CONFIG_PREFIX="sc"
if [ "$CONFIG_TYPE" = "running-config" ]; then
CONFIG_PREFIX="rc"
fi
# Dateiname generieren (max 32 Zeichen)
TIMESTAMP=$(date +"%Y%m%d_%H%M")
BACKUP_FILENAME="${SWITCH_NAME}_${CONFIG_PREFIX}_${TIMESTAMP}.cfg"
# Timeout-Werte
SSH_TIMEOUT="${SSH_TIMEOUT:-15}"
COMMAND_TIMEOUT="${COMMAND_TIMEOUT:-30}"
COPY_TIMEOUT="${COPY_TIMEOUT:-90}"
#===========================================
# FUNKTIONEN
#===========================================
# 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 in der Konfiguration"
exit 1
fi
log "Dateiname-Länge OK: $BACKUP_FILENAME (${#BACKUP_FILENAME} Zeichen)"
}
# Teste SSH-Verbindung mit expect (optional)
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
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"
log "Konfiguration: $CONFIG_NAME"
log "Switch: $SWITCH_IP ($SWITCH_NAME)"
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 "Konfiguration: $CONFIG_NAME"
log "Datei auf FTP-Server: $BACKUP_FILENAME"
log "Backup-Dauer: ${backup_duration} Sekunden"
log "=========================================="
exit 0
else
log "=========================================="
log "BACKUP FEHLGESCHLAGEN"
log "Konfiguration: $CONFIG_NAME"
log "Prüfen Sie FTP-Server-Verbindung und Zugangsdaten"
log "=========================================="
exit 1
fi