#!/bin/bash #author: forge-admin #file: forge-start.sh #comment: Forge Admin 服务管理脚本 #history: # 2026-09-11 创建,支持 forge-admin / forge-flow / forge-app / forge-report 四个服务 ## ==================== 配置区 ==================== # 服务名 SERVICE_NAME=( forge-admin-server forge-flow-server forge-app-server forge-report-server ) # 服务启动包所在的目录 SERVICE_PATH=( /mnt/project/forge-admin /mnt/project/forge-admin /mnt/project/forge-admin /mnt/project/forge-admin ) # 服务启动包 SERVICE_PACKAGE=( forge-admin-server.jar forge-flow-server.jar forge-app-server.jar forge-report-server.jar ) # 服务端口 SERVICE_PORT=( 8580 8081 8583 8582 ) # JVM 内存配置(根据服务器内存调整) # forge-admin: 主服务,分配最多内存 # forge-flow: 流程引擎,中等内存 # forge-app / forge-report: 可选服务,较小内存 JVM_OPTS_ADMIN="-Xms256m -Xmx384m" JVM_OPTS_FLOW="-Xms128m -Xmx256m" JVM_OPTS_APP="-Xms128m -Xmx256m" JVM_OPTS_REPORT="-Xms128m -Xmx256m" # 公共 JVM 参数(MySQL 3306、Redis 无密码、Flyway 关闭) COMMON_JVM_OPTS=" -Dspring.profiles.active=prod -Dspring.flyway.enabled=false -Dspring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/forge_admin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true -Dspring.datasource.dynamic.datasource.master.username=root -Dspring.datasource.dynamic.datasource.master.password=root -Dspring.data.redis.host=localhost -Dspring.data.redis.port=6379 -Dspring.data.redis.redisson.config=singleServerConfig: address: \"redis://localhost:6379\" database: 0 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 connectionPoolSize: 64 connectionMinimumIdleSize: 10 threads: 16 nettyThreads: 32 -Dhotel.alipay.app-id=9021000166699753 -Dhotel.alipay.private-key=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCe+dBsO8duk5JtE5hjFGpjPyIu2j9hEYTO+moxcvX/yzEDdICtOL3CVkIl/j8zL8/dys7NgIvI9irFwnFMlLipTEI1xClFNEU7LHzYqkBDv0+6ra/5n0eLgZXrYH5zR87IMeinOFrSJsN+eMolBrKmdo/N+J5pqB6HyhhY5GNizDAePfiYDpkOHpRf8ea+wRWv8W8l7ZwecKluiE+6lEnDu2fsWFVg6DUAx8iznVZp6lpLpnGXG/KBpRZf2BNrPjHET9uZzX0WONRwahaXWHXIMEBhl+I81lC9a7B0FXAkjtYCG05rEwCD2MVVEQuFGi1mWpUr0g4rzV7+WKNAtbllAgMBAAECggEBAIPvo9APlKXqh11LI+8mpFyVqtLjgjIXDfeQz80WMZ8GjTjm2VvpeWLtn5xUczMR/Rt/Ez5t7pTr5/eUNd9ulgq7JT/l+rJafRJtC3ftY8RV4990AlXSoNfgxgFAZfFaqPxwnzsYhBdg4GH38RvlgSKxxwsTyLS7OAtN6ALuGKWGrAaLAcKM36G3b8uR+NXHZYKipzjr+MnYTSPCeNMzWuNEuWoWcemslgQ43q4YgzDF2uU5K9O/iv4Nilchz4tKfXU0KYML2LtdnFWUsLIjTYbV8/GN9MXCcHWelLs+scsmIffBmLUBgUjuU9iXC0rnQCj+rhvC2aR504WIs0Qqg4kCgYEA3i16kLecE+AgOHYdh6N0QUEjsWlQ08P77RgmLwPbOyFtFRm51RNZmv0gWNtTL9OeTsU7gEd509O7GOeM2IQafjCW1Hb1G3FekITQStu9XNc5YHRylgO9HDSOVB1BkOFXnVagpGdoeRv3d68Kc4j40qAvI6wppnrJmtFZ7IX8Bc8CgYEAty1Jhx9J8nyEFH0MXtgf08YTTrweCAIdWHgpJ5F93Vxf+uMwA9ZQXtZVVAEviGC6ti1gC9fn763/CW5os1fnT3TgZElP0iX51IZaktCgTf69HodF+G9S6xcbbBa5c/V4UeE0Ouw+jgV7jwCKrzVOKGa9u7jUtS/AR+4XzAcuzosCgYBp7Wj4QnIpj7wM71OY7bdpvTLVTQ76SAB+w/rAg6gsgv1NCBzvl/Aq0vBvLPJ2ZQCfMa3ytSFCezpC33Lpb+Jps6TV23l1AhJB+PCOIEIiV4LFl/9hwpqRLgWF2QT/nFB3dWvVtm+6/jh4WX40I2Pul+yhp12cQAKKy7GB8Ud9RQKBgCxQoXw2Hp6ybwXB5u8/HBwQzHT838sSL+VKVLKE6U1XXsUEl4YmIBWBhu0myEgXFrSiL51N44fBsXSnqF7TAlvfq7W3Yr81fsZipqDkJhQYb8pl8ZCT5hyH35N7v+wE09IDSK6EnvGe8/B5shOHMtxlVruGkLcw0TTVrh4nErTXAoGBAK+q7n7GxvdZZJzXNr6RiAaQOHofykoCtCi77FoIRL7ysQpKMCxSgVbvZNvEG7SYNtcyqjJkpbI6CflIcwk2+E9CWmFMWrw35FND9gT5aSG5h04aYH5BPGfs8SrWPL8Ukq1CA0eiRyTF6+2p8OnhVPNsRxS3DjeLJDcuXj9NXEAN -Dhotel.alipay.alipay-public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhkUUNj/3YJGBsADPkkkRpDqmy0ak7XW1HTO/LNRE+/C2di7jEH3f4lRKfgFfuDpRiQZzEcj7HuN6WkbsFavhXXS0LCVy6+ZI1UWCUrwqQjFaYtzgDXP9lsilOrSalbV+pLpTEjPTFK+d4QRXKV6kHlycarbLaKRsMI+LpRkmHpLFupYPw1df3WAcXL1uIgDoCFN/banw9tq22/1R8yLMFDO5JJl61h2VkCyOIrJgE6ivy93O+wUrTvoOlBAfekXkkLgH+OZ6MIJM+/GKDcA2nXBb/fUdeKuoos2Flb/linL3oLAiiEJxdug+OF0GSBPUs4+FLrBUHUftmnsPfKhNaQIDAQAB -Dhotel.alipay.gateway-url=https://openapi-sandbox.dl.alipaydev.com/gateway.do -Dhotel.alipay.sandbox=true -Dhotel.alipay.notify-url=http://localhost:8580/hotel/open/pay/notify -Dhotel.qr.base-url=http://101.133.130.202 -Dhotel.qr.path=/r/ -Dhotel.pay.mock-enabled=true " # 各服务专属 JVM 参数 EXTRA_JVM_OPTS=( "${JVM_OPTS_ADMIN} -Dforge.flow.client.url=http://127.0.0.1:8081 ${COMMON_JVM_OPTS}" "${JVM_OPTS_FLOW} ${COMMON_JVM_OPTS}" "${JVM_OPTS_APP} ${COMMON_JVM_OPTS}" "${JVM_OPTS_REPORT} ${COMMON_JVM_OPTS}" ) # 日志目录 LOG_DIR=/var/log/forge ## ==================== 函数区 ==================== # 脚本提示信息 tips(){ echo "-------------------------------------" echo "" echo "Version:1.0" echo "Author:forge-admin" echo "Comment:Forge Admin 服务管理脚本" echo "" echo " 命令举例:sh forge-start.sh -start" echo " 启动参数:" echo " -status - 查看所有服务运行状态" echo " -start - 启动所有服务" echo " -stop - 停止所有服务" echo " -restart - 重启所有服务" echo " -admin - 重启主后台服务 (port 8580)" echo " -flow - 重启流程引擎服务 (port 8081)" echo " -app - 重启 App 接口服务 (port 8583)" echo " -report - 重启大屏报表服务 (port 8582)" echo "" echo "-------------------------------------" } # 初始化日志目录 init_log_dir(){ if [ ! -d "$LOG_DIR" ]; then mkdir -p "$LOG_DIR" fi } # 查看状态 status(){ echo "" echo "--------- 查看状态 开始执行 ... -----------" for((i=0;i<${#SERVICE_NAME[@]};i++)) do num=$((i+1)) service_name=${SERVICE_NAME[i]} service_port=${SERVICE_PORT[i]} service_pid=$(ps -ef | grep "$service_name" | grep -v grep | grep -v bash | awk '{print $2}') if [ -z "$service_pid" ]; then echo "--- 服务$num: 【$service_name】(port:$service_port) 未运行!!!" else echo "--- 服务$num: 【$service_name】(port:$service_port) PID:$service_pid 运行中..." fi done echo "--------- 查看状态 执行完毕 !!! -----------" echo "" } # 启动单个服务 start_service(){ local idx=$1 local service_name=${SERVICE_NAME[idx]} local service_path=${SERVICE_PATH[idx]} local service_package=${SERVICE_PACKAGE[idx]} local extra_opts=${EXTRA_JVM_OPTS[idx]} cd "$service_path" || return # 创建日志目录 init_log_dir TODAY=$(date +%Y-%m-%d) LOG_NAME="log-${service_name}-${TODAY}.txt" FULL_LOG_NAME="${LOG_DIR}/${LOG_NAME}" # 检查进程是否已存在 service_pid=$(ps -ef | grep "$service_name" | grep -v grep | grep -v bash | awk '{print $2}') if [ -n "$service_pid" ]; then echo "--- $service_name 进程已存在 (PID:$service_pid),无需启动" return fi echo "--- $service_name 开始启动 ..." echo "--- 服务目录:$service_path" echo "--- 启动包: $service_package" # 确保 JAVA_HOME 生效 source /etc/profile 2>/dev/null nohup java $extra_opts -jar "$service_package" > "$FULL_LOG_NAME" 2>&1 & # 等待进程启动 sleep 3 service_pid_new=$(ps -ef | grep "$service_name" | grep -v grep | grep -v bash | awk '{print $2}') if [ -n "$service_pid_new" ]; then echo "--- $service_name 启动成功!PID:$service_pid_new" echo "--- 日志文件:$FULL_LOG_NAME" else echo "--- $service_name 启动失败!请查看日志:$FULL_LOG_NAME" tail -20 "$FULL_LOG_NAME" fi } # 一键启动 start(){ echo "" echo "--------- 启动程序 开始执行 ... -----------" for((i=0;i<${#SERVICE_NAME[@]};i++)) do start_service $i sleep 2 done echo "--------- 启动程序 执行完毕 !!! -----------" echo "" } # 停止单个服务 stop_service(){ local idx=$1 local service_name=${SERVICE_NAME[idx]} service_pid=$(ps -ef | grep "$service_name" | grep -v grep | grep -v bash | awk '{print $2}') if [ -z "$service_pid" ]; then echo "--- $service_name 进程不存在,无需停止" else kill -9 "$service_pid" echo "--- $service_name (PID:$service_pid) 已停止" fi } # 一键停止 stop(){ echo "" echo "--------- 停止程序 开始执行 ... -----------" for((i=0;i<${#SERVICE_NAME[@]};i++)) do stop_service $i sleep 1 done echo "--------- 停止程序 执行完毕 !!! -----------" echo "" } # 一键重启 restart(){ echo "" echo "--------- 重启 开始执行 ... -----------" stop sleep 3 start sleep 1 status echo "--------- 重启 执行完毕 !!! -----------" echo "" } # 重启单个服务 reservice(){ local idx=$1 echo "--- 重启 ${SERVICE_NAME[idx]} ..." stop_service $idx sleep 2 start_service $idx } ## ==================== 入口 ==================== case "$1" in "-status") status ;; "-start") start ;; "-stop") stop ;; "-restart") restart ;; "-admin") reservice 0 ;; "-flow") reservice 1 ;; "-app") reservice 2 ;; "-report") reservice 3 ;; *) tips ;; esac exit 0