达到超时时终止进程并在 Rust 中处理输出

maq*_*ong 6 multithreading multiprocessing rust

我正在尝试使用 Rust 进程的输出。如果进程在一定时间后没有终止,我想终止/终止它。理想情况下,我想将所有内容包装在生成器中,以便我可以逐行迭代输出,但我在 Rust 方面还没有足够的经验。

这是我的代码 ( src/main.rs),使用 subprocess crate:

use subprocess::{Popen, PopenConfig, Redirection};
use std::io::Read;
use std::time::Duration;


fn main() {
    let mut p = Popen::create(&["bash", "-c", "echo \"Hi There!\"; sleep 1000"], PopenConfig {stdout: Redirection::Pipe, ..Default::default()}, ).unwrap();
    let mut output = p.stdout.take().unwrap();

    let thread = std::thread::spawn(move || {
        let three_secs = Duration::from_secs(3);
        let one_sec = Duration::from_secs(1);
        let r = p.wait_timeout(three_secs).unwrap();
        match r {
            None => {
                println!("Wait timed out, terminating process");
                p.terminate().unwrap();
                let r = p.wait_timeout(one_sec).unwrap();
                match r {
                    None => {
                        println!("Termination didn't seem to work, killing");
                        p.kill().unwrap();
                    },
                    Some(_) => {
                        println!("Terminated process successfully");
                    },
                }
                p.wait().unwrap();},
            Some(_) => { println!("Process returned");},
        }
        println!("Everything fine");
    });

    println!("Starting to read output");
    let mut output_str = String::new();
    output.read_to_string(&mut output_str).unwrap();
    println!("Done reading output");
    thread.join().unwrap();

    println!("Output: {}", output_str);
    println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)

我期望以下输出:

Starting to read output
Wait timed out, terminating process
Terminated process successfully
Everything fine
Done reading output
Output: Hi There!

Hello, world!
Run Code Online (Sandbox Code Playgroud)

三秒后该过程结束。但我得到的是

Starting to read output
Wait timed out, terminating process
Terminated process successfully
Everything fine
Run Code Online (Sandbox Code Playgroud)

并且该过程不会终止。

为了完整起见,以下是我Cargo.toml对上面内容的补充src/main.rs:

[package]
name = "subproc"
version = "0.1.0"
authors = ["<snip>"]
edition = "2018"

[dependencies]
subprocess = "0.2.4"
Run Code Online (Sandbox Code Playgroud)

Edd*_*ett 4

我想找一个箱子来帮助你做到这一点。

也许是这样的: https://docs.rs/wait-timeout/0.2.0/wait_timeout/

以下是适用于捕获 stdout 并逐行迭代它的示例代码:

use std::io::Read;
use std::process::{Command, Stdio};
use std::time::Duration;
use wait_timeout::ChildExt;

fn main() {
    let mut child = Command::new("sh")
        .arg("-c")
        .arg("while true; do date; sleep 1; done")
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    let secs = Duration::from_secs(5);
    let _status_code = match child.wait_timeout(secs).unwrap() {
        Some(status) => status.code(),
        None => {
            child.kill().unwrap();
            child.wait().unwrap().code()
        }
    };

    let mut s = String::new();
    child.stdout.unwrap().read_to_string(&mut s).unwrap();

    for (num, line) in s.split("\n").enumerate() {
        println!("{}: {}", num, line);
    }
}
Run Code Online (Sandbox Code Playgroud)

印刷:

0: Mon Jun  1 14:42:06 BST 2020
1: Mon Jun  1 14:42:07 BST 2020
2: Mon Jun  1 14:42:08 BST 2020
3: Mon Jun  1 14:42:09 BST 2020
4: Mon Jun  1 14:42:10 BST 2020
5: 
Run Code Online (Sandbox Code Playgroud)

如果您想在子进程运行时执行其他工作,则必须使用事件循环或线程。