I am trying to make two pipe processes, for example dmesg | grep ACPI
.
I am able to make the Rust version with the following code.
let mut upstream_stdout = Command::new("dmesg")
.stdout(Stdio::piped())
.spawn()?
.stdout.unwrap();
let mut downstream_stdin = Command::new("grep")
.arg("ACPI")
.stdin(Stdio::piped())
.spawn()?
.stdin.unwrap();
upstream_stdout.bytes().for_each(|b| {
downstream_stdin.write_all(&[b.unwrap()]).expect("write error");
});
But this is quite different from what a normal shell does. This method actually setup the pipe in the following way: dmesg --> parent --> grep. And this setup requires the parent process do an additional copy from one pipe to another. But this is unnecessary if we are able to setup pipe between two children instead of establish the pipes connecting them to the parent.
In addition, if there is a longer pipeline with multiple process involved (e.g. A|B|C|D in shell) , it seems we need a lot of threads copying upstream output to downstream input (Or use some event driven pattern...).
But it's definitely better if we are able setup the child processes with chained input and output.
I can use unsafe code for this purpose for sure, but I am wondering if there's any idiomatic way to setup the connected child process with standard library.