Linux 安全重启 Java JAR:优雅停止、PID 管理与启动检查
· 阅读需 2 分钟
在 Linux 服务器上部署可执行 JAR 后,经常需要通过脚本完成停止、启动和重启。一个可靠的重启脚本应避免误杀其他 Java 进程,并优先让应用优雅退出。
基础重启脚本
下面以 test-1.0.jar 为例:
#!/usr/bin/env bash
APP_NAME="test-1.0.jar"
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="$APP_DIR/run.log"
PID_FILE="$APP_DIR/app.pid"
cd "$APP_DIR" || exit 1
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if kill -0 "$PID" 2>/dev/null; then
echo "Stopping $APP_NAME, PID=$PID"
kill "$PID"
for i in $(seq 1 30); do
if ! kill -0 "$PID" 2>/dev/null; then
break
fi
sleep 1
done
if kill -0 "$PID" 2>/dev/null; then
echo "Graceful shutdown timed out, forcing stop"
kill -9 "$PID"
fi
fi
rm -f "$PID_FILE"
fi
nohup java \
-server \
-Xms512m \
-Xmx512m \
-jar "$APP_NAME" \
--spring.profiles.active=test \
>> "$LOG_FILE" 2>&1 &
NEW_PID=$!
echo "$NEW_PID" > "$PID_FILE"
sleep 2
if kill -0 "$NEW_PID" 2>/dev/null; then
echo "Started successfully, PID=$NEW_PID"
else
echo "Start failed, check $LOG_FILE"
exit 1
fi
保存为 restart.sh 后添加执行权限:
chmod +x restart.sh
./restart.sh
为什么使用 PID 文件
使用 ps | grep 按名称查找进程可能匹配到多个程序,也可能匹配到命令本身。启动时把 $! 写入 PID 文件,可以准确记录当前脚本启动的进程。
不过,PID 可能在程序异常退出后被系统复用。因此脚本执行前还应结合应用目录、启动参数或服务管理器进一步确认。
为什么不直接使用 kill -9
kill PID 默认发送 SIGTERM,Java 应用可以执行关闭钩子,释放端口、关闭线程池并处理尚未完成的任务。
kill -9 会立即终止进程,应用没有清理资源的机会,所以只应作为优雅停止超时后的最后手段。
查看启动日志
tail -f run.log
如果启动失败,可以重点检查:
- JAR 文件名称和工作目录是否正确。
- Java 版本是否满足应用要求。
- 服务端口是否被其他进程占用。
spring.profiles.active指定的配置是否存在。- 当前用户是否具有目录和日志文件写入权限。
生产环境建议
长期运行的 Java 服务更适合交给 systemd、Supervisor 或容器平台管理。这些工具支持开机启动、失败重启、日志管理和服务状态检查,比手写脚本更容易维护。