Command
API 启动一个进程,并将其标准输出重定向到标准错误。以下失败:
Command::new("tput").arg("rc")
.stdout(io::stderr())
.status()
.expect("failed to run tput");
因为
Command::new("tput").arg("rc").stdout(<XXX>)
期待一个std::process::Stdio
:
expected struct `std::process::Stdio`, found struct `std::io::Stderr`
Bash 中的等价物可能是
tput rc > /dev/stderr
.
我想知道如何正确地做到这一点。
从 Rust 1.15.0 开始,
Stdio
不会在可移植的 API 中公开此功能,但您可以使用特定于平台的扩展特性来实现此目的。
std::os::unix::io::FromRawFd
特性在 Stdio
上实现。这个特征提供了一个单一的方法,from_raw_fd
,它可以将文件描述符转换为实现特征的类型。由于标准错误被定义为文件描述符 2,您可以简单地使用 .stdout(Stdio::from_raw_fd(2))
.
在 Windows 上,在
FromRawHandle
上实现了一个名为
Stdio
的类似特性。不幸的是,它没有列在联机文档中;它只包含特定于 Unix 的变体。您可以调用 GetStdHandle(STD_ERROR_HANDLE)
来获取标准错误的句柄。
AsFd
特征可以让我们从 BorrowedFd
得到一个
stderr
。
try_clone_to_owned
方法很难找到,但它给出了一个 OwnedFd
可以自动转换为 process::Stdio
,这是配置 stderr
子进程所需的类型。
use std::os::fd::AsFd;
let stderr = std::io::stderr().as_fd().try_clone_to_owned()?;
std::process::Command::new("terraform")
.arg("fmt")
.arg(&outpath)
.stdout(stderr)
.status()
.unwrap_or_else(|_| panic!("terraform fmt failed: {:?}", outpath));
有一个good为什么这如此迷宫的原因吗?或者只是实施者从来不想这样做?