如何使用 'tee' 捕获标准错误

LinuxBeginner
立即练习

介绍

本教程将指导你使用 Linux 标准流,重点关注理解和管理标准错误(stderr)流。你将学习如何使用强大的 tee 命令来捕获和处理 stderr 输出,这是一项在 Linux 系统中进行错误处理和日志记录的宝贵技能。

理解 Linux 标准流

Linux 使用三个基本流来处理输入和输出操作。这些流构成了程序在 Linux 环境中进行通信的基础。

什么是标准流?

在你的 Linux 环境中打开一个终端。我们将通过实际例子来探索标准流的概念。

标准流是连接程序与其环境的通信通道。Linux 有三个标准流:

  1. 标准输入(stdin) - 文件描述符 0
  2. 标准输出(stdout) - 文件描述符 1
  3. 标准错误(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)

这个复杂的命令:

  1. 运行你的脚本
  2. 将 stdout 重定向到 tee stdout.log,这会在屏幕上显示它并保存到文件中
  3. 将 stderr 重定向到 tee stderr.log >&2,这会在屏幕上显示它并保存到文件中

检查结果:

cat stdout.log
cat stderr.log

你应该在 stdout.log 中看到常规输出,在 stderr.log 中看到错误消息。

创建一个完整的错误日志

为了进行全面的日志记录,你可能希望:

  1. 将正常输出发送到屏幕
  2. 将错误发送到屏幕和日志文件
  3. 为错误添加时间戳,以便于跟踪

让我们创建一个脚本来演示这一点:

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)

这将:

  1. 在屏幕上显示所有输出(stdout 和 stderr)
  2. 另外在 error_log.txt 文件中捕获 stderr

检查错误日志:

cat error_log.txt

你应该只看到带有时间戳的错误消息,这使得它们易于跟踪。

实际应用:带有进度和错误处理的命令

让我们创建一个实际的例子,下载一个文件,在屏幕上显示进度,同时记录错误:

wget https://example.com/nonexistent_file.txt 2> >(tee -a download_errors.log >&2)

此命令:

  1. 尝试下载一个不存在的文件
  2. 在屏幕上显示所有输出,包括进度和错误
  3. 另外将任何错误记录到 download_errors.log

检查错误日志:

cat download_errors.log

错误日志仅包含来自失败下载尝试的错误消息。

这些技术允许你使用标准的 Linux 命令构建复杂的错误处理和日志记录系统。

总结

在本教程中,你学习了在 Linux 中管理标准流的基本技术,重点是使用 tee 命令进行错误处理。你现在了解:

  • Linux 中的三个标准流:stdin、stdout 和 stderr
  • 如何使用 tee 命令捕获输出,同时在屏幕上显示它
  • 如何将 stderr 重定向到 stdout,并使用 tee 捕获两者
  • 用于分离和记录不同输出流的高级技术
  • 如何在实际场景中实现实际的错误日志记录

这些技能对于在 Linux 环境中创建健壮的脚本、排除应用程序故障和维护全面的日志非常有用。有效管理标准错误输出的能力将帮助你开发更专业和可维护的 Linux 应用程序。