How to handle exit status properly for piped commands?

use std::process::{Command, Stdio};
use std::str;

fn main() {
    let cat = Command::new("cat")
        .arg("abc") // Make the command fail
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    // Maybe more piped commands here
    // ...

    let echo = Command::new("echo")
        .stdin(Stdio::from(cat.stdout.unwrap()))
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    let output = echo.wait_with_output().unwrap();
    println!("code: {:?}", output.status.code());
    println!("output: {}", str::from_utf8(&output.stdout).unwrap());

    if let Some(code) = output.status.code() {
        if code != 0 {
            std::process::exit(code);
        }
    }
}

In the example above, the ultimate goal of the program is to get the final output of multiple piped subprocesses. However, If the program should terminate if any of the processes fail, how should we check the status of each process?

Checking the final command seems the wrong way to it as in this example it always return 0 code even the first command failed.

What is the best practice of this?

Thank!

You need to check the exit codes of all commands. I would do this with an array (or vec) of all child commands; something like this:

    let all_commands: [Child; 2] = [cat, echo]; // add more commands here
    // You can remove all type annotations with the `2` in them, I just added them for clarity
    
    let results: [Output; 2] = all_commands.map(|c| c.wait_with_output().unwrap());

    let [.., echo_output] = &results;
    println!("output: {}", str::from_utf8(&echo_output.stdout).unwrap());

    for r in results {
        match r.status.code() {
            None => std::process::exit(1),
            Some(0) => continue,
            Some(c) => std::process::exit(c),
        }
    }
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.