在Rust中重定向stdio(管道和文件描述符)

在Rust中重定向stdio(管道和文件描述符),rust,pipe,file-descriptor,stdio,Rust,Pipe,File Descriptor,Stdio,我的主要目标是在Rust中实现一个程序,将stdio重定向到本地管道上,类似于此 程序执行命令“sh”,并在父进程和子进程之间创建管道 子进程的输出通过管道(在本例中是提示符)到达父进程 我在终端上键入一些东西,比如“pwd”,然后这些东西进入到子进程的管道中 子进程执行该命令,并通过管道将输出发送回父进程,并在我的终端上显示当前工作目录 最终,我的目标是让父进程充当代理,并通过远程ncat实例和子进程之间的TLS连接转发此I/O。目前,我正在努力使管道部分正确 我该怎么做?我当前的代码段如

我的主要目标是在Rust中实现一个程序,将stdio重定向到本地管道上,类似于此

  • 程序执行命令“sh”,并在父进程和子进程之间创建管道
  • 子进程的输出通过管道(在本例中是提示符)到达父进程
  • 我在终端上键入一些东西,比如“pwd”,然后这些东西进入到子进程的管道中
  • 子进程执行该命令,并通过管道将输出发送回父进程,并在我的终端上显示当前工作目录
最终,我的目标是让父进程充当代理,并通过远程ncat实例和子进程之间的TLS连接转发此I/O。目前,我正在努力使管道部分正确

我该怎么做?我当前的代码段如下所示,但我不确定重定向部分是否正确,因为我没有看到提示

let message_string=string::from(“fd_pipe\0”);
让message=message_string.as_ptr()as*const c_void;
让mut command_output=std::process::command::new(“/bin/sh”)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect(“无法执行命令”);
让command_stdin=command_output.stdin.unwrap();
普林顿!(“command_stdin{}”,command_stdin.as_raw_fd());
让command_stdout=command_output.stdout.unwrap();
普林顿!(“command_stdout{}”,command_stdout.as_raw_fd());
让command_stderr=command_output.stderr.unwrap();
普林顿!(“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());
2020年11月2日编辑 Rust论坛中有人为我提供了一个解决方案(),我想我也会在这里分享

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(&mut io::stdin(), &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(&mut command_stdout, &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(&mut command_stderr, &mut io::stderr())
});

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

我的下一个问题是如何通过TLS连接将重定向的stdio链接到远程ncat侦听器?

您不需要复制任何内容,我认为您所缺少的只是
命令\u输出。wait()
。你能澄清什么不起作用吗?另外,
.spawn()
意味着
Stdio::piped()
因此这些都是不需要的,
命令::new(“sh”).spawn().unwrap().wait().unwrap()
应该可以代理shell。您好@kmdreko,谢谢您的建议。我还发布了一个其他人也友好地与我分享的解决方案。