繁体   English   中英

如何从在不同线程中运行的多个外部命令管理多个stdout?

[英]How to manage multiple stdout's from multiple external command runned in separate threads?

我想从我的scala程序中运行多个外部命令,并能够处理它们的输出(发送到stdout)。 有没有办法可以让我这样做? 程序的输出将包含一些日志记录和可能的进度信息。 我需要解析它们的输出并将其发送到数据库服务器,以便在它们返回错误时保存日志,进度和关闭进程。 重要的一点是,我不想等待不同的流程完成,而是要不断获得输出。

我这样运行单独的外部命令:

def execCommand(command: String, bId: Long): Future[(Long, Stream[String])] = {
    Future {
      bId -> command.lineStream
    }(executionContext)
  }

“bId”只是我的进程ID。 除了使用以外,我无法管理如何以其他方式获取输出:

Await.result() 

方法,关于“execCommand”方法的结果,但它不是我想要它的工作方式。

我希望我的程序能够处理多个线程中的多个数据流并持续管理这些数据。 它不需要是scala,java中的解决方案也可以。

当您启动该过程时,您还会启动一个线程来读取该过程的输出。

如果要在单个线程中管理该输出,请创建BlockingQueue并将输出发送到队列。 您可能想要跟踪输出来自哪个进程,因此在队列中使用POJO。

public class CommandOutput {
    private final int process;
    private final String line;
    public CommandOutput(int process, String line) {
        this.process = process;
        this.line = line;
    }
    public int getProcess() {
        return this.process;
    }
    public String getLine() {
        return this.line;
    }
}
public class CommandOutputStreamHandler extends Thread {
    private final int process;
    private final InputStream stream;
    private final BlockingQueue<CommandOutput> queue;
    public CommandOutputStreamHandler(int process, InputStream stream, BlockingQueue<CommandOutput> queue) {
        this.process = process;
        this.stream = stream;
        this.queue = queue;
    }
    @Override
    public void run() {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(this.stream))) {
            for (String line; (line = reader.readLine()) != null; ) {
                this.queue.add(new CommandOutput(this.process, line));
                Thread.sleep(200); // just for simulating output over time
            }
        } catch (Exception e) {
            throw new RuntimeException(e); // or simply log the exception
        } finally {
            this.queue.add(new CommandOutput(this.process, null));
        }
    }
}
BlockingQueue<CommandOutput> queue = new LinkedBlockingQueue<>();

final int PROCS = 3;
for (int i = 0; i < PROCS; i++) {
    Process p = new ProcessBuilder("cmd.exe", "/c", "dir", "/b")
            .redirectErrorStream(true)
            .start();
    new CommandOutputStreamHandler(i, p.getInputStream(), queue)
            .start();
}

for (int endMarkers = 0; endMarkers < PROCS; ) {
    CommandOutput co = queue.take();
    if (co.getLine() == null) {
        endMarkers++;
    } else {
        System.out.println(co.getProcess() + ": " + co.getLine());
    }
}

样本输出

0: .classpath
0: .project
1: .classpath
0: .settings
1: .project
0: lib
1: .settings
0: pom.xml
1: lib
0: src
1: pom.xml
0: target
1: src
2: .classpath
1: target
2: .project
2: .settings
2: lib
2: pom.xml
2: src
2: target

暂无
暂无

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

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