feat: introduce os_pipe, redirect stdout and stderr into the same pipe

This commit is contained in:
anjingyu 2024-10-09 11:54:40 +08:00
parent 96d5e65ae2
commit 9a71a8f783
2 changed files with 54 additions and 12 deletions

View File

@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
os_pipe = "1.2.1"

View File

@ -1,6 +1,31 @@
use std::io::{BufRead, BufReader, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::process::{Command, Stdio};
use std::process::Command;
#[allow(dead_code)]
fn run_command(mut command: Command) {
// Here's the interesting part. Open a pipe, clone its writer, and
// set that pair of writers as the child's stdout and stderr.
let (mut reader, writer) = os_pipe::pipe().unwrap();
let writer_clone = writer.try_clone().unwrap();
command.stdout(writer);
command.stderr(writer_clone);
// Now start the child process running.
let mut handle = command.spawn().unwrap();
// Avoid a deadlock! This parent process is still holding open pipe
// writers inside the Command object, and we have to close those
// before we read. Here we do this by dropping the Command object.
drop(command);
// Finally we can read all the output and clean up the child.
let mut output = String::new();
reader.read_to_string(&mut output).unwrap();
handle.wait().unwrap();
assert_eq!(output, "foobar");
println!("output: {}", output);
}
fn handle_connection(mut stream: TcpStream) {
let mut buffer = [0; 1024];
@ -15,25 +40,40 @@ fn handle_connection(mut stream: TcpStream) {
"rebuild",
"-v",
"-d",
"base",
"/home/anjingyu/Documents/projs/work/ad/base",
];
let mut child = Command::new("admake")
.args(args)
.stdout(Stdio::piped())
.spawn()
.unwrap();
let output = child.stdout.take().unwrap();
let mut reader = BufReader::new(output);
// let mut buf = Vec::new();
let mut command = Command::new("admake");
command.args(args);
// Here's the interesting part. Open a pipe, clone its writer, and
// set that pair of writers as the child's stdout and stderr.
let (reader, writer) = os_pipe::pipe().unwrap();
let writer_clone = writer.try_clone().unwrap();
command.stdout(writer);
command.stderr(writer_clone);
// Now start the child process running.
let mut handle = command.spawn().unwrap();
// Avoid a deadlock! This parent process is still holding open pipe
// writers inside the Command object, and we have to close those
// before we read. Here we do this by dropping the Command object.
drop(command);
// let mut reader = BufReader::new(output);
let mut r = BufReader::new(reader);
loop {
let mut line = String::new();
match reader.read_line(&mut line) {
// Finally we can read all the output and clean up the child.
// let mut output = String::new();
// reader.read_to_string(&mut output).unwrap();
match r.read_line(&mut line) {
Ok(0) => break,
Ok(_) => {
stream.write_all(line.as_bytes()).unwrap();
stream.flush().unwrap();
// buf.push(line);
}
Err(e) => {
eprintln!("Error reading command output: {}", e);
@ -41,6 +81,7 @@ fn handle_connection(mut stream: TcpStream) {
}
}
}
handle.wait().unwrap();
} else {
stream
.write(String::from("command format is invalid\n").as_bytes())