使用进程构建器或Apache Commons Exec执行外部程序

3
我需要执行一个外部应用程序,该程序返回大量数据(需要超过2个小时才能完成),并且不断输出数据。我的需求是异步执行此程序,并将输出捕获到文件中。我尝试使用Java进程构建器,但它似乎会挂起并仅在程序退出或被强制终止时返回输出。我尝试使用进程构建器并生成一个新线程来捕获输出,但这也没有帮助。然后我了解了Apache Commons Exec,并尝试了相同的方法。但是,这似乎也需要很长时间,并返回不同的错误代码(对于相同的输入)。
CommandLine cmdLine = new CommandLine("/opt/testsimulator");

    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
    ByteArrayOutputStream stdout = new ByteArrayOutputStream();
    PumpStreamHandler psh = new PumpStreamHandler(stdout);
    ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
    Executor executor = new DefaultExecutor();
    executor.setStreamHandler(psh);
    executor.setWatchdog(watchdog);
    try {
        executor.execute(cmdLine);
    } catch (ExecuteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

任何帮助或工作示例都将非常有帮助。

从Java运行程序是一个硬性要求吗?在我看来,你应该只需从shell执行命令并将其输出导入到目标文件中。 - Perception
我使用ProcessBuilder完成了这个任务,注意处理输入流和错误流,并且没有遇到任何问题。也许你的程序有bug。 - Hovercraft Full Of Eels
如果有帮助到您,请记得接受下方的答案。 - Gray
1个回答

5

哦,使用ProcessBuilder应该适用于您的配置。例如,以下模式对我有效:

ProcessBuilder pb = new ProcessBuilder("/tmp/x");
Process process = pb.start();
final InputStream is = process.getInputStream();
// the background thread watches the output from the process
new Thread(new Runnable() {
    public void run() {
        try {
            BufferedReader reader =
                new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            is.close();
        }
    }
}).start();
// the outer thread waits for the process to finish
process.waitFor();

我正在运行的程序只是一个带有大量 sleep 1echo 行的脚本:

#!/bin/sh
sleep 1
echo "Hello"
sleep 1
echo "Hello"
...

从进程中读取的线程每秒钟输出一个Hello


谢谢,我的外部应用程序出了一些问题,因此进程生成器一直挂起。上面的代码完美地运行着。我还有一个问题。我想异步执行程序,但仍然将输出保存到文件中。如果我不使用process.waitFor(); 程序将在没有保存输出的情况下终止。有没有办法实现这个? - coder
你不需要记录 Process 的结果。如果进程完成后你忽略它,它应该会被垃圾回收。在我的例子中,线程没有标记为守护线程。如果主程序完成,则会等待线程完成。如果你不想等待,那么可以使用 thread = new Thread(...); thread.setDaemon(true); thread.start(); 模式。 - Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接