- 创建完整的迁移框架 (pkg/migration/) - 版本管理系统,时间戳版本号 (YYYYMMDD_HHMMSS) - 事务安全的上下迁移机制 (Up/Down) - 迁移状态跟踪和记录 (migration_records 表) - 命令行迁移工具 (cmd/migrate/main.go) - 生产环境迁移脚本 (scripts/production-migrate.sh) - 生产环境初始化脚本 (scripts/init-production-db.sh) - 迁移测试脚本 (scripts/test-migration.sh) - Makefile 集成 (migrate-up, migrate-down, migrate-status) - 5个预定义迁移 (基础表、默认数据、元数据、收藏、用户资料) - 自动备份机制、预览模式、详细日志 - 完整文档 (docs/DATABASE_MIGRATION.md) 任务13完成,项目完成率达到42.5%
392 lines
9.4 KiB
Bash
Executable File
392 lines
9.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# 生产环境数据库初始化脚本
|
|
# 用于全新的生产环境部署
|
|
|
|
set -e
|
|
|
|
# 默认配置
|
|
CONFIG_FILE="etc/photographyapi-api.yaml"
|
|
BACKUP_DIR="data/backups"
|
|
LOG_FILE="init.log"
|
|
|
|
# 颜色定义
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# 日志函数
|
|
log() {
|
|
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
# 显示横幅
|
|
show_banner() {
|
|
cat << 'EOF'
|
|
____ __ __ __
|
|
/ __ \/ /_ ____ / /_____ ____ __________ _____/ /_
|
|
/ /_/ / __ \/ __ \/ __/ __ \/ __ \/ ___/ __ \/ ___/ __ \
|
|
/ ____/ / / / /_/ / /_/ /_/ / /_/ / / / /_/ / /__/ / / /
|
|
/_/ /_/ /_/\____/\__/\____/\__, /_/ \__,_/\___/_/ /_/
|
|
/____/
|
|
|
|
Production Database Initialization Script
|
|
=========================================
|
|
EOF
|
|
}
|
|
|
|
# 检查环境
|
|
check_environment() {
|
|
log "检查生产环境..."
|
|
|
|
# 检查是否为 root 用户(生产环境建议)
|
|
if [[ $EUID -eq 0 ]]; then
|
|
warning "正在以 root 用户运行"
|
|
fi
|
|
|
|
# 检查Go环境
|
|
if ! command -v go &> /dev/null; then
|
|
error "Go 未安装"
|
|
exit 1
|
|
fi
|
|
|
|
local go_version=$(go version | cut -d' ' -f3)
|
|
log "Go 版本: $go_version"
|
|
|
|
# 检查配置文件
|
|
if [[ ! -f "$CONFIG_FILE" ]]; then
|
|
error "配置文件不存在: $CONFIG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
success "环境检查通过"
|
|
}
|
|
|
|
# 创建目录结构
|
|
create_directories() {
|
|
log "创建目录结构..."
|
|
|
|
local dirs=(
|
|
"data"
|
|
"data/backups"
|
|
"uploads"
|
|
"uploads/photos"
|
|
"uploads/avatars"
|
|
"uploads/thumbnails"
|
|
"logs"
|
|
"bin"
|
|
)
|
|
|
|
for dir in "${dirs[@]}"; do
|
|
if [[ ! -d "$dir" ]]; then
|
|
mkdir -p "$dir"
|
|
log "创建目录: $dir"
|
|
else
|
|
log "目录已存在: $dir"
|
|
fi
|
|
done
|
|
|
|
# 设置权限
|
|
chmod 755 data uploads logs bin
|
|
chmod 700 data/backups # 备份目录更严格的权限
|
|
|
|
success "目录结构创建完成"
|
|
}
|
|
|
|
# 检查数据库状态
|
|
check_database_status() {
|
|
log "检查数据库状态..."
|
|
|
|
if [[ -f "data/photography.db" ]]; then
|
|
warning "数据库文件已存在: data/photography.db"
|
|
local db_size=$(du -h "data/photography.db" | cut -f1)
|
|
log "数据库大小: $db_size"
|
|
|
|
echo -n "数据库已存在,是否继续初始化?这将覆盖现有数据 (y/N): "
|
|
read -r confirm
|
|
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
|
log "用户取消初始化"
|
|
exit 0
|
|
fi
|
|
|
|
# 备份现有数据库
|
|
local backup_name="photography_pre_init_$(date +%Y%m%d_%H%M%S).db"
|
|
cp "data/photography.db" "data/backups/$backup_name"
|
|
log "现有数据库已备份为: $backup_name"
|
|
else
|
|
log "数据库文件不存在,将创建新数据库"
|
|
fi
|
|
}
|
|
|
|
# 初始化数据库
|
|
initialize_database() {
|
|
log "初始化数据库..."
|
|
|
|
# 删除现有数据库(如果存在)
|
|
if [[ -f "data/photography.db" ]]; then
|
|
rm -f "data/photography.db"
|
|
log "删除现有数据库文件"
|
|
fi
|
|
|
|
# 运行迁移
|
|
log "执行数据库迁移..."
|
|
if go run cmd/migrate/main.go -f "$CONFIG_FILE" -c up; then
|
|
success "数据库迁移完成"
|
|
else
|
|
error "数据库迁移失败"
|
|
exit 1
|
|
fi
|
|
|
|
# 验证数据库
|
|
if [[ -f "data/photography.db" ]]; then
|
|
success "数据库创建成功"
|
|
local db_size=$(du -h "data/photography.db" | cut -f1)
|
|
log "数据库大小: $db_size"
|
|
else
|
|
error "数据库创建失败"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 验证数据库结构
|
|
verify_database() {
|
|
log "验证数据库结构..."
|
|
|
|
# 检查迁移状态
|
|
log "检查迁移状态:"
|
|
go run cmd/migrate/main.go -f "$CONFIG_FILE" -c status
|
|
|
|
# 检查表是否存在
|
|
local tables=("user" "category" "photo" "schema_migrations")
|
|
|
|
for table in "${tables[@]}"; do
|
|
if sqlite3 "data/photography.db" ".tables" | grep -q "$table"; then
|
|
success "表 $table 存在"
|
|
else
|
|
error "表 $table 不存在"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# 检查默认数据
|
|
local user_count=$(sqlite3 "data/photography.db" "SELECT COUNT(*) FROM user;")
|
|
local category_count=$(sqlite3 "data/photography.db" "SELECT COUNT(*) FROM category;")
|
|
|
|
log "默认用户数量: $user_count"
|
|
log "默认分类数量: $category_count"
|
|
|
|
if [[ "$user_count" -gt 0 && "$category_count" -gt 0 ]]; then
|
|
success "默认数据初始化成功"
|
|
else
|
|
warning "默认数据可能未正确初始化"
|
|
fi
|
|
}
|
|
|
|
# 创建初始备份
|
|
create_initial_backup() {
|
|
log "创建初始备份..."
|
|
|
|
local backup_name="photography_initial_$(date +%Y%m%d_%H%M%S).db"
|
|
local backup_path="data/backups/$backup_name"
|
|
|
|
cp "data/photography.db" "$backup_path"
|
|
success "初始备份创建成功: $backup_name"
|
|
|
|
# 记录初始备份
|
|
echo "$backup_path" > "data/.initial_backup"
|
|
}
|
|
|
|
# 生成配置摘要
|
|
generate_config_summary() {
|
|
log "生成配置摘要..."
|
|
|
|
cat > "DEPLOYMENT_INFO.md" << EOF
|
|
# Photography Backend Deployment Information
|
|
|
|
## 部署时间
|
|
- 初始化时间: $(date '+%Y-%m-%d %H:%M:%S %Z')
|
|
- 操作系统: $(uname -s) $(uname -r)
|
|
- 主机名: $(hostname)
|
|
|
|
## 数据库信息
|
|
- 数据库类型: SQLite
|
|
- 数据库文件: data/photography.db
|
|
- 初始备份: $(cat data/.initial_backup 2>/dev/null || echo "未找到")
|
|
|
|
## 目录结构
|
|
\`\`\`
|
|
$(tree -d -L 2 2>/dev/null || find . -type d -maxdepth 2 | head -20)
|
|
\`\`\`
|
|
|
|
## 迁移状态
|
|
\`\`\`
|
|
$(go run cmd/migrate/main.go -f "$CONFIG_FILE" -c status 2>/dev/null || echo "无法获取迁移状态")
|
|
\`\`\`
|
|
|
|
## 下一步操作
|
|
1. 启动应用服务: \`make quick\`
|
|
2. 检查服务状态: \`make status\`
|
|
3. 查看迁移状态: \`make migrate-status\`
|
|
4. 创建备份: \`make db-backup\`
|
|
|
|
## 管理命令
|
|
- 查看帮助: \`make help\`
|
|
- 迁移数据库: \`./scripts/production-migrate.sh migrate\`
|
|
- 回滚迁移: \`./scripts/production-migrate.sh rollback 1\`
|
|
- 系统检查: \`./scripts/production-migrate.sh check\`
|
|
|
|
## 注意事项
|
|
- 定期备份数据库
|
|
- 监控日志文件
|
|
- 更新时先测试迁移
|
|
- 保持配置文件安全
|
|
EOF
|
|
|
|
success "配置摘要已生成: DEPLOYMENT_INFO.md"
|
|
}
|
|
|
|
# 设置服务文件(可选)
|
|
setup_systemd_service() {
|
|
if [[ ! -f "/etc/systemd/system" ]]; then
|
|
log "Systemd 不可用,跳过服务配置"
|
|
return 0
|
|
fi
|
|
|
|
log "配置 Systemd 服务..."
|
|
|
|
local service_file="/etc/systemd/system/photography-api.service"
|
|
local current_dir=$(pwd)
|
|
local user=$(whoami)
|
|
|
|
cat > "$service_file" << EOF
|
|
[Unit]
|
|
Description=Photography API Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=$user
|
|
WorkingDirectory=$current_dir
|
|
ExecStart=$current_dir/bin/photography-api -f $current_dir/$CONFIG_FILE
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
# 环境变量
|
|
Environment=GO111MODULE=on
|
|
Environment=GOPROXY=https://goproxy.cn,direct
|
|
|
|
# 日志
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
systemctl daemon-reload
|
|
success "Systemd 服务配置完成"
|
|
log "使用以下命令管理服务:"
|
|
log " sudo systemctl start photography-api"
|
|
log " sudo systemctl enable photography-api"
|
|
log " sudo systemctl status photography-api"
|
|
}
|
|
|
|
# 最终检查
|
|
final_check() {
|
|
log "执行最终检查..."
|
|
|
|
# 检查应用是否可以构建
|
|
if make build; then
|
|
success "应用构建成功"
|
|
else
|
|
error "应用构建失败"
|
|
exit 1
|
|
fi
|
|
|
|
# 检查配置是否正确
|
|
if go run cmd/api/main.go -f "$CONFIG_FILE" -test.timeout=1s 2>/dev/null; then
|
|
success "配置文件验证通过"
|
|
else
|
|
warning "配置文件可能有问题,请检查"
|
|
fi
|
|
|
|
success "最终检查完成"
|
|
}
|
|
|
|
# 显示完成信息
|
|
show_completion() {
|
|
success "数据库初始化完成!"
|
|
|
|
cat << EOF
|
|
|
|
🎉 初始化成功!
|
|
|
|
接下来的步骤:
|
|
1. 启动应用: make quick
|
|
2. 访问应用: http://localhost:8080
|
|
3. 查看状态: make status
|
|
4. 查看帮助: make help
|
|
|
|
管理脚本:
|
|
- 迁移管理: ./scripts/production-migrate.sh
|
|
- 查看部署信息: cat DEPLOYMENT_INFO.md
|
|
|
|
默认管理员账户:
|
|
- 用户名: admin
|
|
- 密码: admin123
|
|
- 邮箱: admin@example.com
|
|
|
|
⚠️ 重要提醒:
|
|
- 请立即修改默认管理员密码
|
|
- 定期备份数据库
|
|
- 监控应用日志
|
|
- 保持系统更新
|
|
|
|
📋 详细信息请查看: DEPLOYMENT_INFO.md
|
|
|
|
EOF
|
|
}
|
|
|
|
# 主函数
|
|
main() {
|
|
show_banner
|
|
|
|
log "开始生产环境数据库初始化..."
|
|
|
|
check_environment
|
|
create_directories
|
|
check_database_status
|
|
initialize_database
|
|
verify_database
|
|
create_initial_backup
|
|
generate_config_summary
|
|
final_check
|
|
|
|
# 询问是否配置 Systemd 服务
|
|
echo -n "是否配置 Systemd 服务? (y/N): "
|
|
read -r setup_service
|
|
if [[ "$setup_service" == "y" || "$setup_service" == "Y" ]]; then
|
|
setup_systemd_service
|
|
fi
|
|
|
|
show_completion
|
|
|
|
log "初始化脚本执行完成"
|
|
}
|
|
|
|
# 运行主函数
|
|
main "$@" |