restart.sh 脚本是一个用于 Java 应用程序的重启脚本,支持以下功能:
主要功能
- 应用程序重启
- 自动停止现有的 Java 应用进程
- 启动新的 Java 应用实例
- 支持优雅停止和强制杀死进程
- 进程管理
- 通过进程名称查找并停止旧进程
- 设置停止超时时间(20秒)
- 如果优雅停止失败,会强制杀死进程
- 启动监控
- 启动后监控进程状态
- 设置启动超时时间(20秒)
- 启动成功/失败的状态反馈
配置支持
- Java 环境配置
- 优先使用
JAVA_HOME环境变量中的 Java - 如果未设置,则使用系统默认的
java命令
- 优先使用
- JVM 参数配置
- 内存设置:
-Xms4g -Xmx8g(初始4GB,最大8GB堆内存) - 垃圾回收: 使用 G1 垃圾收集器
- 错误处理: 支持堆转储配置(当前已注释)
- 系统属性: Spring 开发环境配置,端口9000
- 内存设置:
- 日志管理
- 应用输出日志:
./baseLogs/app.log - GC 日志:
./baseLogs/gc.log - 启动记录:
./baseLogs/startRecord.log - 错误转储目录:
./dump/
- 应用输出日志:
应用配置
- JAR 文件:
web-app-starter-2.2.0-SNAPSHOT.jar - 运行环境: Spring Boot 应用,开发环境
- 服务端口: 9000
- 进程标识: 通过 JAR 文件名识别进程
安全特性
- 使用
set -euo pipefail确保脚本在出错时立即退出 - 自动创建必要的目录
- 检查 JAR 文件是否存在
- 详细的日志记录和状态输出
这个脚本特别适用于 Spring Boot 应用的生产环境部署和维护,提供了完整的启停控制和监控功能。
#!/bin/bash
set -euo pipefail
APP_NAME="填写jar名称.jar"
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
JAR_PATH="${APP_DIR}/${APP_NAME}"
RUN_TAG="${APP_NAME}"
# JAVA_BIN 优先用 JAVA_HOME,否则用系统 java
if [ -n "${JAVA_HOME:-}" ] && [ -x "${JAVA_HOME}/bin/java" ]; then
JAVA_BIN="${JAVA_HOME}/bin/java"
else
JAVA_BIN="java"
fi
LOG_DIR="./baseLogs/"
DUMP_DIR="./dump/"
GC_LOG="${LOG_DIR}/gc.log"
# 如果无法启动可以在这里app.log 看下JVM无法创建虚拟机的信息
APP_OUT="${LOG_DIR}/app.log"
START_LOG="${LOG_DIR}/startRecord.log"
HEAP_OPTS="-Xms4g -Xmx8g"
GC_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC"
ERR_OPTS="" # "-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${DUMP_DIR} -XX:ErrorFile=${DUMP_DIR}/hs_err_pid%p.log -XX:+CreateMinidumpOnCrash"
SYS_PROPS="-Dspring.profiles.active=dev -Dserver.port=9000"
START_TIMEOUT=20
STOP_TIMEOUT=20
mkdir -p "${LOG_DIR}" "${DUMP_DIR}"
if [ ! -f "${JAR_PATH}" ]; then
echo "[$(date +'%F %T')] JAR 不存在: ${JAR_PATH}" | tee -a "${START_LOG}"
exit 1
fi
pids=$(pgrep -f "${RUN_TAG}" || true)
if [ -n "${pids}" ]; then
echo "[$(date +'%F %T')] 正在停止进程: ${pids}" | tee -a "${START_LOG}"
kill ${pids} || true
for i in $(seq 1 ${STOP_TIMEOUT}); do
sleep 1
still=$(pgrep -f "${RUN_TAG}" || true)
[ -z "${still}" ] && break
done
still=$(pgrep -f "${RUN_TAG}" || true)
if [ -n "${still}" ]; then
echo "[$(date +'%F %T')] 发送 KILL: ${still}" | tee -a "${START_LOG}"
kill -9 ${still} || true
fi
else
echo "[$(date +'%F %T')] 无需停止,未发现旧进程" | tee -a "${START_LOG}"
fi
echo "[$(date +'%F %T')] 开始启动 ${APP_NAME}" | tee -a "${START_LOG}"
nohup ${JAVA_BIN:-java} \
${HEAP_OPTS} ${GC_OPTS} ${ERR_OPTS} ${SYS_PROPS} \
-jar "${JAR_PATH}" \
>> "${APP_OUT}" 2>&1 &
new_pid=$!
echo "[$(date +'%F %T')] 启动中,PID=${new_pid}" | tee -a "${START_LOG}"
for i in $(seq 1 ${START_TIMEOUT}); do
if ps -p "${new_pid}" > /dev/null 2>&1; then
echo "[$(date +'%F %T')] 启动成功 PID=${new_pid}" | tee -a "${START_LOG}"
exit 0
fi
sleep 1
done
echo "[$(date +'%F %T')] 启动超时,检查日志 ${APP_OUT}" | tee -a "${START_LOG}"
exit 2
特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤
免责声明: 本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤
免责声明: 本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。
