使用 Supervisor 监控 Java 进程并在进程关闭时自动调用 Shell 脚本重启,是一种可靠的方案。以下是详细配置步骤:
1. 安装 Supervisor
如果尚未安装,在 Linux 系统上执行:
sudo apt update && sudo apt install supervisor -y # Debian/Ubuntu
sudo yum install supervisor -y # CentOS/RHEL
安装后启动并设置开机自启:
sudo systemctl enable supervisor
sudo systemctl start supervisor
2. 编写 Shell 脚本(用于监控 Java 进程)
创建脚本(如 /opt/scripts/monitor_supervisor_zsba_java.sh):
#!/bin/bash
# 配置项
JAVA_PROCESS_NAME="bidding-zsbayy/jar/one-main-0.0.1-SNAPSHOT.jar"
LOG_FILE="/var/log/bidding_supervisor_zsbayy_java_monitor.log"
RESTART_SCRIPT="/home/bid/bidding-zsbayy/one.sh"
APP_PORT=9691 # 您的Java应用端口
MAX_START_TIME=180 # 3分钟启动超时(单位:秒)
HEALTH_CHECK_INTERVAL=30 # 健康检查间隔(秒)
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# 健康检查(通过端口检测)
is_fully_started() {
if netstat -tlnp | grep -w "$APP_PORT" | grep -q java; then
return 0
fi
return 1
}
# 主监控循环
log "启动监控守护进程(最大启动等待时间:${MAX_START_TIME}秒)..."
while true; do
if ! pgrep -f "$JAVA_PROCESS_NAME" > /dev/null; then
log "检测到Java进程停止,开始重启..."
start_time=$(date +%s)
# 异步启动Java进程
"$RESTART_SCRIPT" start >> "$LOG_FILE" 2>&1 &
# 等待启动完成
while [ $(($(date +%s) - start_time)) -lt $MAX_START_TIME ]; do
if is_fully_started; then
log "Java进程启动成功(耗时 $(( $(date +%s) - start_time )) 秒)"
break
fi
sleep 5
done
# 超时处理
if ! is_fully_started; then
log "警告:Java进程启动超时(超过 ${MAX_START_TIME} 秒)"
pkill -f "$JAVA_PROCESS_NAME"
fi
else
# 进程存在时的健康检查
if ! is_fully_started; then
log "检测到异常状态(进程存在但端口未监听),尝试恢复..."
pkill -f "$JAVA_PROCESS_NAME"
fi
fi
sleep $HEALTH_CHECK_INTERVAL
done
赋予执行权限:
sudo chmod +x /opt/scripts/monitor_supervisor_zsba_java.sh
3. 配置 Supervisor 监控
创建配置文件(如 /etc/supervisor/conf.d/java_app.conf):
[program:java_app]
command=/opt/scripts/monitor_supervisor_zsba_java.sh # 指定你的脚本路径
autostart=true # 随 Supervisor 启动
autorestart=true # 自动重启(脚本退出时)
startsecs=300 # 启动等待时间(秒)
startretries=3 # 启动失败重试次数
stderr_logfile=/var/log/java_app_err.log # 错误日志
stdout_logfile=/var/log/java_app_out.log # 输出日志
user=your_user # 运行用户(建议非 root)
environment=JAVA_HOME="/usr/java/jdk17" # 可选:指定 Java 环境
4. 应用配置并启动
sudo supervisorctl reread # 重新加载配置
sudo supervisorctl update # 更新任务
sudo supervisorctl start java_app # 启动监控
可能的错误:
root@localhost:/etc/supervisor/conf.d# tail -f /var/log/supervisor/supervisord.log 2025-05-09 10:30:40,748 INFO gave up: java_zsbbyy_admin_app entered FATAL state,
too many start retries too quickly 2025-05-09 10:33:45,034 INFO spawned:
'java_zsbbyy_admin_app' with pid 140577
查看 supervisord.log 获取详细错误:
sudo tail -f /var/log/supervisor/supervisord.log
monitor_supervisor_zsba_java.sh 配置的状态直接退出了!
5. 验证 Supervisor 状态
sudo supervisorctl status java_app # 查看Supervisor进程状态
tail -f /var/log/java_app_out.log # Supervisor监控日志
6. 检查监控脚本产生的日志
tail -f /var/log/bidding_supervisor_zsbayy_java_monitor.log # 查看监控脚本产生的日志
关键点说明
-
进程匹配逻辑
- 脚本中的
ps -ef | grep需确保能唯一匹配到你的 Java 进程(避免误判)。 - 更精准的方式:使用
pgrep -f "your-java-app.jar"。
- 脚本中的
-
Supervisor 重启机制
- 若脚本执行后退出(即使 Java 进程启动成功),Supervisor 会因
autorestart=true重复触发脚本。 - 解决方案:脚本末尾添加
sleep 1或让脚本常驻(如tail -f /dev/null)。
- 若脚本执行后退出(即使 Java 进程启动成功),Supervisor 会因
-
资源限制(可选)
在 Supervisor 配置中添加:stopsignal=TERM # 停止信号 stopwaitsecs=30 # 等待停止超时 priority=100 # 优先级
替代方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| Supervisor | 轻量、配置简单 | 需手动处理进程匹配 |
| systemd | 原生支持、功能强大 | 学习曲线较陡 |
| cron + 脚本 | 无需额外工具 | 监控延迟(分钟级) |
常见问题
-
问题1:Supervisor 报错
BACKOFF (Exited too quickly)
解决:检查脚本是否有执行权限,或添加sleep防止立即退出。 -
问题2:Java 进程启动但 Supervisor 仍重启
解决:确保脚本持续运行(如末尾加while true; do sleep 60; done)。
按此配置后,Supervisor 会持续监控 Java 进程状态,异常时自动调用脚本恢复服务。