diff --git a/.gitignore b/.gitignore index aceba2d..4fdaf78 100644 --- a/.gitignore +++ b/.gitignore @@ -185,5 +185,4 @@ app/staticfiles app/media/reports/csv/* TODO.md -pre_migration_backup_*.sql -fbf-backup.sql +*.sql diff --git a/databaseBackup/BACKUP_README.md b/databaseBackup/BACKUP_README.md new file mode 100644 index 0000000..7785b6f --- /dev/null +++ b/databaseBackup/BACKUP_README.md @@ -0,0 +1,148 @@ +# Database Backup Script + +Das `create_backup.sh` Script erstellt automatisierte Backups der aktuellen Django-Datenbank mit organisierter Archivierung. + +## 📋 Übersicht + +Das Script erstellt: +1. **Archiviertes Backup**: `JAHR/MONAT/NAME_TIMESTAMP.sql` (permanent) +2. **Standard-Backup**: `NAME.sql` (überschreibbar für Migration) + +## 🚀 Verwendung + +### Standard-Backup erstellen +```bash +cd databaseBackup +./create_backup.sh +``` +Erstellt: `fbf-backup.sql` und `2025/07/fbf-backup_TIMESTAMP.sql` + +### Backup mit eigenem Namen +```bash +./create_backup.sh production-backup +``` +Erstellt: `production-backup.sql` und `2025/07/production-backup_TIMESTAMP.sql` + +### Hilfe anzeigen +```bash +./create_backup.sh --help +``` + +## 📁 Verzeichnisstruktur + +``` +databaseBackup/ +├── create_backup.sh # Backup-Script +├── migrate_live_data.sh # Migration-Script +├── fbf-backup.sql # Standard-Backup (überschreibbar) +├── test-backup.sql # Weiteres Standard-Backup +└── 2025/ # Archiv-Verzeichnis + └── 07/ # Monat + ├── fbf-backup_20250707_231754.sql + └── test-backup_20250707_231826.sql +``` + +## ✅ Features + +- **🔧 Automatische Konfiguration**: Liest .env Datei oder verwendet Standard-Werte +- **📊 Datenbank-Statistiken**: Zeigt Datensatz-Anzahl pro Tabelle +- **📦 Organisierte Archivierung**: Jahr/Monat-Struktur +- **🔄 Kompatibilität**: Funktioniert mit migrate_live_data.sh +- **⚡ Docker-Integration**: Nahtlose Container-Verwaltung +- **📝 Ausführliche Logs**: Farb-kodierte Fortschrittsanzeige + +## 📊 Backup-Informationen + +Das Script zeigt automatisch: +- Dateigröße des Backups +- Anzahl der Zeilen +- Datensatz-Statistiken pro Tabelle +- Erstellungszeit + +## 🔧 Konfiguration + +### Automatische .env Erkennung +Das Script liest automatisch die `.env` Datei aus dem übergeordneten Verzeichnis: +```bash +DB_HOST='db' +DB_NAME='db_fbf' +DB_USER='fbf' +DB_PASSWORD='superSecret' +``` + +### Standard-Werte (wenn .env nicht vorhanden) +```bash +DB_HOST=localhost +DB_NAME=fbf +DB_USER=fbf +DB_PASSWORD=fbfpassword +DB_PORT=5432 +``` + +## 🔄 Integration mit Migration + +Die erstellten Backups sind vollständig kompatibel mit dem Migration-Script: + +```bash +# Backup erstellen +./create_backup.sh + +# Backup wiederherstellen +./migrate_live_data.sh fbf-backup.sql +``` + +## 📋 Voraussetzungen + +- Docker und Docker Compose installiert +- Laufende Container (wird automatisch geprüft) +- Schreibberechtigung im databaseBackup Verzeichnis + +## 🛠️ Problembehandlung + +### Container nicht bereit +```bash +cd .. +docker-compose up -d +cd databaseBackup +./create_backup.sh +``` + +### Backup-Verzeichnis anzeigen +```bash +ls -la 2025/07/ +``` + +### Backup-Inhalt prüfen +```bash +head -20 fbf-backup.sql +``` + +### Manual Database Access +```bash +cd .. +docker-compose exec db psql -U fbf -d db_fbf +``` + +## 📈 Backup-Workflow + +1. **Script starten** → Automatische Konfiguration +2. **Container prüfen** → Status-Validierung +3. **Verzeichnis erstellen** → Jahr/Monat-Struktur +4. **Datenbank exportieren** → pg_dump via Docker +5. **Dateien erstellen** → Archiv + Standard-Kopie +6. **Statistiken anzeigen** → Daten-Übersicht +7. **Zusammenfassung** → Erfolgs-Bestätigung + +## 💡 Tipps + +- **Regelmäßige Backups**: Fügen Sie das Script zu Cron-Jobs hinzu +- **Archiv-Management**: Alte Backups regelmäßig bereinigen +- **Standard-Backups**: Ideal für schnelle Migrations-Tests +- **Archiv-Backups**: Permanente Sicherung mit Zeitstempel + +## 🎯 Nächste Schritte + +Nach dem Backup können Sie: +- Das Backup mit `migrate_live_data.sh` testen +- Die Datenbank mit anderen Daten füllen +- Bei Problemen schnell zum Backup zurückkehren diff --git a/databaseBackup/create_backup.sh b/databaseBackup/create_backup.sh new file mode 100755 index 0000000..a4b9b3f --- /dev/null +++ b/databaseBackup/create_backup.sh @@ -0,0 +1,301 @@ +#!/bin/bash + +# Django FBF Database Backup Script +# Erstellt ein Backup der aktuellen Django-Datenbank +# +# Verwendung: ./create_backup.sh [output-name] +# Standard: ./create_backup.sh (erstellt fbf-backup.sql) + +set -e # Stoppe bei Fehlern + +# Farben für Output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Logging Funktionen +log_info() { + 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}" +} + +# Fortschrittsanzeige +show_progress() { + echo -e "${BLUE}🔄 $1${NC}" +} + +# Banner +print_banner() { + echo -e "${BLUE}" + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Django FBF Database Backup ║" + echo "║ Version 1.0 ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo -e "${NC}" +} + +# Datenbank-Konfiguration (aus .env oder Standard-Werte) +get_db_config() { + # Versuche .env Datei zu laden (sicher) + if [ -f "../.env" ]; then + while IFS='=' read -r key value; do + # Überspringe Kommentare und leere Zeilen + if [[ ! "$key" =~ ^#.* ]] && [[ -n "$key" ]]; then + # Entferne Anführungszeichen von value + value="${value%\'}" + value="${value#\'}" + value="${value%\"}" + value="${value#\"}" + export "$key=$value" + fi + done < <(grep -v '^#' ../.env | grep -v '^$' | grep '=') + fi + + # Standard-Werte setzen falls nicht definiert + DB_NAME="${DB_NAME:-fbf}" + DB_USER="${DB_USER:-fbf}" + DB_PASSWORD="${DB_PASSWORD:-fbfpassword}" + DB_HOST="${DB_HOST:-localhost}" + DB_PORT="${DB_PORT:-5432}" + + log_info "Datenbank-Konfiguration:" + echo " Host: $DB_HOST:$DB_PORT" + echo " Datenbank: $DB_NAME" + echo " Benutzer: $DB_USER" +} + +# Überprüfe Voraussetzungen +check_prerequisites() { + log_info "Überprüfe Voraussetzungen..." + + # Docker und Docker Compose prüfen + if ! command -v docker &> /dev/null; then + log_error "Docker ist nicht installiert oder nicht im PATH" + exit 1 + fi + + if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then + log_error "Docker Compose ist nicht installiert oder nicht im PATH" + exit 1 + fi + + # docker-compose.yaml prüfen + if [ ! -f "../docker-compose.yaml" ]; then + log_error "docker-compose.yaml nicht im übergeordneten Verzeichnis gefunden" + exit 1 + fi + + log_success "Alle Voraussetzungen erfüllt" +} + +# Container Status prüfen +check_containers() { + log_info "Überprüfe Container Status..." + + cd .. + + if ! docker-compose ps | grep -q "django_fbf_db_1.*Up"; then + log_error "Datenbank-Container läuft nicht. Bitte starte zuerst die Container:" + echo " cd .." + echo " docker-compose up -d" + exit 1 + fi + + # Teste Datenbankverbindung + if ! docker-compose exec -T db pg_isready -U "$DB_USER" -d "$DB_NAME" &>/dev/null; then + log_error "Datenbank ist nicht bereit oder erreichbar" + exit 1 + fi + + cd databaseBackup + log_success "Container sind bereit und Datenbank ist erreichbar" +} + +# Erstelle Backup-Verzeichnisstruktur +create_backup_structure() { + local current_year=$(date +"%Y") + local current_month=$(date +"%m") + local backup_dir="${current_year}/${current_month}" + + mkdir -p "$backup_dir" + + echo "$backup_dir" +} + +# Datenbank-Backup erstellen +create_database_backup() { + local output_name="${1:-fbf-backup.sql}" + local backup_dir="$2" + local timestamp=$(date +"%Y%m%d_%H%M%S") + + # Entferne .sql Endung falls vorhanden und füge Timestamp hinzu + local base_name="${output_name%.sql}" + local timestamped_name="${base_name}_${timestamp}.sql" + local backup_path="${backup_dir}/${timestamped_name}" + local full_backup_path="$(pwd)/${backup_path}" + + # Erstelle Backup mit pg_dump + cd .. + if docker-compose exec -T db pg_dump -U "$DB_USER" -d "$DB_NAME" --verbose > "$full_backup_path" 2>/dev/null; then + cd databaseBackup + else + cd databaseBackup + log_error "Fehler beim Erstellen des Backups" + exit 1 + fi + + # Erstelle zusätzlich eine Kopie mit Standard-Namen + local standard_path="${base_name}.sql" + cp "$backup_path" "$standard_path" 2>/dev/null || true + + echo "$backup_path" +} + +# Backup-Informationen anzeigen +show_backup_info() { + local backup_path="$1" + local standard_path="$2" + + # Datei-Größe ermitteln + local file_size=$(stat -f%z "$backup_path" 2>/dev/null || stat -c%s "$backup_path" 2>/dev/null || echo "0") + local size_display="" + if command -v numfmt >/dev/null 2>&1; then + size_display=" ($(numfmt --to=iec $file_size))" + elif [ "$file_size" -gt 0 ]; then + size_display=" (${file_size} bytes)" + fi + + # Anzahl Zeilen zählen + local line_count=$(wc -l < "$backup_path" | tr -d ' ') + + echo "" + log_success "Backup-Informationen:" + echo " 📁 Archiviert: $backup_path$size_display" + echo " 📄 Standard: $standard_path" + echo " 📊 Zeilen: $line_count" + echo " 🕒 Erstellt: $(date)" +} + +# Datenbank-Statistiken anzeigen +show_database_stats() { + log_info "Datenbank-Statistiken:" + + cd .. + + # Zähle Datensätze in wichtigen Tabellen (ohne spezifische Zahlen zu zeigen) + local tables=("auth_user" "bird_bird" "bird_fallenbird" "contact_contact") + local total_records=0 + + for table in "${tables[@]}"; do + local count=$(docker-compose exec -T db psql -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM $table;" 2>/dev/null | tr -d ' \n\r' || echo "0") + echo " 📦 $table: $count Datensätze" + if [[ "$count" =~ ^[0-9]+$ ]]; then + total_records=$((total_records + count)) + fi + done + + echo " 📊 Gesamt (Haupttabellen): $total_records Datensätze" + + cd databaseBackup +} + +# Backup Zusammenfassung +show_backup_summary() { + local backup_path="$1" + local standard_path="$2" + + echo "" + echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗" + echo -e "║ Backup erfolgreich erstellt! ║" + echo -e "╚══════════════════════════════════════════════════════════════╝${NC}" + echo "" + + echo -e "${BLUE}📋 Backup-Dateien:${NC}" + echo " 🗄️ Archiv: $backup_path" + echo " 📄 Standard: $standard_path" + echo "" + + echo -e "${BLUE}📝 Nützliche Befehle:${NC}" + echo " ls -la $(dirname "$backup_path") # Backup-Verzeichnis anzeigen" + echo " ./migrate_live_data.sh $standard_path # Backup wiederherstellen" + echo " head -20 $standard_path # Backup-Inhalt prüfen" + echo "" + + echo -e "${YELLOW}💡 Hinweis: Die Standard-Datei '$standard_path' wird bei jedem Backup überschrieben.${NC}" + echo -e "${YELLOW} Das archivierte Backup '$backup_path' bleibt bestehen.${NC}" +} + +# Hauptfunktion +main() { + local output_name="${1:-fbf-backup}" + + print_banner + + get_db_config + check_prerequisites + check_containers + + log_info "Erstelle Backup-Verzeichnisstruktur..." + local backup_dir=$(create_backup_structure) + log_success "Verzeichnisstruktur erstellt: $backup_dir" + + log_info "Erstelle Datenbank-Backup..." + show_progress "Exportiere Datenbank $DB_NAME..." + local backup_path=$(create_database_backup "$output_name" "$backup_dir") + local standard_path="${output_name%.sql}.sql" + log_success "Backup erfolgreich erstellt: $backup_path" + log_info "Standard-Kopie erstellt: $standard_path" + + show_database_stats + show_backup_info "$backup_path" "$standard_path" + show_backup_summary "$backup_path" "$standard_path" +} + +# Hilfe anzeigen +show_help() { + echo "Django FBF Database Backup Script" + echo "" + echo "Verwendung: $0 [OPTIONEN] [BACKUP-NAME]" + echo "" + echo "OPTIONEN:" + echo " -h, --help Zeige diese Hilfe an" + echo "" + echo "BACKUP-NAME:" + echo " Name der Backup-Datei (Standard: fbf-backup)" + echo " Die .sql Endung wird automatisch hinzugefügt" + echo "" + echo "AUSGABE:" + echo " Erstellt zwei Dateien:" + echo " 1. JAHR/MONAT/NAME_TIMESTAMP.sql (archiviert)" + echo " 2. NAME.sql (überschreibbar für Migration)" + echo "" + echo "Beispiele:" + echo " $0 # Erstellt fbf-backup.sql" + echo " $0 production-backup # Erstellt production-backup.sql" + echo " $0 test-data # Erstellt test-data.sql" + echo "" +} + +# Kommandozeilen-Parameter verarbeiten +case "${1:-}" in + -h|--help) + show_help + exit 0 + ;; + *) + main "$@" + ;; +esac