Перенаправление stdio (каналов и файловых дескрипторов) в Rust

#rust #pipe #file-descriptor #stdio

#Ржавчина #канал #файловый дескриптор #stdio

Вопрос:

Моя главная цель — реализовать программу в Rust для локального перенаправления stdio по каналам и похожа на это

  • Программа выполняет команду «sh» и создает каналы между родительским процессом и дочерним процессом
  • Выходные данные дочернего процесса передаются через канал (в данном случае приглашение) родительскому процессу
  • Я набираю что-то на своем терминале, например «pwd», и это передается в канал дочернему процессу
  • Дочерний процесс выполняет команду и отправляет выходные данные обратно через канал родительскому процессу и отображает текущий рабочий каталог на моем терминале

В конце концов, моя цель — заставить родительский процесс действовать как прокси-сервер и пересылать этот ввод-вывод через TLS-соединение между удаленным экземпляром ncat и дочерним процессом. На данный момент я пытаюсь правильно выполнить часть трубопровода.

Как мне это сделать? Мой текущий фрагмент кода выглядит следующим образом, но я не уверен, правильно ли я понял часть перенаправления, поскольку я не вижу подсказки.

 let message_string = String::from("fd_pipe");
let message = message_string.as_ptr() as *const c_void;

let mut command_output = std::process::Command::new("/bin/sh")
  .stdin(Stdio::piped())
  .stdout(Stdio::piped())
  .stderr(Stdio::piped())
  .spawn()
  .expect("cannot execute command");

let command_stdin = command_output.stdin.unwrap();
println!("command_stdin {}", command_stdin.as_raw_fd());

let command_stdout = command_output.stdout.unwrap();
println!("command_stdout {}", command_stdout.as_raw_fd());

let command_stderr = command_output.stderr.unwrap();
println!("command_stderr {}", command_stderr.as_raw_fd());

nix::unistd::dup2(tokio::io::stdin().as_raw_fd(), command_stdin.as_raw_fd());
nix::unistd::dup2(tokio::io::stdout().as_raw_fd(), command_stdout.as_raw_fd());
nix::unistd::dup2(tokio::io::stderr().as_raw_fd(), command_stderr.as_raw_fd());
  

РЕДАКТИРОВАТЬ 2 ноября 2020

Кто-то на форуме Rust любезно предоставил мне решение (https://users.rust-lang.org/t/redirect-stdio-pipes-and-file-descriptors/50751/8 ), я подумал, что поделюсь этим и здесь

 let mut command_output = std::process::Command::new("/bin/sh")
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .stderr(Stdio::piped())
    .spawn()
    .expect("cannot execute command");

let mut command_stdin = command_output.stdin.unwrap();
println!("command_stdin {}", command_stdin.as_raw_fd());

let copy_stdin_thread = std::thread::spawn(move || {
    io::copy(amp;mut io::stdin(), amp;mut command_stdin)
});
        
let mut command_stdout = command_output.stdout.unwrap();
println!("command_stdout {}", command_stdout.as_raw_fd());

let copy_stdout_thread = std::thread::spawn(move || {
   io::copy(amp;mut command_stdout, amp;mut io::stdout())
});

let command_stderr = command_output.stderr.unwrap();
println!("command_stderr {}", command_stderr.as_raw_fd());

let copy_stderr_thread = std::thread::spawn(move || {
    io::copy(amp;mut command_stderr, amp;mut io::stderr())
});

copy_stdin_thread.join().unwrap()?;
copy_stdout_thread.join().unwrap()?;
copy_stderr_thread.join().unwrap()?;
  

Мой следующий вопрос: как мне связать перенаправленный stdio через TLS-соединение с удаленным прослушивателем ncat?

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

1. Вам не нужно ничего дублировать, я думаю, все, что вам не хватает command_output.wait() . Можете ли вы уточнить, что не работает? Также .spawn() подразумевает Stdio::piped() , что они не нужны, Command::new("sh").spawn().unwrap().wait().unwrap() если прокси-сервер работает нормально.

2. Привет @kmdreko, спасибо за совет. Я также опубликовал решение, которым кто-то еще любезно поделился со мной.