441 lines
13 KiB
Bash
441 lines
13 KiB
Bash
#!/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 <command> [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 "$@" |