feat: introduce os_pipe, redirect stdout and stderr into the same pipe
This commit is contained in:
parent
96d5e65ae2
commit
9a71a8f783
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
os_pipe = "1.2.1"
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Reference in New Issue