如何使用Tokio从子进程的stdout和stderr异步读取?

时间:2019-12-17 12:24:02

标签: rust rust-tokio

Tokio(我使用的是0.2,期货是0.3)具有process::Command.output(),它在完成后从子进程返回组合输出(stdout和stderr)。但是,出于某些原因,我想输出:

  1. 它可能大于可用内存。

  2. stdout和stderr输出可能是交错的(我意识到,一般而言,两者之间的关系不会成为可以依赖的东西,但是我宁愿付出尽可能多的努力来保持结果类似于正常运行该过程。

  3. 我不想等到进程终止后才开始返回输出。

我尝试将select!与一对期货和一个循环一起使用:

let outbuf = [0u8; 512];
let errbuf = [0u8; 512];

let outfut = child_stdout.read(&mut outbuf).fuse();
let errfut = child_stderr.read(&mut errbuf).fuse();

pin_mut!(outfut, errfut);

loop {
    select! {
        result = outfut => {
            let length = result?;
            if length != 0 {
                 output.write_all(&outbuf[..length]).await?
                 outfut.set(child_stdout.read(&mut outbuf).fuse())
            }
        }
        result = errfut => {
            let length = result?;
            if length != 0 {
                 output.write_all(&errbuf[..length]).await?
                 errfut.set(child_stderr.read(&mut errbuf).fuse())
            }
        }
        complete => break
    }
}

let status = child.await?

当然,这是行不通的,因为我两次借用了缓冲区;我尝试过以各种方式重新排列代码,但是当使用select!时,我似乎总是不得不两次借用东西。 (还要注意,实际上,if语句中的输出比我上面显示的要多,并且stdout和stderr分支彼此不同,因此您不能仅将stdout和stderr都重定向到同一地点,并称之为一天。)

很显然,这不是正确的方法。是否有一种惯用的Rust方法来实现我所追求的目标?

0 个答案:

没有答案