如何将子进程输出重定向到标准错误?

问题描述 投票:0回答:2

我正在尝试使用

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 io-redirection
2个回答
7
投票

从 Rust 1.15.0 开始,

Stdio
不会在可移植的 API 中公开此功能,但您可以使用特定于平台的扩展特性来实现此目的。

在类 Unix 平台上,

std::os::unix::io::FromRawFd
特性在
Stdio
上实现。这个特征提供了一个单一的方法,
from_raw_fd
,它可以将文件描述符转换为实现特征的类型。由于标准错误被定义为文件描述符 2,您可以简单地使用
.stdout(Stdio::from_raw_fd(2))
.

在 Windows 上,

FromRawHandle
 上实现了一个名为 
Stdio 的类似特性。不幸的是,它没有列在联机文档中;它只包含特定于 Unix 的变体。您可以调用
GetStdHandle(STD_ERROR_HANDLE)
来获取标准错误的句柄。


0
投票

这适用于 Linux。引入

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为什么这如此迷宫的原因吗?或者只是实施者从来不想这样做?

© www.soinside.com 2019 - 2024. All rights reserved.