程序通常把正常结果写入标准输出,把诊断信息写入另一条名为标准错误(stderr)的数据流。保持两条流分离,就能保存有用数据,而不会混入错误消息。
文本操作 · 第 3 课
stderr (标准错误)
学习在 Bash 中单独重定向标准错误,或将其与标准输出合并。
分离正常输出与错误
$ ls /fake/directory > peanuts.txt
ls: cannot access '/fake/directory': No such file or directory
> 只重定向 stdout。诊断信息写到仍连接终端的 stderr。同时,shell 会为 stdout 创建或清空 peanuts.txt,即使 ls 没有产生正常结果。
标准流按约定使用以下文件描述符:
0: stdin (标准输入)1: stdout (标准输出)2:stderr(标准错误)
为什么 ls /missing > results.txt 的错误通常仍显示在终端?
使用 2> 重定向 stderr
要将 stderr 重定向到文件,你需要使用文件描述符 2 后面跟上 > 运算符。此命令会将任何错误消息发送到指定的 stderr 文件。
$ ls /fake/directory 2> errors.txt
shell 会创建或清空 errors.txt,并把它连接到描述符 2。stdout 保持原目标。需要追加错误输出时,请改用 2>> errors.txt。
哪个命令会用 find /restricted 的诊断信息替换 errors.log,同时让 stdout 保持原目标?
合并 stdout 与 stderr
如果想将正常输出和错误消息都捕获到同一个文件中,该怎么办?你可以通过重定向两个流来实现这一点。
$ ls /fake/directory /etc/passwd > combined.txt 2>&1
我们来分解一下:
> combined.txt把 stdout 连接到文件。2>&1把 stderr 连接到 stdout 此刻所指向的位置。
重定向从左到右处理,因此颠倒顺序会改变结果:
$ ls /fake/directory /etc/passwd 2>&1 > regular.txt
这里 stderr 先复制 stdout 原来的终端目标,随后只有 stdout 移动到 regular.txt,两条流最终位于不同位置。
哪个 Bash 重定向会把 command 的 stdout 和 stderr 都发送到 all.log?
Bash 还提供 &> 作为用两条流替换文件的简写:
$ ls /fake/directory /etc/passwd &> combined.txt
在 Bash 中使用 &>> 可以追加两条流。显式的 > file 2>&1 形式也很重要,因为 shell 脚本和文档中经常使用它。
哪个 Bash 命令会把 build 的 stdout 和 stderr 都追加到 build.log?
有意识地丢弃数据流
有时,你可能希望运行一个命令并完全忽略任何潜在的错误消息。要做到这一点,你可以将 stderr 重定向到一个名为 /dev/null 的特殊文件,该文件会丢弃写入其中的任何数据。
$ ls /fake/directory 2> /dev/null
这不会让命令成功,也不会改变退出状态,只会隐藏诊断流。排障期间应保留或显示 stderr,而不是丢弃所需信息。
check-data 2> /dev/null 改变了什么?
要练习管理三条标准流,可以尝试这个动手实验:
- 在 Linux 中重定向输入和输出 - 在此实验中,你将学习如何在 Linux shell 中重定向输入和输出。你将通过操纵标准输出 (stdout)、标准错误 (stderr) 和标准输入 (stdin) 以及使用
>、>>、2>和tee命令等运算符来练习控制命令的数据流。
课程已完成
你已完成 stderr (标准错误)
现在,你可以让诊断信息保持独立,也可以把它与正常命令输出合并。
知道 stderr 是文件描述符 2。
使用
2>或2>>替换或追加错误日志。从左到右应用多个重定向。
使用明确的语法合并两条输出流。
只在可以接受信息丢失时丢弃诊断。