如何在tomcat关闭时杀死Java生成的子进程
我为JIRA(一个在tomcat中运行的web应用程序)编写了一个服务,它定期运行(比如1小时)。基本上,服务通过runtime.exec(command)执行一个系统命令,并解析命令生成的输出,然后用它更新Lucene索引,输出将是巨大的 问题是: 1) 如果在执行上述服务时使用如何在tomcat关闭时杀死Java生成的子进程,java,tomcat,process,jvm,shutdown,Java,Tomcat,Process,Jvm,Shutdown,我为JIRA(一个在tomcat中运行的web应用程序)编写了一个服务,它定期运行(比如1小时)。基本上,服务通过runtime.exec(command)执行一个系统命令,并解析命令生成的输出,然后用它更新Lucene索引,输出将是巨大的 问题是: 1) 如果在执行上述服务时使用shutdown.sh关闭tomcat,则不会终止java(或catalina)进程。java和子进程都存在一段时间,也就是说,直到系统命令完成&服务处理输出。但是服务无法更新索引,使索引处于不一致的状态 如果在上述服
shutdown.sh
关闭tomcat,则不会终止java(或catalina)进程。java和子进程都存在一段时间,也就是说,直到系统命令完成&服务处理输出。但是服务无法更新索引,使索引处于不一致的状态
如果在上述服务未运行时关闭tomcat,则一切正常。我想。我仍然不清楚为什么JVM不会关闭,因为上面的服务正在tomcat中运行
请注意,这是该机器上运行的唯一java应用程序
2) 然后,如果我使用kill
杀死java,java和子进程都会被杀死,这与
这是因为子进程正在向父进程(java)发送输出,一旦父进程被终止,子进程就不知道向何处发送输出,因此被终止
3) 我试着按解释使用,但这对我不起作用。shutdownhook
中的代码只有在java和子进程完成工作后才能执行。因此,在shutdownhook中调用process.destroy()
,在这里是没有用的
这似乎很明显,因为在我的例子中JVM仍然在运行,所以它不会调用shutdownhooks,直到它开始它的关闭序列。我不知道这对另一个人是如何工作的,我的意思是,为什么java产生的子进程在JVM关闭时仍在运行
4) 如果重新启动tomcat,将生成具有不同pid的新java进程
当tomcat关闭时,是否可以通过编程方式停止子进程
如果我不清楚我的解释,请告诉我
以下是执行系统命令的代码:
String command = getCommand();
File view = new File(viewPath);
Runtime runtime = Runtime.getRuntime();
try
{
final Process process = runtime.exec(command, null, view);
StreamReader errorStreamReader = new StreamReader(process
.getErrorStream());
Thread errorStreamThread = new Thread(errorStreamReader);
errorStreamThread.start();
revisions = parseRevisionLogs(process.getInputStream());
process.waitFor();
process.getInputStream().close();
process.getErrorStream().close();
process.getOutputStream().close();
}
您正在对流程执行waitFor()操作吗
如果是这样的话,您可以捕获到中断异常,并执行
p.destroy()
我建议您执行以下操作
不要直接从java读取进程的输出。相反,将输出重定向到文件,并在进程终止时从那里读取。使用存储单独进程PID的批处理文件或shell脚本包装您的命令,以便能够单独终止此进程。现在将shutdownhook添加到tomcat,它将运行killPID
,其中PID是单独进程的进程ID
我相信这会起作用,因为现在您的tomcat和单独的进程完全解耦了,所以没有什么会让tomcat关闭。过程也是如此
祝你好运。除非剩下的线程被标记为“守护进程”,否则JVM不会关闭。任何非守护进程用户线程都必须在JVM退出之前完成。看见如果没有使用
setDaemon(true)
设置定期任务,则必须在JVM退出之前完成这些任务。在进程开始之前,必须调用setDaemon
您应该能够使您的定期任务成为守护进程,但是JVM关闭时确实存在争用条件。您可以考虑在进程中读取一个守护进程任务,但是拥有一个非守护进程任务,可以更新索引,该索引在工作时可能不会被杀死。
然后,非守护进程线程可能正在休眠,等待加载完成,并测试它是否应以
volatile boolean
字段或其他信号终止。能否显示定期任务是如何创建的?上述代码块将定期执行,由哪个线程执行该代码?主线?那么我的答案就站得住脚了。进程没有停止的原因是主线程不是守护进程线程,它正在从进程中读取数据。您需要在守护进程线程中运行该处理,并且在更新索引时小心它是否被终止。或者你可以做一些类似于@AlexR answer的事情,然后处理一个文件。这个解释让我想到了实际发生的事情。。。将进行一些实验,然后返回。在接收并解析输出之前,程序不会向索引写入任何内容。似乎将系统命令作为守护进程运行可以解决这个问题,但我不知道如何将进程作为守护进程,setDaemon(true)
用于线程?是的,您需要生成另一个线程,并在它启动之前调用setDaemon(true)
。然后,您的main需要监听tomcat的关闭