276 lines
8.1 KiB
Bash
Executable File
276 lines
8.1 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# =============================================================================
|
||
# TimeClock v3 - Backup-Restore Script
|
||
# =============================================================================
|
||
# Stellt ein Datenbank-Backup wieder her
|
||
#
|
||
# Verwendung:
|
||
# ./restore-backup.sh [BACKUP_FILE]
|
||
# ./restore-backup.sh # Zeigt Liste der verfügbaren Backups
|
||
# ./restore-backup.sh timeclock_db_20251018_020000.sql.gz
|
||
#
|
||
# WARNUNG: Dies überschreibt die aktuelle Datenbank!
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# Farben
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
# Konfiguration
|
||
BACKUP_DIR="/var/backups/timeclock"
|
||
PROJECT_DIR="/var/www/timeclock"
|
||
ENV_FILE="$PROJECT_DIR/backend/.env"
|
||
|
||
# Logging
|
||
log() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
# =============================================================================
|
||
# Voraussetzungen prüfen
|
||
# =============================================================================
|
||
|
||
if [ ! -f "$ENV_FILE" ]; then
|
||
log_error ".env Datei nicht gefunden: $ENV_FILE"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -d "$BACKUP_DIR" ]; then
|
||
log_error "Backup-Verzeichnis nicht gefunden: $BACKUP_DIR"
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Datenbank-Credentials aus .env lesen
|
||
# =============================================================================
|
||
|
||
get_env_value() {
|
||
grep "^$1=" "$ENV_FILE" | cut -d '=' -f2- | tr -d '"' | tr -d "'"
|
||
}
|
||
|
||
DB_HOST=$(get_env_value "DB_HOST")
|
||
DB_PORT=$(get_env_value "DB_PORT")
|
||
DB_NAME=$(get_env_value "DB_NAME")
|
||
DB_USER=$(get_env_value "DB_USER")
|
||
DB_PASSWORD=$(get_env_value "DB_PASSWORD")
|
||
|
||
# Defaults
|
||
DB_HOST=${DB_HOST:-localhost}
|
||
DB_PORT=${DB_PORT:-3306}
|
||
|
||
if [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
|
||
log_error "Datenbank-Credentials unvollständig in .env"
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Verfügbare Backups auflisten
|
||
# =============================================================================
|
||
|
||
list_backups() {
|
||
echo ""
|
||
log "Verfügbare Backups in $BACKUP_DIR:"
|
||
echo ""
|
||
|
||
BACKUPS=($(ls -t "$BACKUP_DIR"/timeclock_db_*.sql.gz 2>/dev/null))
|
||
|
||
if [ ${#BACKUPS[@]} -eq 0 ]; then
|
||
log_warning "Keine Backups gefunden!"
|
||
exit 1
|
||
fi
|
||
|
||
for i in "${!BACKUPS[@]}"; do
|
||
BACKUP="${BACKUPS[$i]}"
|
||
FILENAME=$(basename "$BACKUP")
|
||
SIZE=$(du -h "$BACKUP" | cut -f1)
|
||
DATE=$(stat -c %y "$BACKUP" | cut -d'.' -f1)
|
||
|
||
printf "%2d) %-50s %6s %s\n" $((i+1)) "$FILENAME" "$SIZE" "$DATE"
|
||
done
|
||
|
||
echo ""
|
||
}
|
||
|
||
# =============================================================================
|
||
# Backup-Datei auswählen
|
||
# =============================================================================
|
||
|
||
select_backup() {
|
||
list_backups
|
||
|
||
read -p "Wähle ein Backup (Nummer) oder 'q' zum Beenden: " selection
|
||
|
||
if [ "$selection" = "q" ] || [ "$selection" = "Q" ]; then
|
||
log "Abgebrochen."
|
||
exit 0
|
||
fi
|
||
|
||
if ! [[ "$selection" =~ ^[0-9]+$ ]]; then
|
||
log_error "Ungültige Eingabe!"
|
||
exit 1
|
||
fi
|
||
|
||
BACKUPS=($(ls -t "$BACKUP_DIR"/timeclock_db_*.sql.gz 2>/dev/null))
|
||
INDEX=$((selection - 1))
|
||
|
||
if [ $INDEX -lt 0 ] || [ $INDEX -ge ${#BACKUPS[@]} ]; then
|
||
log_error "Ungültige Auswahl!"
|
||
exit 1
|
||
fi
|
||
|
||
BACKUP_FILE="${BACKUPS[$INDEX]}"
|
||
}
|
||
|
||
# =============================================================================
|
||
# Restore durchführen
|
||
# =============================================================================
|
||
|
||
restore_backup() {
|
||
local backup_file=$1
|
||
|
||
if [ ! -f "$backup_file" ]; then
|
||
log_error "Backup-Datei nicht gefunden: $backup_file"
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
log_warning "WARNUNG: Dies wird die aktuelle Datenbank '$DB_NAME' überschreiben!"
|
||
log "Backup-Datei: $(basename $backup_file)"
|
||
log "Größe: $(du -h $backup_file | cut -f1)"
|
||
log "Datenbank: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
|
||
echo ""
|
||
|
||
read -p "Fortfahren? (yes/no): " confirm
|
||
|
||
if [ "$confirm" != "yes" ]; then
|
||
log "Abgebrochen."
|
||
exit 0
|
||
fi
|
||
|
||
# Erstelle Backup der aktuellen Datenbank (Sicherheitskopie)
|
||
log "Erstelle Sicherheitskopie der aktuellen Datenbank..."
|
||
SAFETY_BACKUP="$BACKUP_DIR/timeclock_db_pre_restore_$(date +%Y%m%d_%H%M%S).sql.gz"
|
||
|
||
if mysqldump \
|
||
--host="$DB_HOST" \
|
||
--port="$DB_PORT" \
|
||
--user="$DB_USER" \
|
||
--password="$DB_PASSWORD" \
|
||
--single-transaction \
|
||
--databases "$DB_NAME" \
|
||
| gzip > "$SAFETY_BACKUP"; then
|
||
log_success "Sicherheitskopie erstellt: $(basename $SAFETY_BACKUP)"
|
||
else
|
||
log_error "Sicherheitskopie fehlgeschlagen!"
|
||
read -p "Trotzdem fortfahren? (yes/no): " force
|
||
if [ "$force" != "yes" ]; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Restore durchführen
|
||
log "Stelle Backup wieder her..."
|
||
|
||
# Datenbank leeren (optional, aber empfohlen)
|
||
log "Leere Datenbank..."
|
||
mysql \
|
||
--host="$DB_HOST" \
|
||
--port="$DB_PORT" \
|
||
--user="$DB_USER" \
|
||
--password="$DB_PASSWORD" \
|
||
-e "DROP DATABASE IF EXISTS $DB_NAME; CREATE DATABASE $DB_NAME;"
|
||
|
||
# Backup einspielen
|
||
if gunzip < "$backup_file" | mysql \
|
||
--host="$DB_HOST" \
|
||
--port="$DB_PORT" \
|
||
--user="$DB_USER" \
|
||
--password="$DB_PASSWORD"; then
|
||
|
||
log_success "Backup erfolgreich wiederhergestellt!"
|
||
|
||
# Datenbank-Statistiken
|
||
TABLE_COUNT=$(mysql \
|
||
--host="$DB_HOST" \
|
||
--port="$DB_PORT" \
|
||
--user="$DB_USER" \
|
||
--password="$DB_PASSWORD" \
|
||
-e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';" -s -N)
|
||
|
||
log "Datenbank-Statistik:"
|
||
log " 📊 Tabellen: $TABLE_COUNT"
|
||
|
||
# Optional: Service neu starten
|
||
log_warning "Möchtest du den Backend-Service neu starten?"
|
||
read -p "Service neu starten? (y/n): " restart
|
||
|
||
if [ "$restart" = "y" ] || [ "$restart" = "Y" ]; then
|
||
if command -v pm2 &> /dev/null && pm2 list | grep -q "timeclock-backend"; then
|
||
pm2 restart timeclock-backend
|
||
log_success "PM2-Service neu gestartet"
|
||
elif systemctl is-active --quiet timeclock; then
|
||
sudo systemctl restart timeclock
|
||
log_success "systemd-Service neu gestartet"
|
||
else
|
||
log_warning "Service-Verwaltung nicht gefunden - bitte manuell neu starten"
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
log_success "Restore abgeschlossen!"
|
||
log "Sicherheitskopie der alten Datenbank: $(basename $SAFETY_BACKUP)"
|
||
|
||
else
|
||
log_error "Restore fehlgeschlagen!"
|
||
log "Die Sicherheitskopie befindet sich unter: $(basename $SAFETY_BACKUP)"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# =============================================================================
|
||
# Hauptprogramm
|
||
# =============================================================================
|
||
|
||
echo ""
|
||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BLUE} TimeClock v3 - Backup Restore${NC}"
|
||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
# Wenn Backup-Datei als Argument übergeben wurde
|
||
if [ $# -eq 1 ]; then
|
||
BACKUP_FILE="$1"
|
||
|
||
# Wenn nur Dateiname (ohne Pfad) übergeben wurde
|
||
if [ ! -f "$BACKUP_FILE" ]; then
|
||
BACKUP_FILE="$BACKUP_DIR/$1"
|
||
fi
|
||
|
||
restore_backup "$BACKUP_FILE"
|
||
else
|
||
# Interaktive Auswahl
|
||
select_backup
|
||
restore_backup "$BACKUP_FILE"
|
||
fi
|
||
|
||
exit 0
|
||
|