简体   繁体   English

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

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

I want to run multiple external commands from inside my scala program and be able to handle their output (sent to stdout). 我想从我的scala程序中运行多个外部命令,并能够处理它们的输出(发送到stdout)。 Is there a way which will allow me to do it? 有没有办法可以让我这样做? Output of the programs will contain some logging and probably progress info. 程序的输出将包含一些日志记录和可能的进度信息。 I need to parse their output and send it to database server in order to save logs, progress and shutdown processes if they return an error. 我需要解析它们的输出并将其发送到数据库服务器,以便在它们返回错误时保存日志,进度和关闭进程。 Important aspect is that I don't want to wait for different processes to finish but to get the output continously. 重要的一点是,我不想等待不同的流程完成,而是要不断获得输出。

I am running separate external commands this way: 我这样运行单独的外部命令:

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

"bId" is just my process id. “bId”只是我的进程ID。 I can't manage how to get the output in other way than using: 除了使用以外,我无法管理如何以其他方式获取输出:

Await.result() 

method, on the result of "execCommand" method, but it's not how I want it to work. 方法,关于“execCommand”方法的结果,但它不是我想要它的工作方式。

I want my program to handle multiple streams of data in multiple threads and manage this data continously. 我希望我的程序能够处理多个线程中的多个数据流并持续管理这些数据。 It doesn't need to be scala, solutions in java will be ok as well. 它不需要是scala,java中的解决方案也可以。

When you start the process, you also start a thread for reading the output of that process. 当您启动该过程时,您还会启动一个线程来读取该过程的输出。

If you want to manage that output in a single thread, create a BlockingQueue and send the output to the queue. 如果要在单个线程中管理该输出,请创建BlockingQueue并将输出发送到队列。 You'd likely want to track which process the output came from, so use a POJO in the queue. 您可能想要跟踪输出来自哪个进程,因此在队列中使用POJO。

Example

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

Sample Output 样本输出

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