#!/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