如何监视ProcessBuilder运行的外部进程?

问题描述:

这应该很简单,但我在JavaDocs中看不到任何有用的东西。如何监视ProcessBuilder运行的外部进程?

我需要的是从我的Java代码运行一些外部进程,然后能够监视此进程是否已关闭。换句话说,我希望能够可靠地确定我的外部流程是否未被用户结束。

如果不存在跨平台解决方案,我会接受在Linux下工作的任何东西。

我的代码当前片段:

public static void main(String[] args) { 
    ProcessBuilder pb = new ProcessBuilder("some proces name"); 

    try { 
     Process p = pb.start(); 
     // p.isRunning(); <- now, that would be helpful :-) 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+0

你是什么意思“关机”与“未由用户结束”。你在谈论错误代码还是其他一些输出? – Gray 2012-07-16 18:37:24

+0

那么,说“由用户结束”可能确实没那么准确。我真正想知道的是,如果这个过程仍然在任何时候运行。 – 2012-07-16 18:45:41

启动一个新线程它要求Process.waitFor()并设置一个标志时调用返回。那么,只要您想查看过程是否已完成,您就可以检查该标志。

public class ProcMon implements Runnable { 

    private final Process _proc; 
    private volatile boolean _complete; 

    public boolean isComplete() { return _complete; } 

    public void run() { 
    _proc.waitFor(); 
    _complete = true; 
    } 

    public static ProcMon create(Process proc) { 
    ProcMon procMon = new ProcMon(proc); 
    Thread t = new Thread(procMon); 
    t.start(); 
    return procMon; 
    } 
} 

(省略了一些样板)。

我不知道我理解的问题,但要做到这一点的一种方法是调用process.exitValue();。它抛出一个异常,如果进程尚未终止:

/** 
* Returns the exit value for the subprocess. 
* 
* @return the exit value of the subprocess represented by this 
*   <code>Process</code> object. by convention, the value 
*   <code>0</code> indicates normal termination. 
* @exception IllegalThreadStateException if the subprocess represented 
*    by this <code>Process</code> object has not yet terminated. 
*/ 
abstract public int exitValue(); 

如果你不介意一个黑客,你可以这样做,如果你是它使用UNIXProcess类〜Unix系统的工作如下。这确实然而使用反射:

ProcessBuilder pb = new ProcessBuilder("/bin/sleep", "5"); 
Process process = pb.start(); 
// open accessability of the UNIXProcess.hasExited field using reflection 
Field field = process.getClass().getDeclaredField("hasExited"); 
field.setAccessible(true); 
// now we can get the field using reflection 
while (!(Boolean) field.get(process)) { 
    ... 
} 
+0

想过它,但这听起来有点像API'滥用'。我想知道过程是否正在运行,而不是过程终止没有发生。我知道它应该是相同的,但老实说,我期待一些API组件,它将采用现有的'Process'实例,并且可以提供有关在该进程中运行的线程状态的一些额外的元数据。 – 2012-07-16 18:49:33

+0

@ŁukaszBachman我不会认为这是API“滥用”。全部是非布尔条件。我还添加了一种方法来获得'hasExited'内部值,但它是一种使用反射的黑客。 – Gray 2012-07-16 18:51:00

+0

我会用'waitFor()',但是+1反思想法。 – 2012-07-16 18:57:42

根据问题的具体代码段我可能是添加,自1.8 Process类有一个isAlive()方法是可行的

文档链接有用:https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html

好运,任何阅读!