Как отправить входные данные в stdin процесса, созданного с помощью Command, а затем захватить выходные данные (и статус)

#rust

#Ржавчина

Вопрос:

Я хочу создать дочерний процесс с помощью Command, передать ему stdin от другого созданного мной дочернего процесса, а затем дождаться и зафиксировать выходные данные.

Я видел другие вопросы и ответы об одном или другом, но не оба.

Порядок, который я пытаюсь выполнить, таков:

  • Создайте дочернюю команду назначения, stdin как переданную ()
  • Создайте дочерний элемент с помощью spawn() и верните дочерний элемент обратно
  • получить поле ‘stdin’ от дочернего элемента для использования с buffer writer
  • создать источник процесса данных с помощью stdout Piped()
  • повторите вывод исходного кода, записывая стандартный вывод в стандартный вывод назначения
  • затем попробуйте захватить выходные данные назначения с помощью wait_with_output()

Этот последний шаг не компилируется, поскольку в нем говорится, что дочерний объект перемещается (потребляется), когда я получаю для него stdin.

Ссылка на игровую площадку

Ответ №1:

Вам нужно стать владельцем dest_child.stdin канала, чтобы передать объект BufWriter::new . Поскольку канал находится внутри Option , вы можете использовать Option::take для его перемещения, не оставляя dest_child «частично перемещенный». Еще одна проблема с вашим кодом заключается в том, что он dest.stdin должен передаваться по конвейеру, а не наследоваться, иначе dest_child.stdin просто останется None . С этими изменениями ваш код компилируется и запускается (игровая площадка).

Обратите внимание, однако, что нет необходимости вручную передавать данные из одного процесса в другой, ОС вполне способна сделать это самостоятельно. Например (игровая площадка):

 use std::process::{Command, Stdio};

fn main() {
    let mut dest = Command::new("wc")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    let _source = Command::new("ls")
        .stdout(dest.stdin.take().unwrap())
        .spawn()
        .unwrap();
    let dest_output = dest.wait_with_output().unwrap();

    match dest_output.status.code() {
        Some(0) => println!("OK: {}", String::from_utf8_lossy(amp;dest_output.stdout)),
        Some(code) => println!("Error {}", code),
        None => {}
    }
}
  

Комментарии:

1. Отлично, спасибо. Я скопировал код, который копирует его из другого ответа. Вы намного более лаконичны и элегантны. Приветствуется.