x-i18n: generated_at: “2026-03-01T14:18:40Z” model: gemini-3-flash-preview provider: google-gemini-cli source_hash: f61a0dce702794c35688c89b09a7b5db6b91769a3d65ce1b53d45d84b2202ffb source_path: ch12-06-writing-to-stderr-instead-of-stdout.md workflow: 16
将错误重定向到标准错误 (Redirecting Errors to Standard Error)
Redirecting Errors to Standard Error
目前,我们正使用 println! 宏将所有输出写入终端。在大多数终端中,有两种输出:用于一般信息的“标准输出 (standard output,stdout)”和用于错误消息的“标准错误 (standard error,stderr)”。这种区分使用户能够选择将程序的成功输出定向到文件,但仍将错误消息打印到屏幕上。
At the moment, we’re writing all of our output to the terminal using the
println! macro. In most terminals, there are two kinds of output: standard
output (stdout) for general information and standard error (stderr) for
error messages. This distinction enables users to choose to direct the
successful output of a program to a file but still print error messages to the
screen.
println! 宏只能打印到标准输出,因此我们必须使用其他工具来打印到标准错误。
The println! macro is only capable of printing to standard output, so we have
to use something else to print to standard error.
检查错误写在哪里 (Checking Where Errors Are Written)
Checking Where Errors Are Written
首先,让我们观察 minigrep 打印的内容目前是如何被写入标准输出的,包括我们想要改写到标准错误的任何错误消息。我们将通过在故意引发错误的同时将标准输出流重定向到文件来实现这一点。我们不会重定向标准错误流,因此任何发送到标准错误的内容将继续显示在屏幕上。
First, let’s observe how the content printed by minigrep is currently being
written to standard output, including any error messages we want to write to
standard error instead. We’ll do that by redirecting the standard output stream
to a file while intentionally causing an error. We won’t redirect the standard
error stream, so any content sent to standard error will continue to display on
the screen.
命令行程序应该将错误消息发送到标准错误流,这样即使我们将标准输出流重定向到文件,我们仍然可以在屏幕上看到错误消息。我们的程序目前表现得并不好:我们将看到它将错误消息输出保存到了文件中!
Command line programs are expected to send error messages to the standard error stream so that we can still see error messages on the screen even if we redirect the standard output stream to a file. Our program is not currently well behaved: We’re about to see that it saves the error message output to a file instead!
为了演示此行为,我们将使用 > 和想要重定向标准输出流到的文件路径 output.txt 来运行该程序。我们不传递任何参数,这应该会导致错误:
To demonstrate this behavior, we’ll run the program with > and the file path,
output.txt, that we want to redirect the standard output stream to. We won’t
pass any arguments, which should cause an error:
$ cargo run > output.txt
> 语法告诉 shell 将标准输出的内容写入 output.txt 而不是屏幕。我们没有看到预期的错误消息打印到屏幕上,这意味着它一定进入了文件中。这是 output.txt 包含的内容:
The > syntax tells the shell to write the contents of standard output to
output.txt instead of the screen. We didn’t see the error message we were
expecting printed to the screen, so that means it must have ended up in the
file. This is what output.txt contains:
Problem parsing arguments: not enough arguments
是的,我们的错误消息正被打印到标准输出。让此类错误消息打印到标准错误流更有用,这样只有来自成功运行的数据才会最终进入文件中。我们将改变这一点。
Yup, our error message is being printed to standard output. It’s much more useful for error messages like this to be printed to standard error so that only data from a successful run ends up in the file. We’ll change that.
将错误打印到标准错误 (Printing Errors to Standard Error)
Printing Errors to Standard Error
我们将使用示例 12-24 中的代码来更改错误消息的打印方式。得益于我们在本章前面所做的重构,所有打印错误消息的代码都在一个函数 main 中。标准库提供了打印到标准错误流的 eprintln! 宏,所以让我们将调用 println! 打印错误的两处地方改为使用 eprintln! 。
We’ll use the code in Listing 12-24 to change how error messages are printed.
Because of the refactoring we did earlier in this chapter, all the code that
prints error messages is in one function, main. The standard library provides
the eprintln! macro that prints to the standard error stream, so let’s change
the two places we were calling println! to print errors to use eprintln!
instead.
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-24/src/main.rs:here}}
现在让我们以相同的方式再次运行程序,不带任何参数并使用 > 重定向标准输出:
Let’s now run the program again in the same way, without any arguments and
redirecting standard output with >:
$ cargo run > output.txt
Problem parsing arguments: not enough arguments
现在我们在屏幕上看到了错误,而 output.txt 什么都没有包含,这正是我们期望的命令行程序的行为。
Now we see the error onscreen and output.txt contains nothing, which is the behavior we expect of command line programs.
让我们再次带参数运行程序,这些参数不会导致错误但仍将标准输出重定向到文件,如下所示:
Let’s run the program again with arguments that don’t cause an error but still redirect standard output to a file, like so:
$ cargo run -- to poem.txt > output.txt
我们将不会在终端看到任何输出,而 output.txt 将包含我们的结果:
We won’t see any output to the terminal, and output.txt will contain our results:
文件名: output.txt
Are you nobody, too?
How dreary to be somebody!
这证明了我们现在正适当地将标准输出用于成功输出,将标准错误用于错误输出。
This demonstrates that we’re now using standard output for successful output and standard error for error output as appropriate.
总结 (Summary)
Summary
本章回顾了你目前学到的一些主要概念,并涵盖了如何在 Rust 中执行常见的 I/O 操作。通过使用命令行参数、文件、环境变量以及用于打印错误的 eprintln! 宏,你现在已经准备好编写命令行应用程序。结合前几章的概念,你的代码将组织良好,有效地在适当的数据结构中存储数据,很好地处理错误,并经过充分测试。
This chapter recapped some of the major concepts you’ve learned so far and
covered how to perform common I/O operations in Rust. By using command line
arguments, files, environment variables, and the eprintln! macro for printing
errors, you’re now prepared to write command line applications. Combined with
the concepts in previous chapters, your code will be well organized, store data
effectively in the appropriate data structures, handle errors nicely, and be
well tested.
接下来,我们将探索一些受函数式语言影响的 Rust 特性:闭包 (closures) 和迭代器 (iterators)。
Next, we’ll explore some Rust features that were influenced by functional languages: closures and iterators.