介绍
本教程将指导你使用 Linux 标准流,重点关注理解和管理标准错误(stderr)流。你将学习如何使用强大的 tee 命令来捕获和处理 stderr 输出,这是一项在 Linux 系统中进行错误处理和日志记录的宝贵技能。
理解 Linux 标准流
Linux 使用三个基本流来处理输入和输出操作。这些流构成了程序在 Linux 环境中进行通信的基础。
什么是标准流?
在你的 Linux 环境中打开一个终端。我们将通过实际例子来探索标准流的概念。
标准流是连接程序与其环境的通信通道。Linux 有三个标准流:
- 标准输入(stdin) - 文件描述符 0
- 标准输出(stdout) - 文件描述符 1
- 标准错误(stderr) - 文件描述符 2
让我们通过一些简单的命令来了解这些流的实际应用。
演示标准输入(stdin)
标准输入是程序接收数据的方式,通常来自键盘输入。
在你的终端中输入以下命令:
cat
现在输入任何文本并按 Enter 键。cat 命令从 stdin 读取并将其输出到 stdout。再输入几行文本。
要退出 cat 命令,请按 Ctrl+D(这表示文件结束)。
演示标准输出(stdout)
标准输出是程序发送其正常输出的地方。
运行此命令:
echo "This message goes to standard output"
你应该看到:
This message goes to standard output
echo 命令将文本发送到 stdout,stdout 显示在你的终端上。
演示标准错误(stderr)
标准错误是程序发送错误消息和警告的地方。
运行此命令以生成一个错误:
ls /nonexistent_directory
你应该看到类似于以下内容的错误消息:
ls: cannot access '/nonexistent_directory': No such file or directory
此错误消息被发送到 stderr,但它像 stdout 一样显示在你的终端上。
区分 stdout 和 stderr
为了了解 stdout 和 stderr 之间的区别,让我们将它们分别重定向:
ls /home /nonexistent_directory > output.txt 2> error.txt
现在检查每个文件的内容:
cat output.txt
cat error.txt
你应该看到 output.txt 包含 /home 目录的列表,而 error.txt 包含不存在目录的错误消息。
理解这些流的工作方式对于控制 Linux 中的程序输入和输出至关重要。
介绍 tee 命令
现在你已经了解了标准流,让我们来学习 tee 命令,它提供了一种管理这些流的强大方法。
什么是 tee 命令?
Linux 中的 tee 命令接收输入,并同时将其发送到标准输出和一个或多个文件。它的名字来源于管道中使用的 T 型分流器,该分流器将水流分成两个方向。
让我们通过一个基本示例来探索 tee 的工作原理:
echo "Hello, tee command" | tee hello.txt
你应该看到:
Hello, tee command
此文本显示在你的终端上,并且也被保存到 hello.txt 中。通过检查文件来确认这一点:
cat hello.txt
将 tee 与标准输出结合使用
让我们看看如何将 tee 与程序输出一起使用:
ls -la ~ | tee home_contents.txt
此命令列出你主目录的内容,将其显示在屏幕上,并将其保存到 home_contents.txt。
使用 tee 进行基本错误处理
默认情况下,tee 仅捕获标准输出。为了同时捕获标准错误,我们需要首先将 stderr 重定向到 stdout。
尝试此示例:
ls /home /nonexistent_directory 2>&1 | tee mixed_output.txt
2>&1 部分将 stderr(文件描述符 2)重定向到 stdout(文件描述符 1),从而合并了这两个流。然后,tee 命令捕获此合并的输出。
检查文件的内容:
cat mixed_output.txt
你应该在文件中看到目录列表和错误消息。
追加输出而不是覆盖
如果你想追加到文件而不是覆盖它,请使用 -a 选项:
echo "First line" | tee log.txt
echo "Second line" | tee -a log.txt
检查内容:
cat log.txt
你应该在文件中看到这两行,因为第二个命令追加到了文件,而不是覆盖它。
使用 tee 进行高级错误处理
现在你已经了解了 tee 的基础知识,让我们探索更多用于错误处理和日志记录的高级用法。
分离标准输出和标准错误
有时你希望分别捕获 stdout 和 stderr,同时仍然在终端上显示两者。让我们创建一个生成这两种类型输出的脚本:
nano test_script.sh
将以下内容添加到脚本中:
#!/bin/bash
echo "This is standard output"
echo "This is standard error" >&2
ls /home
ls /nonexistent_directory
保存文件(按 Ctrl+O,然后按 Enter)并退出(按 Ctrl+X)。
使脚本可执行:
chmod +x test_script.sh
现在运行脚本,分别捕获 stdout 和 stderr:
./test_script.sh > >(tee stdout.log) 2> >(tee stderr.log >&2)
这个复杂的命令:
- 运行你的脚本
- 将 stdout 重定向到
tee stdout.log,这会在屏幕上显示它并保存到文件中 - 将 stderr 重定向到
tee stderr.log >&2,这会在屏幕上显示它并保存到文件中
检查结果:
cat stdout.log
cat stderr.log
你应该在 stdout.log 中看到常规输出,在 stderr.log 中看到错误消息。
创建一个完整的错误日志
为了进行全面的日志记录,你可能希望:
- 将正常输出发送到屏幕
- 将错误发送到屏幕和日志文件
- 为错误添加时间戳,以便于跟踪
让我们创建一个脚本来演示这一点:
nano logging_script.sh
添加以下内容:
#!/bin/bash
## Function to generate a timestamp
timestamp() {
date +"%Y-%m-%d %H:%M:%S"
}
## Echo with timestamp to stderr
echo_error() {
echo "$(timestamp) - ERROR: $1" >&2
}
## Normal output
echo "Starting the script"
## Error output
echo_error "Something went wrong"
## More normal output
echo "Script continuing despite the error"
## Another error
echo_error "Another issue occurred"
## Final output
echo "Script completed"
保存并使脚本可执行:
chmod +x logging_script.sh
现在使用错误日志记录运行它:
./logging_script.sh 2> >(tee -a error_log.txt >&2)
这将:
- 在屏幕上显示所有输出(stdout 和 stderr)
- 另外在
error_log.txt文件中捕获 stderr
检查错误日志:
cat error_log.txt
你应该只看到带有时间戳的错误消息,这使得它们易于跟踪。
实际应用:带有进度和错误处理的命令
让我们创建一个实际的例子,下载一个文件,在屏幕上显示进度,同时记录错误:
wget https://example.com/nonexistent_file.txt 2> >(tee -a download_errors.log >&2)
此命令:
- 尝试下载一个不存在的文件
- 在屏幕上显示所有输出,包括进度和错误
- 另外将任何错误记录到
download_errors.log
检查错误日志:
cat download_errors.log
错误日志仅包含来自失败下载尝试的错误消息。
这些技术允许你使用标准的 Linux 命令构建复杂的错误处理和日志记录系统。
总结
在本教程中,你学习了在 Linux 中管理标准流的基本技术,重点是使用 tee 命令进行错误处理。你现在了解:
- Linux 中的三个标准流:stdin、stdout 和 stderr
- 如何使用
tee命令捕获输出,同时在屏幕上显示它 - 如何将 stderr 重定向到 stdout,并使用
tee捕获两者 - 用于分离和记录不同输出流的高级技术
- 如何在实际场景中实现实际的错误日志记录
这些技能对于在 Linux 环境中创建健壮的脚本、排除应用程序故障和维护全面的日志非常有用。有效管理标准错误输出的能力将帮助你开发更专业和可维护的 Linux 应用程序。



