'How do you properly pipe a dd command to a netcat command in Rust?

I am fairly new to Rust and am trying to pipe a dd command to a netcat command to check the network bandwidth between two machines.

The total command is: dd if=/dev/zero bs=16000 count=625 | nc -v <my IP> <port number>.

My code so far:

use std::process::Command;
use std::process::Stdio;
use std::io::Write;
use std::io::Read;
use std::fs::File;

fn main() 
{
    let mut dd_cmd = Command::new("dd")
                         .args(&["if=/dev/zero", "bs=16000", 
                                 "count=625"])
                         .output()
                         .unwrap();

    let mut nc_cmd = Command::new("nc")
                         .args(&["-v", "<my IP>", "<port Number>"])
                         .stdin(Stdio::piped())
                         .spawn()
                         .unwrap();

    nc_cmd.stdin.unwrap().write_all(&dd_cmd.stdout).unwrap();
 }

(Note: I am aware that I am not error checking and that my nc command arguments for IP address and port number are changed. This is done for security reasons.)

What I want the output to look like:

enter image description here

The Problem:

I can successfully transfer files to the other machine and the text shows up in the terminal. However, on the first machine I don't receive any information about the network bandwidth. All I see in the terminal of the first machine are the "...inverse host lookup failed..." and "(UNKNOWN)..." lines. But, if I just test the dd command and change line 11 from ".output()" to ".spawn()", then I am able to see the network bandwidth information in the terminal of the first machine. After researching online, I understand that spawn() will by default make the stdin and stdout inherit from the parent process and output() will by default make the stdin and stdout be piped(). I don't understand why I am able to successfully transfer the data but lose the actual bandwidth information. Is that information not a part of the dd command output? Shouldn't it show up wherever the transferred data does as well?

A weird result:

I can open up a file and write it to the stdin of the nc command. When I do it this way, I can actually see the bandwidth information in the terminal of the first machine!



Solution 1:[1]

I don't understand why I am able to successfully transfer the data but lose the actual bandwidth information. Is that information not a part of the dd command output? Shouldn't it show up wherever the transferred data does as well?

Would you want the data you're transferring with dd and dd's stats reporting to be intermixed? That sounds like something which would break whatever you're transferring.

Or at least dd's designers thought so, which is why dd sends the data it transfers to stdout, but sends its own data to stderr. So if you want to send both over to the next stage in your pipeline, you need to send both.

Or maybe you mean that when you run this the information from dd does not show up in your terminal? That would be because

By default, stdout and stderr are captured (and used to provide the resulting output).

So stderr is captured, stored in a buffer, then dropped on the ground when the program terminates.

Incidentally your dd does not seem very useful here: output is going to start the child process, wait until it terminates, and collect all of its output in a Vec<u8>. So it's a very complicated and inefficient version of:

vec![0u8;10_000_000]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Masklinn