首页 > 解决方案 > 如何使shell命令过程完成?

问题描述

我想在带有 Java 的 Linux 机器上执行特定的 shell 命令。所以我找到了来自 baeldung.com 的教程。

链接到教程

我的问题是,即使是示例命令(进程)也永远不会完成。

private static class StreamGobbler implements Runnable {
    private InputStream inputStream;
    private Consumer<String> consumer;

    public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
        this.inputStream = inputStream;
        this.consumer = consumer;
    }

    @Override
    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).lines()
          .forEach(consumer);
    }
}

boolean isWindows = System.getProperty("os.name")
  .toLowerCase().startsWith("windows");
String homeDirectory = System.getProperty("user.home");
Process process;
if (isWindows) {
    process = Runtime.getRuntime()
      .exec(String.format("cmd.exe /c dir %s", homeDirectory));
} else {
    process = Runtime.getRuntime()
      .exec(String.format("sh -c ls %s", homeDirectory));
}
StreamGobbler streamGobbler = 
  new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

希望有人有想法。

标签: java

解决方案


当您调用 时Executors.newSingleThreadExecutor(),将启动一个后台线程。由于线程不是守护线程,JVM 不会终止,直到线程停止运行。这永远不会发生,因此您的 Java 程序会继续运行,即使main线程已终止。

有多种修复方法:

  • 不要使用执行器,只需启动一个线程,该线程将在run()方法结束时StreamGobbler结束。

    StreamGobbler streamGobbler = ...
    new Thread(streamGobbler).start();
    int exitCode = process.waitFor();
    
  • 完成后关闭执行程序。

    StreamGobbler streamGobbler = ...
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(streamGobbler);
    int exitCode = process.waitFor();
    executor.shutdown();
    

推荐阅读