我继承了Java Web服务代码库(BEA / Oracle Weblogic),需要从Web服务启动/启动外部后台应用程序。
我已经尝试过了:
ProcessBuilder pb = new ProcessBuilder(arg);
pb.start();
以及:
Runtime.exec(cmdString);
但是在以这种方式启动应用程序时遇到了奇怪的行为(即,即使进程仍处于活动状态,启动的应用程序也会停止工作。 - 从正常命令行手动运行时,应用程序正常工作。)
有没有更好的方法来启动外部流程?
编辑:----------------------
我有一些额外的信息可能有助于解决这个问题。
waitfor()
)将不是理想的情况。我已经成功了,其中外部应用程序作为后台进程启动(使用“&”)。
#!/bin/bash
java -jar myApp.jar &
这显然会创建一个孤立的进程,但至少应用程序会继续执行。
答案 0 :(得分:2)
首先,这是在Windows或Linux上发生的吗?此外,推出的应用程序应该或多或少做什么? (它是一个脚本吗?它是二进制文件吗?它是你的二进制文件吗?)
修改强>
好的,所以启动一个bash
脚本(使用ProcessBuilder
),然后生成一个新的JVM(java -jar myApp.jar
)。
当您尝试使用ProcessBuilder
直接生成新的JVM 时会发生什么?你最初说:
启动的应用程序停止工作
bash
脚本?ProcessBuilder
方法(以及以何种顺序)的确切和完整参数(及其值)是什么? (例如提供带注释的代码)lsof
,那么在运行时会显示哪个文件与文件描述符2(查看FD
列)相关联:lsof -p 1234
(其中{ {1}}是“挂起”JVM的进程ID?)在这里附加1234
命令的整个输出可能会很有趣。lsof
(其中kill -QUIT 1234
是进程ID “挂”JVM?)答案 1 :(得分:2)
通过“即使进程仍处于活动状态也停止工作”我假设您可能期望从已启动的应用程序获得一些输出而没有得到任何结果。
尝试使用以下内容:
ProcessBuilder pb = new ProcessBuilder(arg);
Process p = pb.start();
p.waitFor();
waitFor()会导致当前线程等待,如果有必要,直到此Process对象表示的进程终止。
http://java.sun.com/javase/6/docs/api/java/lang/Process.html#waitFor()
答案 2 :(得分:2)
简单地说:如果启动的应用程序写入SDTOUT / STDIN并且您不经常刷新它们(请参阅Process.getErrorStream / Process.getInputStream),那么进程将在缓冲区已满时阻塞(这非常小,4KB或更少)。
我建议您在启动进程之前调用ProcessBuilder.redirectErrorStream()。然后,在此之后,使用run()方法创建一个线程:
public void run() {
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
答案 3 :(得分:1)
您是否正确处理过程的标准输入和输出?如果您的应用程序正在处理标准输入或输出,并且您没有正确处理它,那么您执行的进程将等待I / O.
测试方法是编写一个运行程序的脚本,将标准输入,输出和错误重定向到文件。然后让您的Web服务应用程序运行脚本而不是程序。如果程序以这种方式运行完成,则问题是处理过程的输出。
答案 4 :(得分:0)
我猜测问题可能是启动进程的线程在请求结束后获得TERMINATED或其他任何内容。尝试在应用程序中使用单个线程,确保始终保持活动状态,您可以通过从其他线程调用它来启动进程。