System.exit(状态代码)或从Java返回错误代码的最佳实践的任何替代方法
我们有一个Java作业,它是通过Shell脚本实用程序触发的。计划定期运行 现在,shell脚本需要一个退出代码,以防作业失败,从而触发其他报警点。因此,在我们的主类中有System.exit(STATUS_CODE),当发生任何异常时,它在catch块中被调用。主要方法如下所示。我们用的是弹簧。我们还在记录器中配置了smtp,以便通过电子邮件发送所有错误级别日志。现在,我们注意到System.exit在退出JVM时突然停止记录器和其他线程。因此,我们添加了一个Thread.sleep(10000),以便在调用System.exit之前完成任何日志记录 这是从java向脚本发送错误状态代码的最佳方式吗?我们可以不使用System.exit调用发送状态吗?当需要System.exit时(shudownhook…),是否有任何最佳实践或建议?Spring中有没有其他方法在DI容器退出时发送错误代码System.exit(状态代码)或从Java返回错误代码的最佳实践的任何替代方法,java,spring,Java,Spring,我们有一个Java作业,它是通过Shell脚本实用程序触发的。计划定期运行 现在,shell脚本需要一个退出代码,以防作业失败,从而触发其他报警点。因此,在我们的主类中有System.exit(STATUS_CODE),当发生任何异常时,它在catch块中被调用。主要方法如下所示。我们用的是弹簧。我们还在记录器中配置了smtp,以便通过电子邮件发送所有错误级别日志。现在,我们注意到System.exit在退出JVM时突然停止记录器和其他线程。因此,我们添加了一个Thread.sleep(1000
private static Logger LOG = LoggerFactory.getLogger(Application.class);
public static void main(final String[] args) throws InterruptedException {
LOG.info("Starting Timeout Service...");
try {
final AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
final SomeBean somebean = ctx.getBean(SomeBean.class);
somebean.doSomething();
} catch (final Exception exception) {
LOG.error(exception.getMessage(), exception);
waitForLogToProcessAndExit();
}
LOG.info("Timeout Service Completed");
}
private static void waitForLogToProcessAndExit() throws InterruptedException {
Thread.sleep(10000); //Waiting for any logging to complete before firing System.exit
System.exit(1);
}
为什么不在调用
System.exit
之前简单地执行所有报告/错误处理?
据我所知,除了使用System.exit()
由于logger可能使用单独的线程发送电子邮件,因此您可能需要等待它真正发送,或者实现电子邮件服务,从某种队列中提取要发送的消息,并将其运行到您的进程旁边(我认为这是最好的选择,因为它可以用于将来需要此类解决方案的每个组件).(旁注:您可以使用TimeUnit.SECONDS.sleep(10)
,而不是Thread.sleep(10000)
)
这里的“bug”可能是记录器使用守护进程线程;当JVM退出时,它不会等待这些线程完成。直接的结果是,如果线程在System.exit()
之前未能发送邮件,则您没有邮件
解决办法:
- 通过谷歌搜索,我发现,至少在log4j中,如果您有对appener的引用,
在退出之前将其删除:它将确保刷新队列中的所有消息;或者,您可以首先将appender配置为不使用守护进程线程.close()
- 只需使用普通的
和适当的cron
并登录到stdout:MAILTO
默认情况下将stdout和stderr的内容邮寄到给定的邮件地址cron
main()
抛出的异常将使JVM退出,1您可以使用finally block,对不起。为什么不检查spring批处理的CommandLineJobRunner.class呢。它已经用退出代码实现了命令执行器。