351 lines
9.1 KiB
Bash
351 lines
9.1 KiB
Bash
#!/bin/bash
|
|
# ================================================
|
|
# Urban Lifeline - 服务管理脚本
|
|
#
|
|
# 用法:
|
|
# ./service-manager.sh start-all # 启动所有服务
|
|
# ./service-manager.sh start gateway # 启动单个服务
|
|
# ./service-manager.sh stop gateway # 停止单个服务
|
|
# ./service-manager.sh restart gateway # 重启单个服务
|
|
# ./service-manager.sh status # 查看所有服务状态
|
|
# ./service-manager.sh logs gateway # 查看服务日志
|
|
# ================================================
|
|
|
|
set -e
|
|
|
|
# 目录配置
|
|
JAR_DIR="/app/jars"
|
|
LOG_DIR="/app/logs"
|
|
PID_DIR="/app/pids"
|
|
|
|
# 服务配置: 服务名=端口:内存
|
|
declare -A SERVICES=(
|
|
["gateway"]="8080:384m"
|
|
["system"]="8082:384m"
|
|
["auth"]="8081:256m"
|
|
["file"]="8084:256m"
|
|
["log"]="8083:192m"
|
|
["message"]="8085:256m"
|
|
["crontab"]="8086:192m"
|
|
["ai"]="8090:384m"
|
|
["bidding"]="8087:256m"
|
|
["platform"]="8089:256m"
|
|
["workcase"]="8088:384m"
|
|
)
|
|
|
|
# 启动顺序 (有依赖关系)
|
|
# BOOT_ORDER=(gateway system auth file log message crontab ai bidding platform workcase)
|
|
BOOT_ORDER=(gateway system auth file ai workcase)
|
|
|
|
# 颜色输出
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# 获取服务端口
|
|
get_port() {
|
|
local service=$1
|
|
echo "${SERVICES[$service]}" | cut -d: -f1
|
|
}
|
|
|
|
# 获取服务内存配置
|
|
get_memory() {
|
|
local service=$1
|
|
echo "${SERVICES[$service]}" | cut -d: -f2
|
|
}
|
|
|
|
# 检查服务是否运行
|
|
is_running() {
|
|
local service=$1
|
|
local pid_file="${PID_DIR}/${service}.pid"
|
|
|
|
if [ -f "$pid_file" ]; then
|
|
local pid=$(cat "$pid_file")
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# 等待服务就绪
|
|
wait_for_service() {
|
|
local service=$1
|
|
local port=$(get_port "$service")
|
|
local max_wait=60
|
|
local count=0
|
|
|
|
while [ $count -lt $max_wait ]; do
|
|
if curl -sf "http://localhost:${port}/actuator/health" > /dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
count=$((count + 2))
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# 启动单个服务
|
|
start_service() {
|
|
local service=$1
|
|
local port=$(get_port "$service")
|
|
local memory=$(get_memory "$service")
|
|
local jar_file="${JAR_DIR}/${service}.jar"
|
|
local log_file="${LOG_DIR}/${service}.log"
|
|
local pid_file="${PID_DIR}/${service}.pid"
|
|
|
|
if [ ! -f "$jar_file" ]; then
|
|
log_error "JAR 文件不存在: $jar_file"
|
|
return 1
|
|
fi
|
|
|
|
if is_running "$service"; then
|
|
log_warn "$service 已在运行 (PID: $(cat $pid_file))"
|
|
return 0
|
|
fi
|
|
|
|
log_info "启动 $service (端口: $port, 内存: $memory)..."
|
|
|
|
# JVM 参数
|
|
local java_opts="-Xms128m -Xmx${memory} -XX:+UseG1GC -XX:MaxGCPauseMillis=100"
|
|
java_opts="$java_opts -Djava.security.egd=file:/dev/./urandom"
|
|
java_opts="$java_opts -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod}"
|
|
|
|
# Nacos 配置
|
|
if [ -n "$NACOS_SERVER_ADDR" ]; then
|
|
java_opts="$java_opts -Dspring.cloud.nacos.discovery.server-addr=$NACOS_SERVER_ADDR"
|
|
java_opts="$java_opts -Dspring.cloud.nacos.config.server-addr=$NACOS_SERVER_ADDR"
|
|
fi
|
|
|
|
if [ -n "$NACOS_NAMESPACE" ]; then
|
|
java_opts="$java_opts -Dspring.cloud.nacos.discovery.namespace=$NACOS_NAMESPACE"
|
|
java_opts="$java_opts -Dspring.cloud.nacos.config.namespace=$NACOS_NAMESPACE"
|
|
fi
|
|
|
|
# 启动服务
|
|
nohup java $java_opts -jar "$jar_file" > "$log_file" 2>&1 &
|
|
local pid=$!
|
|
echo $pid > "$pid_file"
|
|
|
|
log_info "$service 已启动 (PID: $pid)"
|
|
}
|
|
|
|
# 停止单个服务
|
|
stop_service() {
|
|
local service=$1
|
|
local pid_file="${PID_DIR}/${service}.pid"
|
|
|
|
if ! is_running "$service"; then
|
|
log_warn "$service 未在运行"
|
|
return 0
|
|
fi
|
|
|
|
local pid=$(cat "$pid_file")
|
|
log_info "停止 $service (PID: $pid)..."
|
|
|
|
# 优雅关闭
|
|
kill -15 "$pid" 2>/dev/null || true
|
|
|
|
# 等待进程退出
|
|
local count=0
|
|
while [ $count -lt 30 ] && kill -0 "$pid" 2>/dev/null; do
|
|
sleep 1
|
|
count=$((count + 1))
|
|
done
|
|
|
|
# 强制关闭
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
log_warn "强制终止 $service..."
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
fi
|
|
|
|
rm -f "$pid_file"
|
|
log_info "$service 已停止"
|
|
}
|
|
|
|
# 重启单个服务
|
|
restart_service() {
|
|
local service=$1
|
|
stop_service "$service"
|
|
sleep 2
|
|
start_service "$service"
|
|
}
|
|
|
|
# 启动所有服务
|
|
start_all() {
|
|
log_info "=========================================="
|
|
log_info " Urban Lifeline - 启动所有服务"
|
|
log_info "=========================================="
|
|
|
|
# 等待 Nacos
|
|
if [ -n "$NACOS_SERVER_ADDR" ]; then
|
|
log_info "等待 Nacos 就绪..."
|
|
local nacos_host=$(echo $NACOS_SERVER_ADDR | cut -d: -f1)
|
|
local nacos_port=$(echo $NACOS_SERVER_ADDR | cut -d: -f2)
|
|
|
|
for i in $(seq 1 30); do
|
|
if curl -sf "http://${nacos_host}:${nacos_port}/nacos/" > /dev/null 2>&1; then
|
|
log_info "Nacos 已就绪"
|
|
break
|
|
fi
|
|
sleep 2
|
|
done
|
|
fi
|
|
|
|
# 按顺序启动服务,等待健康检查通过后再启动下一个
|
|
for service in "${BOOT_ORDER[@]}"; do
|
|
start_service "$service"
|
|
|
|
log_info "等待 $service 健康检查..."
|
|
if wait_for_service "$service"; then
|
|
log_info "$service 已就绪 ✓"
|
|
else
|
|
log_warn "$service 健康检查超时,继续启动下一个服务"
|
|
fi
|
|
done
|
|
|
|
log_info "=========================================="
|
|
log_info " 所有服务启动完成"
|
|
log_info "=========================================="
|
|
|
|
show_status
|
|
|
|
# 保持容器运行并监控
|
|
monitor_services
|
|
}
|
|
|
|
# 停止所有服务
|
|
stop_all() {
|
|
log_info "停止所有服务..."
|
|
|
|
# 逆序停止
|
|
for ((i=${#BOOT_ORDER[@]}-1; i>=0; i--)); do
|
|
stop_service "${BOOT_ORDER[$i]}"
|
|
done
|
|
|
|
log_info "所有服务已停止"
|
|
}
|
|
|
|
# 查看服务状态
|
|
show_status() {
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " Urban Lifeline 服务状态"
|
|
echo "=========================================="
|
|
printf "%-12s %-8s %-8s %-10s\n" "服务" "端口" "PID" "状态"
|
|
echo "------------------------------------------"
|
|
|
|
for service in "${BOOT_ORDER[@]}"; do
|
|
local port=$(get_port "$service")
|
|
local pid_file="${PID_DIR}/${service}.pid"
|
|
local pid="-"
|
|
local status="${RED}停止${NC}"
|
|
|
|
if [ -f "$pid_file" ]; then
|
|
pid=$(cat "$pid_file")
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
status="${GREEN}运行中${NC}"
|
|
fi
|
|
fi
|
|
|
|
printf "%-12s %-8s %-8s " "$service" "$port" "$pid"
|
|
echo -e "$status"
|
|
done
|
|
echo "=========================================="
|
|
}
|
|
|
|
# 查看服务日志
|
|
show_logs() {
|
|
local service=$1
|
|
local log_file="${LOG_DIR}/${service}.log"
|
|
|
|
if [ ! -f "$log_file" ]; then
|
|
log_error "日志文件不存在: $log_file"
|
|
return 1
|
|
fi
|
|
|
|
tail -f "$log_file"
|
|
}
|
|
|
|
# 监控服务 (保持容器运行)
|
|
monitor_services() {
|
|
log_info "进入监控模式..."
|
|
|
|
# 捕获退出信号
|
|
trap 'stop_all; exit 0' SIGTERM SIGINT
|
|
|
|
while true; do
|
|
sleep 30
|
|
|
|
# 检查服务状态,自动重启挂掉的服务
|
|
for service in "${BOOT_ORDER[@]}"; do
|
|
if ! is_running "$service"; then
|
|
log_warn "$service 已停止,尝试重启..."
|
|
start_service "$service"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
# 主入口
|
|
case "${1:-help}" in
|
|
start-all)
|
|
start_all
|
|
;;
|
|
stop-all)
|
|
stop_all
|
|
;;
|
|
start)
|
|
if [ -z "$2" ]; then
|
|
log_error "请指定服务名"
|
|
exit 1
|
|
fi
|
|
start_service "$2"
|
|
;;
|
|
stop)
|
|
if [ -z "$2" ]; then
|
|
log_error "请指定服务名"
|
|
exit 1
|
|
fi
|
|
stop_service "$2"
|
|
;;
|
|
restart)
|
|
if [ -z "$2" ]; then
|
|
log_error "请指定服务名"
|
|
exit 1
|
|
fi
|
|
restart_service "$2"
|
|
;;
|
|
status)
|
|
show_status
|
|
;;
|
|
logs)
|
|
if [ -z "$2" ]; then
|
|
log_error "请指定服务名"
|
|
exit 1
|
|
fi
|
|
show_logs "$2"
|
|
;;
|
|
*)
|
|
echo "Urban Lifeline 服务管理"
|
|
echo ""
|
|
echo "用法: $0 <命令> [服务名]"
|
|
echo ""
|
|
echo "命令:"
|
|
echo " start-all 启动所有服务"
|
|
echo " stop-all 停止所有服务"
|
|
echo " start <服务> 启动指定服务"
|
|
echo " stop <服务> 停止指定服务"
|
|
echo " restart <服务> 重启指定服务"
|
|
echo " status 查看服务状态"
|
|
echo " logs <服务> 查看服务日志"
|
|
echo ""
|
|
echo "可用服务: ${!SERVICES[*]}"
|
|
;;
|
|
esac
|