diff --git a/commandtest/src/main.rs b/commandtest/src/main.rs index 412a385..a77f5a4 100644 --- a/commandtest/src/main.rs +++ b/commandtest/src/main.rs @@ -4,6 +4,7 @@ use std::io::{BufRead, BufReader, Read, Write}; use std::path::PathBuf; use std::process::Command; +/// Special script that looks for some file in $PATH. fn search_in_path(name: &str) -> Option { let path = std::env::var_os("PATH").unwrap_or_else(OsString::new); std::env::split_paths(&path).find_map(|dir| { @@ -29,9 +30,12 @@ fn main() { .spawn() .unwrap(); + // capture both the stdout and stderr as File structs (actually FDs, but basically the same + // thing) let stdout = cmd.stdout.take().unwrap(); let mut stderr = cmd.stderr.take().unwrap(); + // spawn a thread to keep capturing and processing the stdout. let writer_pid = std::thread::spawn(move || { let reader = BufReader::new(stdout); let lines = reader.lines(); @@ -56,15 +60,27 @@ fn main() { result }); + // run the command till it finishes cmd.wait().unwrap(); + + // ... and wait till the thread finishes processing the whole output. let warnings = writer_pid.join().unwrap(); + // this is somewhat a hack: Instead of spawning a thread for stderr and trying to fight with + // stdout for the lock to be able to write in the log file, we do this after the thread ends + // (which closes the file) and then open it again and write the stderr in the end. We do this + // 'cause we expect that the stderr is way smaller than stdout and can fit in memory without + // any issues. let mut buffer = String::new(); stderr.read_to_string(&mut buffer).unwrap(); let mut file = OpenOptions::new().append(true).open("script.log").unwrap(); file.write(buffer.as_bytes()).unwrap(); + // This is purely for diagnostic purposes. We could put the warnings in another file, or pass + // it along to something else to process it. Here, we just display them. + // Same for stderr: Since we already put them in the file, this is used just to make sure we + // are capturing the errors without looking at the file. println!("Warnings:\n{:?}", warnings); println!("ERR:\n{:?}", buffer) }