#!/bin/bash # Advanced Database Backup Script for CKB Docker # =============================================== # Configuration CONTAINER_NAME="ckb-mysql-dev" DB_NAME="ckb_db" DB_USER="root" DB_PASSWORD="root" BACKUP_DIR="./backups" DATE=$(date +%Y%m%d_%H%M%S) RETENTION_DAYS=30 # Keep backups for 30 days # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Functions print_header() { echo -e "${BLUE}================================================${NC}" echo -e "${BLUE} CKB Database Advanced Backup Tool${NC}" echo -e "${BLUE}================================================${NC}" } print_success() { echo -e "${GREEN}✅ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } check_container() { if ! docker ps | grep -q $CONTAINER_NAME; then print_error "Container $CONTAINER_NAME is not running!" exit 1 fi print_success "Container $CONTAINER_NAME is running" } create_backup_dir() { mkdir -p $BACKUP_DIR print_info "Backup directory: $BACKUP_DIR" } cleanup_old_backups() { print_info "Cleaning up backups older than $RETENTION_DAYS days..." # Find and delete old backup files old_files=$(find $BACKUP_DIR -name "ckb_backup_*.sql*" -mtime +$RETENTION_DAYS 2>/dev/null) if [[ -z "$old_files" ]]; then print_info "No old backup files found" else echo "$old_files" | while read file; do rm -f "$file" print_warning "Deleted old backup: $(basename "$file")" done fi } backup_full() { local backup_file="$BACKUP_DIR/ckb_backup_${DATE}.sql" print_info "Creating full backup..." if docker exec $CONTAINER_NAME mysqldump -u $DB_USER -p$DB_PASSWORD \ --single-transaction \ --routines \ --triggers \ --add-drop-table \ $DB_NAME > "$backup_file"; then print_success "Full backup created: $backup_file" return 0 else print_error "Full backup failed!" return 1 fi } backup_structure_only() { local backup_file="$BACKUP_DIR/ckb_structure_${DATE}.sql" print_info "Creating structure-only backup..." if docker exec $CONTAINER_NAME mysqldump -u $DB_USER -p$DB_PASSWORD \ --no-data \ --routines \ --triggers \ $DB_NAME > "$backup_file"; then print_success "Structure backup created: $backup_file" return 0 else print_error "Structure backup failed!" return 1 fi } backup_data_only() { local backup_file="$BACKUP_DIR/ckb_data_${DATE}.sql" print_info "Creating data-only backup..." if docker exec $CONTAINER_NAME mysqldump -u $DB_USER -p$DB_PASSWORD \ --no-create-info \ --single-transaction \ $DB_NAME > "$backup_file"; then print_success "Data backup created: $backup_file" return 0 else print_error "Data backup failed!" return 1 fi } compress_backup() { local file="$1" if [[ -f "$file" ]]; then print_info "Compressing backup..." if gzip "$file"; then print_success "Backup compressed: $file.gz" # Show compression ratio original_size=$(stat -c%s "$file" 2>/dev/null || echo "0") compressed_size=$(stat -c%s "$file.gz" 2>/dev/null || echo "0") if [[ $original_size -gt 0 ]]; then ratio=$(echo "scale=1; (1 - $compressed_size/$original_size) * 100" | bc -l 2>/dev/null || echo "0") print_info "Compression ratio: ${ratio}%" fi else print_error "Compression failed!" fi fi } show_backup_stats() { print_info "Backup Statistics:" echo "----------------------------------------" # Count backup files total_backups=$(ls -1 $BACKUP_DIR/ckb_backup_*.sql* 2>/dev/null | wc -l) total_size=$(du -sh $BACKUP_DIR 2>/dev/null | cut -f1) echo "Total backups: $total_backups" echo "Total size: $total_size" echo "Newest backup: $(ls -1t $BACKUP_DIR/ckb_backup_*.sql* 2>/dev/null | head -1 | xargs basename 2>/dev/null || echo "None")" echo "Oldest backup: $(ls -1tr $BACKUP_DIR/ckb_backup_*.sql* 2>/dev/null | head -1 | xargs basename 2>/dev/null || echo "None")" } # Main Script print_header echo "Backup Options:" echo "1. Full backup (structure + data)" echo "2. Structure only backup" echo "3. Data only backup" echo "4. All backup types" echo "5. Show backup statistics" echo "6. Cleanup old backups" echo "7. Exit" echo read -p "Choose option (1-7): " -n 1 -r option echo case $option in 1) check_container create_backup_dir if backup_full; then backup_file="$BACKUP_DIR/ckb_backup_${DATE}.sql" read -p "Compress backup? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then compress_backup "$backup_file" fi cleanup_old_backups show_backup_stats fi ;; 2) check_container create_backup_dir if backup_structure_only; then backup_file="$BACKUP_DIR/ckb_structure_${DATE}.sql" read -p "Compress backup? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then compress_backup "$backup_file" fi fi ;; 3) check_container create_backup_dir if backup_data_only; then backup_file="$BACKUP_DIR/ckb_data_${DATE}.sql" read -p "Compress backup? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then compress_backup "$backup_file" fi fi ;; 4) check_container create_backup_dir print_info "Creating all backup types..." backup_full && compress_backup "$BACKUP_DIR/ckb_backup_${DATE}.sql" backup_structure_only && compress_backup "$BACKUP_DIR/ckb_structure_${DATE}.sql" backup_data_only && compress_backup "$BACKUP_DIR/ckb_data_${DATE}.sql" cleanup_old_backups show_backup_stats ;; 5) create_backup_dir show_backup_stats ;; 6) create_backup_dir cleanup_old_backups show_backup_stats ;; 7) print_info "Goodbye!" exit 0 ;; *) print_error "Invalid option!" exit 1 ;; esac print_success "Backup process completed!"