我在用Rust编写的shell中实现I / O重定向。通过使用带有原始文件描述符的不安全代码和来自libc crate的pipe()
,我成功地在两个子进程之间进行管道。
当我尝试将最后一个子进程的stdout
重定向到我有权访问的文件时,它会失败:
extern crate libc;
use std::process::{Command, Stdio};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::fs::File;
use self::libc::c_int;
fn main() {
let mut fds = [-1 as c_int, -1 as c_int];
let fd1 = File::open("test1").unwrap().into_raw_fd();
let fd2 = File::open("test2").unwrap().into_raw_fd();
let fd3 = File::open("test3").unwrap().into_raw_fd();
println!("{:?}, {:?}, {:?}", fd1, fd2, fd3);
unsafe {
libc::pipe(&mut fds[0] as *mut c_int);
let cmd1 = Command::new("ls")
.arg("/")
.stdout(Stdio::from_raw_fd(fds[1]))
.spawn()
.unwrap();
let mut cmd2 = Command::new("grep")
.arg("etc")
.stdin(Stdio::from_raw_fd(fds[0]))
.stdout(Stdio::from_raw_fd(fd1))
.spawn()
.unwrap();
let _result = cmd2.wait().unwrap();
}
}
以上作品的结果:
3, 4, 5
grep: write error: Bad file descriptor
似乎没有正确返回文件描述符,但如果没有名为test1,test2和test3的文件,File::open(_).unwrap()
应该发生恐慌,而不是假装打开文件。
如果删除了重定向到文件的代码,即只使用管道,代码就可以正常工作。
答案 0 :(得分:3)
File::open
州的文件(强调我的):
尝试以只读模式打开文件。
切换到File::create
似乎会创建文件" etc"是写给它的。
此外,你应该:
pipe
的返回值以处理错误。extern crate libc;
extern crate nix;
use std::process::{Command, Stdio};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::fs::File;
use nix::unistd::pipe;
fn main() {
let fds = pipe().unwrap();
let fd1 = File::create("test1").unwrap().into_raw_fd();
let (pipe_in, pipe_out, file_out) = unsafe {
(Stdio::from_raw_fd(fds.0),
Stdio::from_raw_fd(fds.1),
Stdio::from_raw_fd(fd1))
};
Command::new("ls")
.arg("/")
.stdout(pipe_out)
.spawn()
.unwrap();
let mut cmd2 = Command::new("grep")
.arg("etc")
.stdin(pipe_in)
.stdout(file_out)
.spawn()
.unwrap();
cmd2.wait().unwrap();
}