#!/bin/bash # MySQL 数据库备份脚本 # 创建日期: 2025-12-05 # 使用方法: ./backup_database.sh # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # 获取脚本所在目录 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # 备份配置 BACKUP_DIR="$SCRIPT_DIR" TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") BACKUP_FILE="backup_math_${TIMESTAMP}.sql" BACKUP_PATH="$BACKUP_DIR/$BACKUP_FILE" GZIP_BACKUP_PATH="${BACKUP_PATH}.gz" # 日志文件 LOG_FILE="$BACKUP_DIR/backup.log" # 记录日志函数 log() { local message=$1 local color=${2:-$NC} echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] ${message}${NC}" | tee -a "$LOG_FILE" } # 检查是否在正确的目录 if [ ! -f "$PROJECT_DIR/.env" ]; then log "错误: 未找到 .env 文件,请确保在正确的项目目录中执行" $RED exit 1 fi # 开始备份 log "=========================================" $GREEN log "开始 MySQL 数据库备份" $GREEN log "=========================================" $GREEN # 切换到项目目录 cd "$PROJECT_DIR" # 创建 PHP 备份脚本 PHP_SCRIPT="$BACKUP_DIR/backup_${TIMESTAMP}.php" cat > "$PHP_SCRIPT" << 'EOF' make(Illuminate\Contracts\Console\Kernel::class); $kernel->bootstrap(); use Illuminate\Support\Facades\DB; try { // 创建备份内容 $tables = DB::select('SHOW TABLES'); $dump = "-- MySQL Database Backup\n"; $dump .= "-- Generated on: " . date('Y-m-d H:i:s') . "\n"; $dump .= "-- Database: math\n"; $dump .= "-- FilamentAdmin Project Backup\n\n"; $totalTables = count($tables); $currentTable = 0; foreach ($tables as $table) { $tableName = array_values((array)$table)[0]; $currentTable++; echo "备份表 [$currentTable/$totalTables]: $tableName\n"; // 获取建表语句 $createTable = DB::select('SHOW CREATE TABLE ' . $tableName); if (isset($createTable[0])) { $dump .= "--\n-- Table structure for table `$tableName`\n--\n"; $dump .= "DROP TABLE IF EXISTS `$tableName`;\n"; $dump .= $createTable[0]->{'Create Table'} . ";\n\n"; } // 获取表数据 $dump .= "--\n-- Dumping data for table `$tableName`\n--\n"; // 分批获取数据以避免内存问题 $offset = 0; $limit = 1000; $hasData = false; do { $data = DB::table($tableName)->offset($offset)->limit($limit)->get(); foreach ($data as $row) { $hasData = true; $values = []; $columns = []; foreach ((array)$row as $key => $value) { if (is_numeric($key)) continue; // 跳过数字索引 $columns[] = "`$key`"; if ($value === null) { $values[] = 'NULL'; } elseif (is_string($value)) { // 处理特殊字符 $value = str_replace(["\n", "\r", "\t"], ["\\n", "\\r", "\\t"], $value); $values[] = "'" . addslashes($value) . "'"; } elseif (is_bool($value)) { $values[] = $value ? '1' : '0'; } elseif (is_float($value) || is_double($value)) { $values[] = sprintf('%F', $value); } else { $values[] = $value; } } $dump .= "INSERT INTO `$tableName` (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $values) . ");\n"; } $offset += $limit; } while ($data->count() == $limit); if (!$hasData) { $dump .= "-- Table is empty\n"; } $dump .= "\n"; } // 添加备份结束标记 $dump .= "--\n-- Backup completed successfully\n--\n"; // 保存备份文件 $filename = getenv('BACKUP_FILE') ?: 'backup.sql'; file_put_contents($filename, $dump); echo "\n备份完成!\n"; echo "备份文件: $filename\n"; echo "文件大小: " . number_format(filesize($filename) / 1024, 2) . " KB\n"; } catch (Exception $e) { echo "\n备份失败!\n"; echo "错误信息: " . $e->getMessage() . "\n"; exit(1); } EOF # 设置环境变量 export BACKUP_FILE="$BACKUP_PATH" # 执行备份 log "正在执行数据库备份..." $YELLOW if php "$PHP_SCRIPT" 2>&1; then # 备份成功 log "数据库备份成功完成!" $GREEN # 压缩备份文件 log "正在压缩备份文件..." $YELLOW if gzip -c "$BACKUP_PATH" > "$GZIP_BACKUP_PATH"; then log "压缩成功!" $GREEN log "压缩文件: $GZIP_BACKUP_PATH" log "原始文件: $BACKUP_PATH ($(ls -lh "$BACKUP_PATH" | awk '{print $5}'))" log "压缩文件: $(ls -lh "$GZIP_BACKUP_PATH" | awk '{print $5}')" else log "压缩失败!" $RED fi # 清理临时PHP文件 rm -f "$PHP_SCRIPT" # 显示备份文件列表 log "\n最近的备份文件:" $GREEN ls -lh "$BACKUP_DIR"/backup_math_*.sql.gz | tail -5 | awk '{print $9 " (" $5 ")"}' # 保留最近10个备份文件 log "正在清理旧备份(保留最近10个)..." $YELLOW cd "$BACKUP_DIR" ls -t backup_math_*.sql.gz | tail -n +11 | xargs -r rm ls -t backup_math_*.sql | tail -n +11 | xargs -r rm log "清理完成!" $GREEN else # 备份失败 log "数据库备份失败!" $RED rm -f "$PHP_SCRIPT" exit 1 fi log "=========================================" $GREEN log "备份脚本执行完毕" $GREEN log "=========================================" $GREEN exit 0