简体   繁体   English

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

[英]How to Exit a Process (.exec()) if the External Program hangs

Let me explain my software.让我解释一下我的软件。 What my software simply does is that it creates 10 threads and assigns a number of tasks to each thread.我的软件所做的只是创建 10 个线程并为每个线程分配多个任务。 Each thread then creates a Runtime Process that will start a cmd batch file which in turn will start a program that will telnet to a device (I have about 200 of them) to poll its configuration.然后每个线程创建一个运行时进程,该进程将启动一个 cmd 批处理文件,该文件又将启动一个程序,该程序将 telnet 到设备(我有大约 200 个)以轮询其配置。 Here is the code for my process creation:这是我的流程创建代码:

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

batchFile is the full path of the batch file. batchFile是批处理文件的完整路径。 Don't get me wrong, the software works fine up to 100% of the execution and it hanged ONLY ONE TIME at about 95%, so I'm trying to find a solution for that.不要误会我的意思,该软件在执行 100% 的情况下都可以正常工作,并且在 95% 左右挂起一次,所以我正在尝试为此找到解决方案。 Why it hanged is not my issue now, but rather how to deal with hangups later on..!为什么它挂起不是我现在的问题,而是以后如何处理挂机..!

Now the problem is that I need to wait for the process to finish because my telnet client will write to a file that I will read later on in the thread;现在的问题是我需要等待进程完成,因为我的 telnet 客户端将写入我稍后将在线程中读取的文件; and hence the use of the .waitFor() .因此使用.waitFor() My question is how can I get the thread to understand that the external program hanged?我的问题是如何让线程理解外部程序挂了? In other words, can I give the external program some time limit to finish;换句话说,我可以给外部程序一些时间限制来完成吗? and if it does not the thread will kill the process?如果不是,线程会杀死进程吗?

Also I have read about reading the error and output streams;我还阅读了有关读取错误和输出流的内容; however, I don't think it is applicable here, or is it?但是,我认为它不适用于这里,是吗?

Also I have read about reading the error and output streams;我还阅读了有关读取错误和输出流的内容; however, I don't think it is applicable here, or is it?但是,我认为它不适用于这里,是吗?

Almost certainly yes, it is applicable.几乎可以肯定,它是适用的。 Try using ProcessBuilder instead of Runtime.exec and read all the output before calling waitFor .尝试使用ProcessBuilder而不是Runtime.exec并在调用waitFor之前读取所有输出。 For example (exception handling omitted, in particular waitFor may throw InterruptedException before the process actually exited)例如(省略异常处理,特别是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 and NullOutputStream are from Apache commons-io ). (IOUtils 和 NullOutputStream 来自Apache commons-io )。

To answer the actual question in the title, if your process still hangs even after properly reading its output, you may need to use p.destroy() to forcibly terminate the process.要回答标题中的实际问题,如果您的进程即使在正确读取其输出后仍然挂起,您可能需要使用p.destroy()强行终止该进程。 You could define a timer task something like你可以定义一个类似的计时器任务

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

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

and then do然后做

    // 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();

This will cause the process to be killed if it has been running for more than 30 seconds (adjust the schedule call to change the timeout).如果进程已经运行超过 30 秒,这将导致进程被终止(调整schedule调用以更改超时)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM