312 lines
8.1 KiB
Bash
312 lines
8.1 KiB
Bash
#!/bin/bash
|
|
|
|
# 即梦 Free API 多实例 PM2 管理脚本
|
|
# 使用方法: ./multi-instance.sh [start|stop|restart|status|logs] [port1,port2,port3|all]
|
|
|
|
set -e
|
|
|
|
# 颜色输出
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# 日志函数
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# 可用的端口列表
|
|
AVAILABLE_PORTS=(3302 3303 3304)
|
|
ALL_APPS=("jimeng-api-3302" "jimeng-api-3303" "jimeng-api-3304")
|
|
|
|
# 检查PM2
|
|
check_pm2() {
|
|
if ! command -v pm2 &> /dev/null; then
|
|
log_error "PM2 未安装,请先安装 PM2"
|
|
log_info "npm install -g pm2"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 构建项目
|
|
build_project() {
|
|
if [ ! -d "dist" ]; then
|
|
log_info "构建项目..."
|
|
yarn install
|
|
yarn run build
|
|
log_success "项目构建完成"
|
|
fi
|
|
}
|
|
|
|
# 解析端口参数
|
|
parse_ports() {
|
|
local port_arg=$1
|
|
local target_ports=()
|
|
|
|
if [ "$port_arg" = "all" ] || [ -z "$port_arg" ]; then
|
|
target_ports=("${AVAILABLE_PORTS[@]}")
|
|
else
|
|
IFS=',' read -ra PORTS <<< "$port_arg"
|
|
for port in "${PORTS[@]}"; do
|
|
if [[ " ${AVAILABLE_PORTS[@]} " =~ " ${port} " ]]; then
|
|
target_ports+=("$port")
|
|
else
|
|
log_warning "无效端口: $port (可用端口: ${AVAILABLE_PORTS[*]})"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo "${target_ports[@]}"
|
|
}
|
|
|
|
# 获取应用名称
|
|
get_app_name() {
|
|
local port=$1
|
|
echo "jimeng-api-${port}"
|
|
}
|
|
|
|
# 启动指定端口的服务
|
|
start_services() {
|
|
local ports_str=$1
|
|
local env_mode=${2:-production}
|
|
local target_ports=($(parse_ports "$ports_str"))
|
|
|
|
if [ ${#target_ports[@]} -eq 0 ]; then
|
|
log_error "没有有效的端口"
|
|
return 1
|
|
fi
|
|
|
|
log_info "启动服务实例..."
|
|
build_project
|
|
|
|
for port in "${target_ports[@]}"; do
|
|
local app_name=$(get_app_name "$port")
|
|
log_info "启动 $app_name (端口 $port)..."
|
|
|
|
# 停止现有实例
|
|
pm2 delete "$app_name" 2>/dev/null || true
|
|
|
|
# 启动新实例
|
|
if [ "$env_mode" = "production" ]; then
|
|
pm2 start ecosystem.config.json --only "$app_name" --env production
|
|
else
|
|
pm2 start ecosystem.config.json --only "$app_name"
|
|
fi
|
|
|
|
# 等待启动完成
|
|
sleep 2
|
|
|
|
# 检查启动状态
|
|
if pm2 list | grep -q "$app_name.*online"; then
|
|
log_success "$app_name 启动成功 (http://localhost:$port)"
|
|
else
|
|
log_error "$app_name 启动失败"
|
|
fi
|
|
done
|
|
|
|
pm2 save
|
|
log_success "所有服务启动完成"
|
|
}
|
|
|
|
# 停止指定端口的服务
|
|
stop_services() {
|
|
local ports_str=$1
|
|
local target_ports=($(parse_ports "$ports_str"))
|
|
|
|
if [ ${#target_ports[@]} -eq 0 ]; then
|
|
log_error "没有有效的端口"
|
|
return 1
|
|
fi
|
|
|
|
log_info "停止服务实例..."
|
|
|
|
for port in "${target_ports[@]}"; do
|
|
local app_name=$(get_app_name "$port")
|
|
log_info "停止 $app_name..."
|
|
pm2 delete "$app_name" 2>/dev/null || log_warning "$app_name 不存在或已停止"
|
|
done
|
|
|
|
log_success "服务停止完成"
|
|
}
|
|
|
|
# 重启服务
|
|
restart_services() {
|
|
local ports_str=$1
|
|
local env_mode=${2:-production}
|
|
|
|
log_info "重启服务..."
|
|
stop_services "$ports_str"
|
|
sleep 2
|
|
start_services "$ports_str" "$env_mode"
|
|
}
|
|
|
|
# 查看服务状态
|
|
check_status() {
|
|
local ports_str=$1
|
|
local target_ports=($(parse_ports "$ports_str"))
|
|
|
|
echo "=== PM2 进程列表 ==="
|
|
pm2 list
|
|
|
|
echo
|
|
echo "=== 服务详细状态 ==="
|
|
|
|
if [ ${#target_ports[@]} -eq 0 ]; then
|
|
target_ports=("${AVAILABLE_PORTS[@]}")
|
|
fi
|
|
|
|
for port in "${target_ports[@]}"; do
|
|
local app_name=$(get_app_name "$port")
|
|
echo "--- $app_name (端口 $port) ---"
|
|
|
|
if pm2 list | grep -q "$app_name"; then
|
|
local status=$(pm2 list | grep "$app_name" | awk '{print $10}')\n log_info "状态: $status"
|
|
|
|
# 健康检查
|
|
if curl -s "http://localhost:$port/ping" > /dev/null 2>&1; then
|
|
log_success "健康检查: 正常"
|
|
|
|
# 获取服务器信息
|
|
local server_info=$(curl -s "http://localhost:$port/api/servers/current" 2>/dev/null || echo "{}")\n if [ "$server_info" != "{}" ]; then
|
|
log_info "服务器信息: $(echo "$server_info" | jq -r '.data.server_id // "unknown"' 2>/dev/null || echo "获取失败")"
|
|
fi
|
|
else
|
|
log_error "健康检查: 失败"
|
|
fi
|
|
else
|
|
log_warning "进程不存在"
|
|
fi
|
|
echo
|
|
done
|
|
|
|
echo "=== 端口占用情况 ==="
|
|
for port in "${target_ports[@]}"; do
|
|
if netstat -tlnp 2>/dev/null | grep ":$port " > /dev/null; then
|
|
log_success "端口 $port: 已占用"
|
|
else
|
|
log_warning "端口 $port: 未占用"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# 查看日志
|
|
view_logs() {
|
|
local ports_str=$1
|
|
local target_ports=($(parse_ports "$ports_str"))
|
|
|
|
if [ ${#target_ports[@]} -eq 0 ]; then
|
|
log_error "没有有效的端口"
|
|
return 1
|
|
fi
|
|
|
|
if [ ${#target_ports[@]} -eq 1 ]; then
|
|
# 单个服务,显示实时日志
|
|
local app_name=$(get_app_name "${target_ports[0]}")
|
|
log_info "查看 $app_name 实时日志..."
|
|
pm2 logs "$app_name" --lines 50
|
|
else
|
|
# 多个服务,显示最近日志
|
|
for port in "${target_ports[@]}"; do
|
|
local app_name=$(get_app_name "$port")
|
|
echo "=== $app_name 最近日志 ==="
|
|
pm2 logs "$app_name" --lines 20 --nostream
|
|
echo
|
|
done
|
|
fi
|
|
}
|
|
|
|
# 显示帮助
|
|
show_help() {
|
|
echo "即梦 Free API 多实例 PM2 管理脚本"
|
|
echo
|
|
echo "使用方法:"
|
|
echo " $0 <command> [ports] [env]"
|
|
echo
|
|
echo "命令:"
|
|
echo " start 启动服务实例"
|
|
echo " stop 停止服务实例"
|
|
echo " restart 重启服务实例"
|
|
echo " status 查看服务状态"
|
|
echo " logs 查看服务日志"
|
|
echo " help 显示此帮助信息"
|
|
echo
|
|
echo "端口参数:"
|
|
echo " all 所有端口 (默认)"
|
|
echo " 3302 仅端口 3302"
|
|
echo " 3302,3303 多个端口,用逗号分隔"
|
|
echo " 可用端口: ${AVAILABLE_PORTS[*]}"
|
|
echo
|
|
echo "环境参数 (仅 start/restart):"
|
|
echo " production 生产环境 (默认)"
|
|
echo " development 开发环境"
|
|
echo
|
|
echo "示例:"
|
|
echo " $0 start all production # 启动所有实例 (生产环境)"
|
|
echo " $0 start 3302,3303 development # 启动端口 3302 和 3303 (开发环境)"
|
|
echo " $0 stop 3304 # 停止端口 3304"
|
|
echo " $0 restart all # 重启所有实例"
|
|
echo " $0 status # 查看所有实例状态"
|
|
echo " $0 logs 3302 # 查看端口 3302 的日志"
|
|
echo
|
|
echo "服务访问地址:"
|
|
for port in "${AVAILABLE_PORTS[@]}"; do
|
|
echo " - http://localhost:$port (jimeng-api-$port)"
|
|
done
|
|
}
|
|
|
|
# 主函数
|
|
main() {
|
|
local command="$1"
|
|
local ports="$2"
|
|
local env_mode="${3:-production}"
|
|
|
|
check_pm2
|
|
|
|
case "$command" in
|
|
start)
|
|
start_services "$ports" "$env_mode"
|
|
;;
|
|
stop)
|
|
stop_services "$ports"
|
|
;;
|
|
restart)
|
|
restart_services "$ports" "$env_mode"
|
|
;;
|
|
status)
|
|
check_status "$ports"
|
|
;;
|
|
logs)
|
|
view_logs "$ports"
|
|
;;
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
"")
|
|
log_error "请指定命令"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
*)
|
|
log_error "未知命令: $command"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# 执行主函数
|
|
main "$@" |