#!/bin/bash # ============================================ # LinkShare Blog - 增强健康检查脚本 # ============================================ # 用途: 全面检查系统状态,包括初始化状态 # 用法: ./scripts/healthcheck.sh [--admin-token TOKEN] # 示例: ./scripts/healthcheck.sh # ./scripts/healthcheck.sh --admin-token xxx set -e # API 地址 API_URL=${HEALTH_CHECK_URL:-http://localhost:3001} ADMIN_TOKEN=${ADMIN_TOKEN:-} # 颜色定义 GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } # 检查 API 健康 check_api() { log_step "检查 API 健康状态..." local response=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL/health" 2>/dev/null) if [ "$response" = "200" ]; then log_info "✓ API 健康检查通过 (HTTP $response)" return 0 else log_error "✗ API 健康检查失败 (HTTP $response)" return 1 fi } # 检查数据库连接 check_database() { log_step "检查数据库连接..." local health_json=$(curl -s "$API_URL/health" 2>/dev/null || echo "") if echo "$health_json" | grep -q '"database":"ok"'; then log_info "✓ 数据库连接正常" return 0 else log_error "✗ 数据库连接异常" return 1 fi } # 检查 Redis 连接 check_redis() { log_step "检查 Redis 连接..." local health_json=$(curl -s "$API_URL/health" 2>/dev/null || echo "") if echo "$health_json" | grep -q '"redis":"ok"'; then log_info "✓ Redis 连接正常" return 0 else log_error "✗ Redis 连接异常" return 1 fi } # 检查初始化状态(需要管理员 token) check_initialization() { log_step "检查系统初始化状态..." if [ -z "$ADMIN_TOKEN" ]; then # 尝试从环境变量或 .env 文件获取管理员 token(简化版) log_warn "未提供管理员 token,跳过初始化状态检查" log_info "提示: 使用 --admin-token 参数或设置 ADMIN_TOKEN 环境变量" return 0 fi local response=$(curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ "$API_URL/init/status" 2>/dev/null) if [ "$response" = "200" ]; then log_info "✓ 初始化状态检查成功" # 可选:显示详细状态 # local status_json=$(curl -s -H "Authorization: Bearer $ADMIN_TOKEN" "$API_URL/init/status") # echo "$status_json" | python3 -m json.tool 2>/dev/null || echo "$status_json" return 0 else log_error "✗ 初始化状态检查失败 (HTTP $response)" return 1 fi } # 检查关键 API 端点 check_endpoints() { log_step "检查关键 API 端点..." local all_ok=true # 健康检查端点 if curl -sf "$API_URL/health" >/dev/null 2>/dev/null; then log_info " ✓ GET /health" else log_error " ✗ GET /health 失败" all_ok=false fi # 登录端点(不验证,只检查是否存在) if curl -sf -X POST "$API_URL/login" \ -H "Content-Type: application/json" \ -d '{"emailOrUsername":"test","password":"test"}"' \ >/dev/null 2>&1; then # 即使登录失败(401),端点也是可用的 log_info " ✓ POST /login (可用)" else log_error " ✗ POST /login 不可用" all_ok=false fi # 初始化端点(需要管理员 token) if [ -n "$ADMIN_TOKEN" ]; then if curl -sf -H "Authorization: Bearer $ADMIN_TOKEN" "$API_URL/init/status" \ >/dev/null 2>&1; then log_info " ✓ GET /init/status (管理员)" else log_warn " ⚠ GET /init/status 失败 (可能需要管理员权限)" fi fi return $([ "$all_ok" = true ] && echo 0 || echo 1) } # 检查磁盘空间 check_disk() { log_step "检查磁盘空间..." local available=$(df -BG /app 2>/dev/null | tail -1 | awk '{print $4}' | sed 's/G//' || echo "0") if [ "$available" -ge 5 ]; then log_info "✓ 可用磁盘空间: ${available}GB" return 0 else log_warn "⚠ 可用磁盘空间: ${available}GB (建议至少 5GB)" return 0 # 仅警告,不失败 fi } # 检查 Docker 容器状态 check_containers() { log_step "检查 Docker 容器状态..." local all_running=true # 检查 API 容器 if docker ps --format '{{.Names}}' | grep -q 'blog-api'; then log_info " ✓ API 容器运行中" else log_error " ✗ API 容器未运行" all_running=false fi # 检查数据库容器 if docker ps --format '{{.Names}}' | grep -q 'blog-postgres'; then log_info " ✓ PostgreSQL 容器运行中" else log_error " ✗ PostgreSQL 容器未运行" all_running=false fi # 检查 Redis 容器 if docker ps --format '{{.Names}}' | grep -q 'blog-redis'; then log_info " ✓ Redis 容器运行中" else log_error " ✗ Redis 容器未运行" all_running=false fi return $([ "$all_running" = true ] && echo 0 || echo 1) } # 主检查流程 main() { echo "==========================================" echo "LinkShare Blog 系统健康检查" echo "检查时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "API URL: $API_URL" echo "==========================================" echo "" local all_passed=true # 1. 容器状态检查 if command -v docker &>/dev/null; then check_containers || all_passed=false echo "" fi # 2. API 健康检查 check_api || all_passed=false echo "" # 3. 数据库检查 check_database || all_passed=false echo "" # 4. Redis 检查 check_redis || all_passed=false echo "" # 5. 初始化状态检查 check_initialization || all_passed=false echo "" # 6. 关键端点检查 check_endpoints || all_passed=false echo "" # 7. 磁盘空间检查 check_disk echo "" # 总结 echo "==========================================" if [ "$all_passed" = true ]; then log_info "所有关键检查通过!系统运行正常。" echo "" echo "下一步:" echo " - 访问 API: $API_URL" echo " - Swagger 文档: $API_URL/api-docs (开发环境)" echo " - 初始化状态: $API_URL/init/status (需要管理员 Token)" exit 0 else log_error "部分检查失败,请排查上述问题。" echo "" echo "故障排查:" echo " - 查看日志: docker-compose logs -f api" echo " - 重启服务: make restart" echo " - 重新部署: make deploy" echo " - 查看文档: DEPLOYMENT.md" exit 1 fi } # 运行主函数 main