Java程序手动及shell调用正常,crontab执行无法写入输出文件求助
crontab定时执行Java程序输出文件为空的解决方案
核心原因
- crontab运行时的环境变量PATH和交互式登录shell的PATH不一致,找不到
util_mem_usage、java这类自定义/非系统默认路径的命令 - Java代码中的进程处理逻辑错误,硬等待10秒后强制销毁进程,可能命令还没完成输出写入就被终止,同时错误流读取逻辑不生效,无法捕获报错信息
修复步骤
第一步:补全所有命令的绝对路径
首先在交互式终端执行以下命令获取对应程序的绝对路径:
把返回的路径替换到所有用到对应命令的位置:which util_mem_usage which java which bash which tee- 修改shell脚本
hb_execute_bridge_util_mem_usage.sh,把java改成绝对路径:
#!/bin/bash # 替换成你自己的java绝对路径,示例为/usr/bin/java /usr/bin/java -classpath /home/jcb/bridge/heartbeat/ojdbc6.jar:. hb_bridge_util_mem_usage- 修改Java代码中的ProcessBuilder命令,所有命令都用绝对路径:
// 替换成你实际的util_mem_usage、bash、tee的绝对路径 processBuilder.command("/bin/bash", "-c", "/your/path/to/util_mem_usage | /usr/bin/tee /home/jcb/bridge/heartbeat/hb_bridge_util_mem_usage.txt");- 修改shell脚本
第二步:修正Java进程处理逻辑
删掉硬等待sleep和主动销毁进程的逻辑,改为等待进程自然执行结束,同时完善流读取逻辑避免进程阻塞、丢失报错:ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command("/bin/bash", "-c", "/your/path/to/util_mem_usage | /usr/bin/tee /home/jcb/bridge/heartbeat/hb_bridge_util_mem_usage.txt"); // 合并错误流和输出流,避免进程因为流满阻塞 processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); // 读取所有进程输出,避免阻塞 try (InputStream inputStream = process.getInputStream()) { byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { System.out.write(buffer, 0, len); } } // 等待进程执行完成,获取退出码 int exitCode = process.waitFor(); System.out.println("命令执行退出码:" + exitCode); // 只有需要超时中断的场景才主动调用destroy,正常执行不需要主动销毁进程第三步:给crontab添加日志,方便排查问题
修改crontab条目,把执行输出全部写入日志文件:
后续如果还有问题,直接查看对应日志文件就能看到具体报错信息。*/2 * * * * (cd /home/jcb/bridge/heartbeat/; ./hb_execute_bridge_util_mem_usage.sh >> /home/jcb/bridge/heartbeat/cron_run.log 2>&1) */5 * * * * (cd /home/jcb/bridge/heartbeat/; ./hb_bridge_status_cron.sh >> /home/jcb/bridge/heartbeat/cron_status.log 2>&1)
内容的提问来源于stack exchange,提问作者Barry Brierley
相关产品推荐
相关产品推荐

