Я пытаюсь написать оболочку в Rust. Одной из функций оболочки является возможность перенаправления ввода в файл, перенаправление файла на вход и вывод вывода программы в другую программу. Я использую функции run::process_output
в std
для запуска программ и получения их вывода, но я не знаю, как отправить ввод, как если бы он был stdin для программы после ее запуска. Есть ли способ создать объект, который напрямую связан с запущенной программой и вставить вход, как он был введен в stdin?Как отправить ввод в программу через stdin в Rust
4
A
ответ
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();
вероятно 'станд :: бежать :: Process', вы можете получить' 'Reader' и Writer 'для' stdout' и 'stdin' – Arjan