6

fn main() {
    let output = Command::new("/bin/bash")
                .args(&["-c", "docker","build", "-t", "postgres:latest", "-", "<>", "dockers/PostgreSql"])
                .output()
                .expect("failed to execute process");

    println!("{:?}", output);
}
  1. Above code runs fine but prints output only after docker script is completely ran, But I want to see all command output in my Linux terminal as it happens and want to see output as it happens,
  2. I tried all combinations given in documentation and read it many times, not understanding, how do I redirect stdout to my terminal window,
1

2 Answers 2

7

According to the documentation stdout has default behavior depending on how you launch your subprocess:

Defaults to inherit when used with spawn or status, and defaults to piped when used with output.

So stdout is piped when you call output(). What does piped mean? This means the child process's output will be directed to the parent process (our rust program in this case). std::process::Command is kind enough to give us this as a string:

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

let output = Command::new("echo")
    .arg("Hello, world!")
    .stdout(Stdio::piped())
    .output()
    .expect("Failed to execute command");

assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n");
// Nothing echoed to console

Now that we understand where the stdout is currently going, if you wish to have the console get streamed output, call the process using spawn():

use std::process::Command;

fn main() {

    let output = Command::new("/bin/bash")
                .args(&["-c", "echo hello world"])
                .spawn()
                .expect("failed to execute process");


    println!("{:?}", output);
}

Notice also in this later example, I pass the full echo hello world command in one string. This is because bash -c splits its arg by space and runs it. If you were in your console executing a docker command through a bash shell you would say:

bash -c "docker run ..."

The quotes above tell the terminal to keep the third arg together and not split it by space. The equivalent in our rust array is to just pass the full command in a single string (assuming you wish to call it through bash -c of course).

Sign up to request clarification or add additional context in comments.

2 Comments

This setting worked for me fn run_command() { let _output = Command::new("/bin/bash") .arg("-c") .arg("docker build -t postgres:latest - < dockers/PostgreSql") .spawn() .expect("failed to execute process"); }
Actually during debugging, I changed package name in cargo, but forgot to run new name in executable, so I saw no change whole night I was changing and building and no change , so thought documentation is bad, Documentation is sufficient and my fault I struggled,
0

I had luck with the other answer, but I had to modify it a little. For me, I needed to add the wait method:

use std::{io, process::Command};

fn main() -> io::Result<()> {
   let mut o = Command::new("rustc").arg("-V").spawn()?;
   o.wait()?;
   Ok(())
}

otherwise the parent program will end before the child.

https://doc.rust-lang.org/std/process/struct.Child.html#method.wait

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.