Browse Source

Comments

master
Julio Biason 9 months ago
parent
commit
3b7bfed082
  1. 16
      commandtest/src/main.rs

16
commandtest/src/main.rs

@ -4,6 +4,7 @@ use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
/// Special script that looks for some file in $PATH.
fn search_in_path(name: &str) -> Option<PathBuf> { fn search_in_path(name: &str) -> Option<PathBuf> {
let path = std::env::var_os("PATH").unwrap_or_else(OsString::new); let path = std::env::var_os("PATH").unwrap_or_else(OsString::new);
std::env::split_paths(&path).find_map(|dir| { std::env::split_paths(&path).find_map(|dir| {
@ -29,9 +30,12 @@ fn main() {
.spawn() .spawn()
.unwrap(); .unwrap();
// capture both the stdout and stderr as File structs (actually FDs, but basically the same
// thing)
let stdout = cmd.stdout.take().unwrap(); let stdout = cmd.stdout.take().unwrap();
let mut stderr = cmd.stderr.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 writer_pid = std::thread::spawn(move || {
let reader = BufReader::new(stdout); let reader = BufReader::new(stdout);
let lines = reader.lines(); let lines = reader.lines();
@ -56,15 +60,27 @@ fn main() {
result result
}); });
// run the command till it finishes
cmd.wait().unwrap(); cmd.wait().unwrap();
// ... and wait till the thread finishes processing the whole output.
let warnings = writer_pid.join().unwrap(); 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(); let mut buffer = String::new();
stderr.read_to_string(&mut buffer).unwrap(); stderr.read_to_string(&mut buffer).unwrap();
let mut file = OpenOptions::new().append(true).open("script.log").unwrap(); let mut file = OpenOptions::new().append(true).open("script.log").unwrap();
file.write(buffer.as_bytes()).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!("Warnings:\n{:?}", warnings);
println!("ERR:\n{:?}", buffer) println!("ERR:\n{:?}", buffer)
} }

Loading…
Cancel
Save