Skip to content

Instantly share code, notes, and snippets.

@pkozelka
Last active February 7, 2024 17:49
Show Gist options
  • Save pkozelka/3514f8ba2a5fcb9992ef6ee001747a5d to your computer and use it in GitHub Desktop.
Save pkozelka/3514f8ba2a5fcb9992ef6ee001747a5d to your computer and use it in GitHub Desktop.
Process execution in Rust
use std::path::Path;
use std::process::Stdio;
use tokio::io::BufReader;
use tokio::io::AsyncBufReadExt;
use tokio::process::Command;
use tokio::sync::mpsc;
/// Execute a process, gather its mixed outputs into stdout
///
pub async fn execute<P: AsRef<Path>>(executable: P, args: Vec<&'static str>) {
let mut process = Command::new(executable.as_ref())
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
println!("Executing {:?}", process);
let (tx, mut rx) = mpsc::channel(1000);
{ // spawn a task that reads standard output
let tx = tx.clone();
let stdout = process.stdout.take().unwrap();
tokio::spawn(async move {
let mut lines = BufReader::new(stdout).lines();
while let Some(line) = lines.next_line().await.unwrap() {
tx.send(format!("- {}", line)).await.unwrap();
}
});
}
{ // spawn a task that reads standard error
let stderr = process.stderr.take().unwrap();
tokio::spawn(async move {
let mut lines = BufReader::new(stderr).lines();
while let Some(line) = lines.next_line().await.unwrap() {
tx.send(format!("! {}", line)).await.unwrap();
}
});
}
// mix all the outputs
while let Some(line) = rx.recv().await {
println!("{}", line);
}
let exit_status = process.wait().await.unwrap();
println!("exit code: {}", exit_status);
}
#[tokio::main]
async fn main() {
execute("find", vec!("/", "-name", "*.sh")).await;
}
use std::path::Path;
use std::process::Stdio;
use tokio::io::BufReader;
use tokio::io::AsyncBufReadExt;
use tokio::process::Command;
pub async fn execute<P: AsRef<Path>>(executable: P, args: Vec<&'static str>) {
let mut process = Command::new(executable.as_ref())
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.unwrap();
{
let stdout = process.stdout.take().unwrap();
let reader = BufReader::new(stdout);
let mut lines = reader.lines();
while let Some(line) = lines.next_line().await.unwrap() {
println!("STDOUT: {}", line);
}
}
let exit_status = process.wait().await.unwrap();
println!("exit code: {}", exit_status);
}
#[tokio::main]
async fn main() {
execute("find", vec!("/", "-name", "*.sh")).await;
}
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::{Command, Stdio};
pub fn execute<P: AsRef<Path>>(executable: P, args: Vec<&'static str>) {
let mut cmd = Command::new(executable.as_ref())
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.unwrap();
{
let stdout = cmd.stdout.as_mut().unwrap();
let reader = BufReader::new(stdout);
let lines = reader.lines();
for line in lines {
println!("Read: {:?}", line);
}
}
cmd.wait().unwrap();
}
fn main() {
execute("find", vec!("/", "-name", "*.sh"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment