#!/bin/bash # QAUP 统一服务管理脚本 # 支持管理QAUP核心服务、数据库、缓存和ADXP适配器 set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' NC='\033[0m' # 配置变量 COMPOSE_FILE="docker-compose.yml" ADXP_COMPOSE_FILE="docker-compose.adxp.yml" APP_SERVICE="qaup-app" DB_SERVICE="qaup-postgres" REDIS_SERVICE="qaup-redis" ADXP_SERVICE="adxp-adapter" print_message() { echo -e "${1}${2}${NC}" } print_header() { echo "" print_message $BLUE "=== QAUP 统一服务管理 ===" print_message $BLUE "当前目录: $(pwd)" print_message $BLUE "时间: $(date)" echo "" } # 检查必要文件 check_files() { if [ ! -f "$COMPOSE_FILE" ]; then print_message $RED "❌ 找不到 $COMPOSE_FILE 文件" exit 1 fi if [ ! -f "config.yml" ]; then print_message $RED "❌ 找不到 config.yml 文件" exit 1 fi } # 启动所有服务 start_all() { print_message $BLUE "启动所有QAUP服务..." # 启动基础设施服务 print_message $BLUE "1. 启动数据库服务..." docker compose up -d $DB_SERVICE print_message $BLUE "2. 启动缓存服务..." docker compose up -d $REDIS_SERVICE # 等待基础设施就绪 print_message $BLUE "等待基础设施服务就绪..." sleep 30 # 检查数据库状态 if ! docker exec $DB_SERVICE pg_isready -U qaup > /dev/null 2>&1; then print_message $RED "❌ 数据库启动失败" return 1 fi # 检查Redis状态 if ! docker exec $REDIS_SERVICE redis-cli ping > /dev/null 2>&1; then print_message $RED "❌ Redis启动失败" return 1 fi print_message $GREEN "✓ 基础设施服务就绪" # 启动应用服务 print_message $BLUE "3. 启动应用服务..." docker compose up -d $APP_SERVICE # 启动ADXP适配器(如果配置文件存在) if [ -f "$ADXP_COMPOSE_FILE" ]; then print_message $BLUE "4. 启动ADXP适配器..." docker compose -f $COMPOSE_FILE -f $ADXP_COMPOSE_FILE up -d $ADXP_SERVICE fi print_message $GREEN "🎉 所有服务启动完成!" show_status } # 停止所有服务 stop_all() { print_message $BLUE "停止所有QAUP服务..." # 停止ADXP适配器 if [ -f "$ADXP_COMPOSE_FILE" ]; then docker compose -f $COMPOSE_FILE -f $ADXP_COMPOSE_FILE down $ADXP_SERVICE 2>/dev/null || true fi # 停止应用服务 docker compose stop $APP_SERVICE 2>/dev/null || true # 停止缓存服务 docker compose stop $REDIS_SERVICE 2>/dev/null || true # 停止数据库服务 docker compose stop $DB_SERVICE 2>/dev/null || true print_message $GREEN "✓ 所有服务已停止" } # 重启所有服务 restart_all() { print_message $BLUE "重启所有QAUP服务..." stop_all sleep 5 start_all } # 查看服务状态 show_status() { print_message $BLUE "服务状态:" echo "" # 显示服务状态表格 printf "%-20s %-15s %-15s %-10s\n" "服务名" "状态" "端口" "健康检查" printf "%-20s %-15s %-15s %-10s\n" "--------------------" "---------------" "---------------" "----------" # 检查各个服务状态 services=( "$APP_SERVICE:8080:qaup-app" "$DB_SERVICE:5432:qaup-postgres" "$REDIS_SERVICE:6379:qaup-redis" ) for service_info in "${services[@]}"; do service=$(echo $service_info | cut -d: -f1) port=$(echo $service_info | cut -d: -f2) container=$(echo $service_info | cut -d: -f3) status=$(docker compose ps $service --format json 2>/dev/null | jq -r '.[0].State' 2>/dev/null || echo "unknown") # 健康检查 if [ "$status" = "running" ]; then if [ "$service" = "$APP_SERVICE" ]; then health=$(curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1 && echo "正常" || echo "异常") elif [ "$service" = "$DB_SERVICE" ]; then health=$(docker exec $DB_SERVICE pg_isready -U qaup > /dev/null 2>&1 && echo "正常" || echo "异常") elif [ "$service" = "$REDIS_SERVICE" ]; then health=$(docker exec $REDIS_SERVICE redis-cli ping > /dev/null 2>&1 && echo "正常" || echo "异常") fi else health="未运行" fi printf "%-20s %-15s %-15s %-10s\n" "$service" "$status" "$port" "$health" done # 检查ADXP适配器状态 if [ -f "$ADXP_COMPOSE_FILE" ]; then adxp_status=$(docker compose -f $COMPOSE_FILE -f $ADXP_COMPOSE_FILE ps $ADXP_SERVICE --format json 2>/dev/null | jq -r '.[0].State' 2>/dev/null || echo "unknown") adxp_health=$(curl -f -s http://localhost:8086/health > /dev/null 2>&1 && echo "正常" || echo "异常") printf "%-20s %-15s %-15s %-10s\n" "$ADXP_SERVICE" "$adxp_status" "8086" "$adxp_health" fi echo "" } # 查看日志 show_logs() { local service=${1:-""} local lines=${2:-50} if [ -n "$service" ]; then print_message $BLUE "查看 $service 服务日志 (最后 $lines 行):" docker compose logs --tail=$lines -f $service else print_message $BLUE "查看所有服务日志 (最后 $lines 行):" docker compose logs --tail=$lines -f fi } # 健康检查 health_check() { print_message $BLUE "执行健康检查..." local errors=0 # 检查Docker服务 if ! docker info > /dev/null 2>&1; then print_message $RED "❌ Docker服务不可用" ((errors++)) else print_message $GREEN "✓ Docker服务正常" fi # 检查应用健康状态 if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then print_message $GREEN "✓ 应用服务健康检查通过" else print_message $RED "❌ 应用服务健康检查失败" ((errors++)) fi # 检查数据库连接 if docker exec $DB_SERVICE pg_isready -U qaup > /dev/null 2>&1; then print_message $GREEN "✓ 数据库连接正常" else print_message $RED "❌ 数据库连接失败" ((errors++)) fi # 检查Redis连接 if docker exec $REDIS_SERVICE redis-cli ping > /dev/null 2>&1; then print_message $GREEN "✓ Redis连接正常" else print_message $RED "❌ Redis连接失败" ((errors++)) fi # 检查磁盘空间 available_space=$(df . | tail -1 | awk '{print $4}') if [ "$available_space" -gt $((1024*1024)) ]; then # 1GB print_message $GREEN "✓ 磁盘空间充足" else print_message $RED "❌ 磁盘空间不足" ((errors++)) fi # 检查端口占用 ports=(8080 5432 6379 8086) for port in "${ports[@]}"; do if netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then print_message $GREEN "✓ 端口 $port 占用正常" else print_message $YELLOW "⚠️ 端口 $port 未占用" fi done if [ $errors -eq 0 ]; then print_message $GREEN "🎉 所有健康检查通过!" return 0 else print_message $RED "❌ 发现 $errors 个问题" return 1 fi } # 数据备份 backup_data() { local backup_dir="backup" local timestamp=$(date +%Y%m%d_%H%M%S) print_message $BLUE "开始数据备份..." mkdir -p "$backup_dir" # 备份数据库 local db_backup="$backup_dir/qaup_db_backup_$timestamp.sql" print_message $BLUE "1. 备份数据库..." if docker exec $DB_SERVICE pg_dump -U qaup qaup > "$db_backup" 2>/dev/null; then print_message $GREEN "✓ 数据库备份成功: $db_backup" else print_message $RED "❌ 数据库备份失败" return 1 fi # 备份Redis数据 local redis_backup="$backup_dir/redis_backup_$timestamp.rdb" print_message $BLUE "2. 备份Redis数据..." if docker exec $REDIS_SERVICE redis-cli BGSAVE > /dev/null 2>&1; then sleep 5 docker cp $REDIS_SERVICE:/data/dump.rdb "$redis_backup" 2>/dev/null if [ -f "$redis_backup" ]; then print_message $GREEN "✓ Redis备份成功: $redis_backup" else print_message $RED "❌ Redis备份失败" fi else print_message $YELLOW "⚠️ Redis备份跳过" fi # 备份应用配置 local config_backup="$backup_dir/config_backup_$timestamp.yml" print_message $BLUE "3. 备份应用配置..." if cp config.yml "$config_backup"; then print_message $GREEN "✓ 配置备份成功: $config_backup" else print_message $RED "❌ 配置备份失败" fi print_message $GREEN "🎉 数据备份完成!" ls -la "$backup_dir"/*_$timestamp.* } # 清理数据 clean_data() { print_message $YELLOW "⚠️ 这将删除所有数据目录,确认继续吗?(y/N): " read -r confirmation if [[ ! $confirmation =~ ^[Yy]$ ]]; then print_message $BLUE "操作已取消" return fi print_message $BLUE "清理数据目录..." # 停止所有服务 stop_all # 删除数据目录 rm -rf data/ logs/ backup/ print_message $GREEN "✓ 数据目录已清理" print_message $BLUE "请运行 './qaup-service.sh start' 重新初始化数据" } # 更新应用 update_app() { if [ ! -f "new-app.jar" ]; then print_message $RED "❌ 未找到新版本文件: new-app.jar" print_message $BLUE "请先将新版本文件重命名为 new-app.jar" exit 1 fi print_message $BLUE "开始应用更新..." # 备份当前应用 local backup_dir="backup" local timestamp=$(date +%Y%m%d_%H%M%S) mkdir -p "$backup_dir" if [ -f "app.jar" ]; then cp app.jar "$backup_dir/app.jar.backup.$timestamp" print_message $BLUE "✓ 当前应用已备份" fi # 停止应用服务 docker compose stop $APP_SERVICE # 替换应用文件 if cp new-app.jar app.jar; then print_message $GREEN "✓ 应用文件更新成功" else print_message $RED "❌ 应用文件更新失败" exit 1 fi # 启动应用服务 docker compose up -d $APP_SERVICE # 等待应用启动 print_message $BLUE "等待应用启动..." sleep 30 # 验证更新结果 if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then print_message $GREEN "🎉 应用更新成功!" else print_message $RED "❌ 应用更新失败,正在回滚..." # 回滚应用 if [ -f "$backup_dir/app.jar.backup.$timestamp" ]; then docker compose stop $APP_SERVICE cp "$backup_dir/app.jar.backup.$timestamp" app.jar docker compose up -d $APP_SERVICE print_message $BLUE "✓ 应用已回滚" fi exit 1 fi } # 显示帮助信息 show_help() { print_message $BLUE "QAUP 统一服务管理脚本" echo "" print_message $BLUE "使用方法:" print_message $BLUE " ./qaup-service.sh [options]" echo "" print_message $BLUE "可用命令:" print_message $BLUE " start 启动所有服务" print_message $BLUE " stop 停止所有服务" print_message $BLUE " restart 重启所有服务" print_message $BLUE " status 查看服务状态" print_message $BLUE " logs [service] 查看日志 (可指定服务名)" print_message $BLUE " health 执行健康检查" print_message $BLUE " backup 备份数据" print_message $BLUE " clean 清理所有数据" print_message $BLUE " update 更新应用" print_message $BLUE " help 显示此帮助信息" echo "" print_message $BLUE "示例:" print_message $BLUE " ./qaup-service.sh start" print_message $BLUE " ./qaup-service.sh logs qaup-app" print_message $BLUE " ./qaup-service.sh health" print_message $BLUE " ./qaup-service.sh backup" } # 主函数 main() { check_files case "${1:-help}" in start) start_all ;; stop) stop_all ;; restart) restart_all ;; status) show_status ;; logs) show_logs "$2" "${3:-50}" ;; health) health_check ;; backup) backup_data ;; clean) clean_data ;; update) update_app ;; help|--help|-h) show_help ;; *) print_message $RED "❌ 未知命令: $1" show_help exit 1 ;; esac } # 执行主函数 main "$@"