Posts Tagged ‘commandline’
Executant una comanda des de Rust
He aconseguit desenvolupar una petita funció anomenada run_easy() que permet executar una comanda des de rust.
En concret, la comanda és l’execució d’un programa en Java que rep arguments per línia de comanda, llegeix per entrada estàndard, escriu per sortida estàndard i d’error estàndard, i es queda en un bucle infinit.
run_easy() permet indicar la comanda, l’entrada, els arguments i el temps màxim d’espera en segons.
run_easy() retorna l’estructura RunResult:
pub struct RunResult {
pub status: i32,
pub stdout: String,
pub stderr: String,
}
El codi de la funció és:
fn run_easy(input: &str, program: &str, args: &[&str], timeout: u64) -> RunResult {
let mut child = Command::new(program)
.args(args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
// write input
_ = child.stdin.take().as_mut().unwrap().write_all(input.as_bytes());
// wait for execution
let duration = Duration::from_secs(timeout);
let status_code = match child.wait_timeout(duration).unwrap() {
Some(status) => status.code(),
None => { // child hasn't exited yet
child.kill().unwrap();
child.wait().unwrap();
Some(124)
}
};
// recollect output
let mut stdout = String::new();
child.stdout.unwrap().read_to_string(&mut stdout).unwrap();
let mut stderr = String::new();
child.stderr.unwrap().read_to_string(&mut stderr).unwrap();
// compose result
RunResult {
status: status_code.unwrap(),
stdout: stdout,
stderr: stderr
}
}
Et caldrà indicar els següents use:
use std::io::prelude::*;
use std::process::{Command, Stdio};
use std::time::Duration;
use wait_timeout::ChildExt;
No oblidis incloure la dependència a Cargo.toml:
[dependencies]
wait-timeout = "0.1.5"
Finalment, un exemple d’ús:
let input = "THIS IS THE WONDERFUL INPUT";
let args = &["MyProgram", "un", "dos", "tres"];
let program = "java";
let result = run_easy(input, program, args, 4);
println!("Resulting execution:");
println!("\tstatus: {}", result.status);
println!("\toutput:\n{}", result.stdout);
println!("\terror:\n{}", result.stderr);
El contingut de MyProgram.java pot ser tant senzill com:
public class MyProgram {
public static void main(String[] args){
for (String arg: args) {
System.out.println("arg: " + arg);
}
String text = Entrada.readLine();
System.out.println("Hello World " + text);
System.err.println("some error text");
while(true);
}
}
De moment és el més senzill que he estat capaç d’escriure.