#!/usr/bin/env bash # BossAi 数据库加密备份脚本 # 用法: ./backup.sh [backup_dir] [gpg_recipient] # 默认: backup_dir=./backups, gpg 不加密(无 recipient 时) # # 功能: # 1. pg_dump 导出 mcp 数据库 # 2. 可选 GPG 加密(指定 gpg_recipient 时) # 3. 滚动保留 7 天,自动清理旧备份 # 4. 记录备份日志 # # 推荐配合 crontab 每天 2 次执行: # 0 2,14 * * * cd /Users/freedak/Documents/AIDashboard/BossAi && ./backup.sh >> backups/backup.log 2>&1 set -euo pipefail BACKUP_DIR="${1:-./backups}" GPG_RECIPIENT="${2:-}" DB_NAME="${DB_NAME:-mcp}" DB_USER="${DB_USER:-postgres}" DB_HOST="${DB_HOST:-localhost}" DB_PORT="${DB_PORT:-5432}" RETENTION_DAYS=7 mkdir -p "$BACKUP_DIR" TIMESTAMP=$(date +%Y%m%d_%H%M%S) DUMP_FILE="$BACKUP_DIR/bossai_${TIMESTAMP}.sql" COMPRESSED="$DUMP_FILE.gz" echo "[$(date)] 开始备份: $DB_NAME@$DB_HOST:$DB_PORT" # 1. pg_dump 导出 if pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$DUMP_FILE"; then echo "[$(date)] 导出成功: $DUMP_FILE" else echo "[$(date)] 导出失败" >&2 exit 1 fi # 2. 压缩 gzip -f "$DUMP_FILE" echo "[$(date)] 压缩成功: $COMPRESSED" # 3. 可选 GPG 加密 if [ -n "$GPG_RECIPIENT" ]; then ENCRYPTED="$COMPRESSED.gpg" if gpg --encrypt --recipient "$GPG_RECIPIENT" --output "$ENCRYPTED" "$COMPRESSED"; then rm -f "$COMPRESSED" echo "[$(date)] 加密成功: $ENCRYPTED" FINAL_FILE="$ENCRYPTED" else echo "[$(date)] 加密失败,保留未加密文件" >&2 FINAL_FILE="$COMPRESSED" fi else FINAL_FILE="$COMPRESSED" fi # 4. 滚动清理:删除超过 RETENTION_DAYS 天的备份 DELETED=$(find "$BACKUP_DIR" -name "bossai_*.sql.gz*" -mtime +$RETENTION_DAYS -print -delete | wc -l) echo "[$(date)] 清理旧备份: 删除 ${DELETED} 个超过 ${RETENTION_DAYS} 天的文件" # 5. 恢复说明 cat < bossai_XXXXXXXX_XXXXXX.sql.gz # 解压 gunzip bossai_XXXXXXXX_XXXXXX.sql.gz # 恢复 psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME < bossai_XXXXXXXX_XXXXXX.sql EOF echo "[$(date)] 备份完成: $FINAL_FILE"