真实系统问题排查:解决 Java 服务在 Cron 下无法启动的问题
·
真实系统问题排查实战:拯救 “Java 服务无法在 Cron 下启动”的 Monitor 脚本
在生产环境中,我们经常会遇到这样一个场景:
每 5 分钟监控一次的
monitor.sh脚本,总是报“应用启动失败”,但是手动执行deploy.sh restart却完全正常。
今天就来记录一下我是如何定位、分析并彻底解决这个问题的。
一、问题现象
原始监控脚本 monitor.sh 很简单:
cd /opt/soft/robot-springboot
robot_proc=$(ps -ef | grep robot-springboot.jar | grep -v grep | awk '{print $2}')
if [[ -z "$robot_proc" ]]; then
sh deploy.sh restart
fi
通过 Cron 定时触发后,日志显示:
robot-springboot no exit
no java process
starting java process
Wait app to pass health check: 1...
...
Wait app to pass health check: 40...
app start failed
但是在同一台机器上,手动执行:
sh deploy.sh restart
却能顺利启动,健康检查返回 HTTP 200。
二、分析原因
对比手动执行与 Cron 执行的差异:
| 执行方式 | 现象 | 环境差异 |
|---|---|---|
| 手动执行 | 启动成功 | 登录 shell 已加载环境变量(JAVA_HOME、PATH) |
| Cron 或 monitor.sh 内调用 | 启动失败 | 环境变量缺失,Java 命令找不到 |
结论:问题不是脚本逻辑,而是 执行环境不一致。
Cron 和非交互 shell 默认不会加载 /etc/profile 或 ~/.bash_profile,导致 JAVA_HOME、PATH 丢失,java 命令不可用。
三、解决方案
最小改动方案:在 monitor.sh 顶部显式设置 Java 环境变量:
#!/bin/bash
export JAVA_HOME=/opt/java-8-openjdk
export PATH=$JAVA_HOME/bin:$PATH
然后保留原有逻辑:
cd /opt/soft/robot-springboot
robot_proc=$(ps -ef | grep robot-springboot.jar | grep -v grep | awk '{print $2}')
if [[ -z "$robot_proc" ]]; then
sh deploy.sh restart
fi
✅ 加上这两行后:
- Cron 执行也能找到
java - Monitor 脚本能正确判断进程是否存在
- Deploy 脚本启动成功,健康检查通过
四、经验总结
-
Cron 执行环境是干净的
- 不会自动加载
.bash_profile/.bashrc - 很多命令可能找不到
- 不会自动加载
-
Java 服务监控常见坑
monitor.sh脚本调用deploy.sh启动失败- 健康检查一直超时
-
最佳实践
- 在脚本顶部显式设置
JAVA_HOME和PATH - 关键命令尽量使用绝对路径
- 日志统一输出到文件,便于排查
- 在脚本顶部显式设置
-
调试技巧
- 先手动执行脚本确认逻辑正常
- 在 Cron 环境下打印
$PATH和$JAVA_HOME - 用绝对路径测试
java -version
五、最终日志效果
monitor start...
:robot-springboot
robot-springboot no exit
no java process
starting java process
started java process
checking http://127.0.0.1:8140/spring/healthy/check
Wait app to pass health check: 1...
...
code is 200
check http://127.0.0.1:8140/spring/healthy/check success
monitor end ...
一切恢复正常,Cron 定时任务完全稳定运行。
六、总结
这次实战告诉我们:
很多系统问题,并不是业务逻辑错,而是环境不一致导致的“假死”现象。
在生产环境中,尤其是监控、定时任务场景下,显式声明依赖环境比依赖用户登录环境更可靠。
更多推荐



所有评论(0)