Files
hzdyjs/docs/部署文档/杭州第一技师部署文档/start-multi-instance.sh
T
2025-08-31 19:38:31 +08:00

285 lines
7.6 KiB
Bash

#!/bin/bash
# 多实例启动脚本
# 使用方法: ./start-multi-instance.sh [start|stop|restart|status] [instance_name]
# 实例名称: 9900, 9901, 9902, 9903, all
# 配置变量
JAR_NAME="ruoyi-admin.jar"
JAVA_OPTS="-Xms8192m -Xmx8192m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1024m"
JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/"
# 实例配置
declare -A INSTANCES
INSTANCES[9900]="prod-9900"
INSTANCES[9901]="prod-9901"
INSTANCES[9902]="prod-9902"
INSTANCES[9903]="prod-9903"
# 日志目录
LOG_DIR="logs"
mkdir -p $LOG_DIR
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 打印带颜色的消息
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# 检查JAR文件是否存在
check_jar() {
if [ ! -f "$JAR_NAME" ]; then
print_message $RED "错误: $JAR_NAME 文件不存在!"
print_message $YELLOW "请确保在正确的目录下运行此脚本,或先执行 mvn clean package -Pprod 编译项目"
exit 1
fi
}
# 启动单个实例
start_instance() {
local port=$1
local profile=$2
local pid_file="logs/ruoyi-admin-${port}.pid"
local log_file="logs/ruoyi-admin-${port}.log"
# 检查是否已经运行
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p $pid > /dev/null 2>&1; then
print_message $YELLOW "实例 $port 已经在运行中 (PID: $pid)"
return
else
# PID文件存在但进程不存在,清理PID文件
rm -f "$pid_file"
fi
fi
print_message $GREEN "正在启动实例 $port (配置文件: $profile)..."
# 启动应用
nohup java $JAVA_OPTS \
-Dspring.profiles.active=prod,$profile \
-Dserver.port=$port \
-jar $JAR_NAME \
> "$log_file" 2>&1 &
local new_pid=$!
echo $new_pid > "$pid_file"
# 等待启动
sleep 3
# 检查启动状态
if ps -p $new_pid > /dev/null 2>&1; then
print_message $GREEN "实例 $port 启动成功 (PID: $new_pid)"
print_message $GREEN "访问地址: http://localhost:$port"
print_message $GREEN "日志文件: $log_file"
else
print_message $RED "实例 $port 启动失败,请检查日志文件: $log_file"
rm -f "$pid_file"
fi
}
# 停止单个实例
stop_instance() {
local port=$1
local pid_file="logs/ruoyi-admin-${port}.pid"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p $pid > /dev/null 2>&1; then
print_message $YELLOW "正在停止实例 $port (PID: $pid)..."
kill $pid
# 等待进程结束
local count=0
while ps -p $pid > /dev/null 2>&1 && [ $count -lt 30 ]; do
sleep 1
count=$((count + 1))
done
# 强制杀死进程
if ps -p $pid > /dev/null 2>&1; then
print_message $YELLOW "强制停止实例 $port..."
kill -9 $pid
fi
rm -f "$pid_file"
print_message $GREEN "实例 $port 已停止"
else
print_message $YELLOW "实例 $port 未运行"
rm -f "$pid_file"
fi
else
print_message $YELLOW "实例 $port 未运行"
fi
}
# 重启单个实例
restart_instance() {
local port=$1
print_message $YELLOW "重启实例 $port..."
stop_instance $port
sleep 2
start_instance $port ${INSTANCES[$port]}
}
# 查看实例状态
status_instance() {
local port=$1
local pid_file="logs/ruoyi-admin-${port}.pid"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p $pid > /dev/null 2>&1; then
local memory=$(ps -o rss= -p $pid | awk '{print $1/1024 " MB"}')
local uptime=$(ps -o etime= -p $pid)
print_message $GREEN "实例 $port: 运行中 (PID: $pid, 内存: $memory, 运行时间: $uptime)"
else
print_message $RED "实例 $port: 异常 (PID文件存在但进程不存在)"
rm -f "$pid_file"
fi
else
print_message $YELLOW "实例 $port: 未运行"
fi
}
# 启动所有实例
start_all() {
print_message $GREEN "启动所有实例..."
for port in "${!INSTANCES[@]}"; do
start_instance $port ${INSTANCES[$port]}
sleep 2
done
}
# 停止所有实例
stop_all() {
print_message $YELLOW "停止所有实例..."
for port in "${!INSTANCES[@]}"; do
stop_instance $port
done
}
# 重启所有实例
restart_all() {
print_message $YELLOW "重启所有实例..."
stop_all
sleep 3
start_all
}
# 查看所有实例状态
status_all() {
print_message $GREEN "所有实例状态:"
for port in "${!INSTANCES[@]}"; do
status_instance $port
done
}
# 显示帮助信息
show_help() {
echo "多实例启动脚本使用方法:"
echo " $0 [命令] [实例名称]"
echo ""
echo "命令:"
echo " start 启动实例"
echo " stop 停止实例"
echo " restart 重启实例"
echo " status 查看实例状态"
echo ""
echo "实例名称:"
echo " 9900 启动9900端口实例"
echo " 9901 启动9901端口实例"
echo " 9902 启动9902端口实例"
echo " 9903 启动9903端口实例"
echo " all 操作所有实例"
echo ""
echo "示例:"
echo " $0 start 9900 # 启动9900端口实例"
echo " $0 start all # 启动所有实例"
echo " $0 stop 9900 # 停止9900端口实例"
echo " $0 status all # 查看所有实例状态"
echo " $0 restart all # 重启所有实例"
}
# 主函数
main() {
local action=$1
local instance=$2
# 检查参数
if [ -z "$action" ]; then
show_help
exit 1
fi
# 检查JAR文件
check_jar
case $action in
start)
if [ "$instance" = "all" ]; then
start_all
elif [ -n "${INSTANCES[$instance]}" ]; then
start_instance $instance ${INSTANCES[$instance]}
else
print_message $RED "无效的实例名称: $instance"
show_help
exit 1
fi
;;
stop)
if [ "$instance" = "all" ]; then
stop_all
elif [ -n "${INSTANCES[$instance]}" ]; then
stop_instance $instance
else
print_message $RED "无效的实例名称: $instance"
show_help
exit 1
fi
;;
restart)
if [ "$instance" = "all" ]; then
restart_all
elif [ -n "${INSTANCES[$instance]}" ]; then
restart_instance $instance
else
print_message $RED "无效的实例名称: $instance"
show_help
exit 1
fi
;;
status)
if [ "$instance" = "all" ]; then
status_all
elif [ -n "${INSTANCES[$instance]}" ]; then
status_instance $instance
else
print_message $RED "无效的实例名称: $instance"
show_help
exit 1
fi
;;
*)
print_message $RED "无效的命令: $action"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"