2014-02-06 1 views
4

Я пытаюсь написать оболочку в Rust. Одной из функций оболочки является возможность перенаправления ввода в файл, перенаправление файла на вход и вывод вывода программы в другую программу. Я использую функции run::process_output в std для запуска программ и получения их вывода, но я не знаю, как отправить ввод, как если бы он был stdin для программы после ее запуска. Есть ли способ создать объект, который напрямую связан с запущенной программой и вставить вход, как он был введен в stdin?Как отправить ввод в программу через stdin в Rust

+0

вероятно 'станд :: бежать :: Process', вы можете получить' 'Reader' и Writer 'для' stdout' и 'stdin' – Arjan

ответ

1

Для этого вам понадобится ручка для выполнения процесса.

// spawn process 
let mut p = std::process::Command::new(prog).arg(arg).spawn().unwrap(); 
// give that process some input, processes love input 
p.stdin().get_mut_ref().write_str(contents); 
// wait for it to complete, you may need to explicitly close stdin above 
// i.e. p.stdin().get_mut_ref().close(); 
p.wait(); 

Вышеупомянутый должен позволить вам отправлять произвольные данные в процесс. Было бы важно закрыть трубу stdin, если порожденный процесс читается до тех пор, пока не будет, как это делают многие программы.

3

Эта программа демонстрирует, как вы можете запускать внешние программы и поток их стандартный вывод -> STDIN вместе:

use std::io::{BufRead, BufReader, BufWriter, Write}; 
use std::process::{Command, Stdio}; 

fn main() { 
    // Create some argument vectors for lanuching external programs 
    let a = vec!["view", "-h", "file.bam"]; 
    let outsam = vec!["view", "-bh", "-o", "rust.bam", "-"]; 

    let mut child = Command::new("samtools") 
     .args(&a) 
     .stdout(Stdio::piped()) 
     .spawn() 
     .unwrap(); 
    let outchild = Command::new("samtools") 
     .args(&outsam) 
     .stdin(Stdio::piped()) 
     .spawn() 
     .unwrap(); 

    // Create a handle and writer for the stdin of the second process 
    let mut outstdin = outchild.stdin.unwrap(); 
    let mut writer = BufWriter::new(&mut outstdin); 

    // Loop over the output from the first process 
    if let Some(ref mut stdout) = child.stdout { 
     for line in BufReader::new(stdout).lines() { 

      let mut l: String = line.unwrap(); 
      // Need to add an end of line character back to the string 
      let eol: &str = "\n"; 
      l = l + eol; 

      // Print some select lines from the first child to stdin of second 
      if (l.chars().skip(0).next().unwrap()) == '@' { 
       // convert the string into bytes and write to second process 
       let bytestring = l.as_bytes(); 
       writer.write_all(bytestring).unwrap(); 
      } 
     } 
    } 
} 
0

Обновленный вариант ответа Майкла. Если выход/вход мал, вы можете прочитать его в строку и трубы обратно следующим образом:

let output = Command::new("ls").arg("-aFl") 
     .output().unwrap().stdout; 
let output = String::from_utf8_lossy(&output); 
println!("First program output: {:?}", output); 
let put_command = Command::new("my_other_program") 
     .stdin(Stdio::piped()) 
     .spawn().unwrap(); 
write!(put_command.stdin.unwrap(), "{}", output).unwrap();