java - 如果外部程序挂起,如何退出进程 (.exec())

标签 java process runtime.exec process-exit

让我解释一下我的软件。我的软件所做的只是创建 10 个线程并为每个线程分配一些任务。然后每个线程创建一个运行时进程,它将启动一个 cmd 批处理文件,该批处理文件又将启动一个程序,该程序将远程登录到一个设备(我有大约 200 个)以轮询其配置。这是我的流程创建代码:

Process p1 = java.lang.Runtime.getRuntime().exec("cmd /c  start /b /wait " + batchFile); 
int returnVal = p1.waitFor();

batchFile 是批处理文件的完整路径。不要误会我的意思,该软件在 100% 的执行时都可以正常工作,并且它在大约 95% 时挂起只有一次,所以我正在尝试为此寻找解决方案。为什么它挂起现在不是我的问题,而是以后如何处理挂起......!

现在的问题是我需要等待进程完成,因为我的 telnet 客户端将写入一个文件,稍后我将在线程中读取该文件;因此使用了 .waitFor() 。我的问题是如何让线程了解外部程序已挂起?换句话说,我可以给外部程序一些时间限制来完成吗?如果不是,线程将终止进程?

我还阅读了有关读取错误和输出流的内容;但是,我认为它不适用于这里,是吗?

最佳答案

Also I have read about reading the error and output streams; however, I don't think it is applicable here, or is it?

几乎可以肯定,它是适用的。尝试使用 ProcessBuilder 而不是 Runtime.exec 并在调用 waitFor 之前读取所有输出。例如(省略了异常处理,特别是 waitFor 可能会在进程实际退出之前抛出 InterruptedException)

    ProcessBuilder pb = new ProcessBuilder(
        "cmd", "/c", "start", "/b", "/wait", batchFile);
    pb.redirectErrorStream(true);
    Process p = pb.start();
    IOUtils.closeQuietly(p.getOutputStream());
    IOUtils.copy(p.getInputStream(), System.out);
    // or alternatively throw away the output using
    // IOUtils.copy(p.getInputStream(), NullOutputStream.NULL_OUTPUT_STREAM);
    IOUtils.closeQuietly(p.getInputStream());
    int returnVal = p.waitFor();

(IOUtils 和 NullOutputStream 来自 Apache commons-io)。

要回答标题中的实际问题,如果您的进程在正确读取其输出后仍然挂起,您可能需要使用 p.destroy() 强制终止该进程。您可以定义一个计时器任务,例如

    public class TimeoutProcessKiller extends TimerTask {
      private Process p;
      public TimeoutProcessKiller(Process p) {
        this.p = p;
      }

      public void run() {
        p.destroy();
      }
    }

然后做

    // single shared timer instance
    Timer t = new Timer();

    // for each device
    Process p = pb.start();
    TimerTask killer = new TimeoutProcessKiller(p);
    t.schedule(killer, 30000);
    // ... read output stream as before ...
    int returnVal = p.waitFor();
    killer.cancel();

如果进程运行超过 30 秒,这将导致进程被终止(调整 schedule 调用以更改超时)。

关于java - 如果外部程序挂起,如何退出进程 (.exec()),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14483397/

相关文章:

java - getRuntime().exec(<命令>) : <command> not working

java - 从 Java 启动 OpenOffice 服务 (soffice) 时出现问题(命令在命令行中运行,但不能从 Java 运行)

java - conwert 对象,其中包含 utf-8 的字符串到具有正确编码的字符串

java - 事件源 : Short way to fire event

java - 通过即时获取每月的第一天和最后一天

java - 在 lombok 中为 @singular 列表设置 null 或为空

c++ - C++ 中的 Linux 进程加载器

c# - 从调用进程获取命令行

java - 如何使用 Java 启动 Windows `runas` 进程?

java - 从另一个 java 程序运行 java 程序