laobinghu 37742571ae feat: 完成项目初始化并重构部署流程
主要变更:
- 添加完整的项目结构和模块(admin、articles、comments、users、session、oauth2、email、moderation、analytics、jobs 等)
- 实现系统初始化 API(/init/status 和 /init/run)
- 重写部署流程:迁移到 package.json scripts,删除 Makefile
- 优化部署脚本:deploy.sh、healthcheck.sh、backup.sh、restore.sh、verify-env.sh
- 更新 README.md:简化文档,整合部署指南
- 优化 AGENTS.md:精简到约 150 行,包含完整的代码规范和命令速查
- 配置 Docker Compose 自动化部署(prisma migrate deploy + seed)
- 生成 OAuth2 RSA 密钥对支持
- 添加环境变量验证和数据库备份恢复功能
2026-03-28 16:53:25 +08:00

258 lines
6.7 KiB
Bash

#!/bin/bash
# ============================================
# LinkShare Blog - 环境验证脚本
# ============================================
# 用途: 在生产环境部署前验证所有必需配置
# 用法: ./scripts/verify-env.sh
set -e # 遇到错误退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查项计数
CHECKS_PASSED=0
CHECKS_FAILED=0
CHECKS_WARNING=0
# 检查函数
check_file_exists() {
local file=$1
local description=$2
if [ -f "$file" ]; then
log_info "$description: 存在 ($file)"
((CHECKS_PASSED++))
return 0
else
log_error "$description: 缺失 ($file)"
((CHECKS_FAILED++))
return 1
fi
}
check_env_var() {
local var=$1
local description=$2
local required=${3:-true}
local value=$(eval echo "\$$var")
if [ -n "$value" ] && [ "$value" != "your-secret-here" ] && [ "$value" != "change_me" ]; then
log_info "$description ($var): 已设置"
((CHECKS_PASSED++))
return 0
else
if [ "$required" = "true" ]; then
log_error "$description ($var): 未设置或为默认值"
((CHECKS_FAILED++))
return 1
else
log_warn "$description ($var): 未设置或为默认值 (可选)"
((CHECKS_WARNING++))
return 0
fi
fi
}
check_command() {
local cmd=$1
local description=$2
if command -v "$cmd" &> /dev/null; then
local version=$($cmd --version 2>&1 | head -n1)
log_info "$description: 已安装 ($version)"
((CHECKS_PASSED++))
return 0
else
log_error "$description: 未安装"
((CHECKS_FAILED++))
return 1
fi
}
check_port() {
local port=$1
local description=$2
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
log_info "$description (端口 $port): 已占用"
((CHECKS_WARNING++))
return 0
else
log_info "$description (端口 $port): 可用"
((CHECKS_PASSED++))
return 0
fi
}
check_docker() {
if docker info >/dev/null 2>&1; then
log_info "Docker: 运行中"
((CHECKS_PASSED++))
return 0
else
log_error "Docker: 未运行或无权限"
((CHECKS_FAILED++))
return 1
fi
}
# ============================================
# 开始检查
# ============================================
echo "=========================================="
echo "LinkShare Blog 环境验证"
echo "=========================================="
echo ""
# 1. 检查必需文件
log_info "检查文件..."
check_file_exists ".env" "环境变量文件"
check_file_exists "docker-compose.yml" "Docker Compose 配置"
check_file_exists "Dockerfile.api" "Dockerfile"
check_file_exists "ecosystem.config.js" "PM2 配置"
check_file_exists "package.json" "Package.json"
echo ""
# 2. 检查环境变量
log_info "检查环境变量..."
check_env_var "DATABASE_URL" "数据库连接"
check_env_var "SESSION_COOKIE_SECRET" "Session 密钥"
check_env_var "AI_API_KEY" "AI API 密钥"
check_env_var "SMTP_HOST" "SMTP 主机"
check_env_var "SMTP_PORT" "SMTP 端口"
check_env_var "SMTP_USER" "SMTP 用户名"
check_env_var "SMTP_PASS" "SMTP 密码"
check_env_var "OAUTH2_TOKEN_SIGNING_PRIVATE_KEY" "OAuth2 私钥"
check_env_var "OAUTH2_TOKEN_SIGNING_PUBLIC_KEY" "OAuth2 公钥"
echo ""
# 3. 检查可选环境变量
log_info "检查可选环境变量..."
check_env_var "REDIS_HOST" "Redis 主机" "false"
check_env_var "THROTTLE_TTL" "限流配置" "false"
check_env_var "APP_BASE_URL" "应用基础 URL" "false"
echo ""
# 4. 检查命令行工具
log_info "检查命令行工具..."
check_command "docker" "Docker CLI"
check_command "docker-compose" "Docker Compose"
check_command "node" "Node.js"
check_command "pnpm" "PNPM"
check_command "git" "Git"
echo ""
# 5. 检查端口占用
log_info "检查端口占用..."
check_port "3001" "API 端口"
check_port "5432" "PostgreSQL 端口"
check_port "6379" "Redis 端口"
echo ""
# 6. 检查 Docker 状态
log_info "检查 Docker 状态..."
check_docker
echo ""
# 7. 检查 Docker 镜像
log_info "检查 Docker 镜像..."
if docker image inspect binglogyblog-api:latest >/dev/null 2>&1; then
log_info "API 镜像: 存在"
((CHECKS_PASSED++))
else
log_warn "API 镜像: 不存在 (需要运行 docker-compose build)"
((CHECKS_WARNING++))
fi
if docker image inspect postgres:16-alpine >/dev/null 2>&1; then
log_info "PostgreSQL 镜像: 存在"
((CHECKS_PASSED++))
else
log_warn "PostgreSQL 镜像: 不存在 (将自动拉取)"
((CHECKS_WARNING++))
fi
if docker image inspect redis:7-alpine >/dev/null 2>&1; then
log_info "Redis 镜像: 存在"
((CHECKS_PASSED++))
else
log_warn "Redis 镜像: 不存在 (将自动拉取)"
((CHECKS_WARNING++))
fi
echo ""
# 8. 检查磁盘空间
log_info "检查磁盘空间..."
AVAILABLE_SPACE=$(df -BG . | tail -1 | awk '{print $4}' | sed 's/G//')
if [ "$AVAILABLE_SPACE" -ge 10 ]; then
log_info "可用磁盘空间: ${AVAILABLE_SPACE}GB"
((CHECKS_PASSED++))
else
log_warn "可用磁盘空间: ${AVAILABLE_SPACE}GB (建议至少 10GB)"
((CHECKS_WARNING++))
fi
echo ""
# 9. 检查数据库迁移状态
log_info "检查数据库迁移..."
if [ -d "prisma/migrations" ]; then
MIGRATION_COUNT=$(ls -1 prisma/migrations | wc -l)
log_info "迁移文件数量: $MIGRATION_COUNT"
((CHECKS_PASSED++))
else
log_warn "未找到迁移文件"
((CHECKS_WARNING++))
fi
echo ""
# ============================================
# 输出总结
# ============================================
echo "=========================================="
echo "验证完成"
echo "=========================================="
echo -e "通过: ${GREEN}$CHECKS_PASSED${NC}"
echo -e "警告: ${YELLOW}$CHECKS_WARNING${NC}"
echo -e "失败: ${RED}$CHECKS_FAILED${NC}"
echo ""
if [ $CHECKS_FAILED -gt 0 ]; then
log_error "存在 $CHECKS_FAILED 个问题需要修复"
echo ""
echo "建议操作:"
echo "1. 复制 .env.example 为 .env"
echo "2. 填写所有必需的配置项"
echo "3. 生成 OAuth2 RSA 密钥对"
echo "4. 运行: docker-compose build"
exit 1
elif [ $CHECKS_WARNING -gt 0 ]; then
log_warn "存在 $CHECKS_WARNING 个警告"
echo "建议继续,但请注意上述警告"
exit 0
else
log_info "所有检查通过!可以开始部署。"
echo ""
echo "下一步:"
echo " docker-compose build # 构建镜像"
echo " docker-compose up -d # 启动服务"
echo " curl http://localhost:3001/health # 验证健康状态"
exit 0
fi