介绍
在本实验中,你将学习在 Linux 终端中重定向输入和输出的基础技术。你将探索如何通过操作三个标准流:标准输出(stdout)、标准错误(stderr)和标准输入(stdin)来控制命令的数据流。本实验提供了关于核心重定向操作符的动手实践,使你能够保存命令输出、管理错误消息以及从文件中为命令提供输入。
在整个练习过程中,你将使用 > 操作符将命令输出发送到文件(会覆盖现有内容),并使用 >> 操作符在不丢失数据的情况下追加输出。你还将学习如何使用 2> 专门重定向错误消息,以及如何将标准输出和标准错误合并到单个文件中。最后,你将使用 tee 命令在屏幕上显示输出的同时将其保存到文件中,并练习使用 < 操作符重定向标准输入,使命令从文件而不是键盘读取数据。
使用 > 操作符重定向标准输出
在这一步中,你将学习如何重定向命令的标准输出。在 Linux 终端中,大多数命令都会产生一些输出。默认情况下,这些被称为「标准输出」(Standard Output,简称 stdout)的内容会显示在你的终端屏幕上。但是,你可以使用 > 操作符将此输出重定向到文件。这对于保存命令结果、创建日志文件或生成报告非常有用。
首先,让我们执行一个简单的命令并在终端上查看其输出。
echo "Hello from LabEx"
你应该直接在终端中看到以下输出:
Hello from LabEx
现在,让我们将此输出重定向到文件中。我们将使用 > 操作符,后跟一个文件名。这会告诉终端将 echo 命令的输出发送到当前目录(~/project)中名为 hello.txt 的文件。
执行以下命令:
echo "Hello from LabEx" > hello.txt
请注意,这次你在终端上看不到任何输出。这是因为输出已被发送到 hello.txt 文件中。你可以使用 cat 命令验证文件的内容:
cat hello.txt
输出将显示被重定向的文本:
Hello from LabEx
如果文件不存在,> 操作符将创建该文件。请注意,如果文件已经存在,> 操作符将覆盖其全部内容,且不会发出任何警告。让我们来看看实际效果。
首先,让我们列出当前目录的内容并将其保存到名为 file_list.txt 的新文件中。
ls -l > file_list.txt
现在,查看 file_list.txt 的内容:
cat file_list.txt
你将看到项目目录中的文件列表,内容应该类似于:
total 4
-rw-rw-r-- 1 labex labex 0 Jun 25 14:56 file_list.txt
-rw-rw-r-- 1 labex labex 17 Jun 25 14:56 hello.txt
现在,让我们运行一个不同的命令并将其输出重定向到同一个文件 file_list.txt。
echo "This is new content." > file_list.txt
如果你再次检查 file_list.txt 的内容,你会发现原始的文件列表已被替换。
cat file_list.txt
现在的输出是:
This is new content.
这演示了 > 操作符的覆盖行为。在下一步中,你将学习如何在不覆盖文件的情况下将输出追加到文件中。
使用 >> 操作符追加标准输出
在这一步中,你将学习如何在不删除文件现有内容的情况下,将输出添加到文件的末尾。在前面的步骤中,你看到了 > 操作符会覆盖目标文件。为了避免这种情况,你可以使用追加操作符 >>。这个操作符对于维护运行日志文件等任务非常有用,因为你希望随着时间的推移不断添加新条目。
让我们先创建一个带有初始内容的文件,命名为 greetings.txt。
echo "Hello, this is the first line." > greetings.txt
现在,验证其内容:
cat greetings.txt
输出应该是:
Hello, this is the first line.
接下来,我们不覆盖文件,而是使用 >> 操作符向其中追加一行新内容。
echo "This is the second line, appended." >> greetings.txt
再次检查 greetings.txt 的内容。
cat greetings.txt
这一次,你会看到新行已添加到原始内容之后:
Hello, this is the first line.
This is the second line, appended.
>> 操作符非常适合创建日志文件。让我们创建一个名为 activity.log 的简单日志文件,并使用 date 命令向其中添加时间戳。
date > activity.log
现在,让我们向同一个文件追加另一个时间戳。
date >> activity.log
查看最终的 activity.log 文件以查看这两个条目。
cat activity.log
输出将显示两个时间戳,证明第二个命令追加了其输出而不是覆盖了文件。具体时间会有所不同。
Wed Jun 25 14:56:53 CST 2025
Wed Jun 25 14:56:56 CST 2025
这展示了 >> 如何保留现有数据并将新数据添加到文件末尾,使其成为更新文件信息的安全方式。
使用 2> 操作符重定向标准错误
在这一步中,你将学习如何管理错误消息。除了标准输出(stdout)之外,命令还会产生另一种类型的输出,称为「标准错误」(Standard Error,简称 stderr)。这是一个专门用于错误消息和诊断信息的独立流。默认情况下,stdout 和 stderr 都会显示在你的终端上,但你目前学到的重定向操作符(> 和 >>)仅影响 stdout。
要重定向 stderr,你需要指定其文件描述符,即 2。> 操作符实际上是 1> 的简写,其中 1 是 stdout 的文件描述符。因此,要重定向 stderr,你需要使用 2>。
让我们生成一个错误来看看实际效果。我们将尝试列出一个不存在的文件。
ls non_existent_file
该命令将失败并在终端打印错误消息:
ls: cannot access 'non_existent_file': No such file or directory
现在,让我们尝试使用标准的 > 操作符来重定向它。
ls non_existent_file > output.txt
请注意,错误消息仍然打印在终端上。> 操作符没有捕获到它。如果你检查 output.txt 文件,你会发现它是空的。
cat output.txt
该命令没有产生输出,因为没有生成标准输出,只生成了标准错误。
现在,让我们使用 2> 正确地将标准错误重定向到名为 error.log 的文件中。
ls non_existent_file 2> error.log
这一次,终端上没有出现任何消息。错误已被成功重定向。你可以查看 error.log 的内容来查看捕获的消息。
cat error.log
输出将是来自 ls 命令的错误消息:
ls: cannot access 'non_existent_file': No such file or directory
就像 >> 追加标准输出一样,你可以使用 2>> 将标准错误追加到文件中。让我们尝试列出另一个不存在的文件,并将错误追加到我们的 error.log 中。
ls another_fake_file 2>> error.log
现在,再次检查 error.log 的内容。
cat error.log
你会看到新的错误消息已添加到文件末尾。
ls: cannot access 'non_existent_file': No such file or directory
ls: cannot access 'another_fake_file': No such file or directory
这种技术对于将正常输出与错误消息分开非常有用,允许你记录错误以便以后查看,而不会弄乱你的主输出文件。
将 stdout 和 stderr 同时重定向到单个文件
在这一步中,你将学习如何将命令的所有输出(包括标准输出和标准错误)捕获到单个文件中。当你想要完整记录脚本或命令的执行情况(包括发生的任何错误)时,这特别有用。
让我们使用一个同时产生 stdout 和 stderr 的命令。我们将尝试列出一个存在的文件(/etc/passwd)和一个不存在的文件(non_existent_file)。
ls -l /etc/passwd non_existent_file
你将在终端上看到两种类型的输出。第一行是标准错误,第二行是标准输出。
ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18 2024 /etc/passwd
如果你尝试仅使用 > 重定向 stdout,错误消息仍会出现在屏幕上。
ls -l /etc/passwd non_existent_file > output_only.txt
终端上的输出:
ls: cannot access 'non_existent_file': No such file or directory
而 output_only.txt 将仅包含标准输出:
cat output_only.txt
-rw-r--r-- 1 root root 1916 Jul 18 2024 /etc/passwd
要将这两个流都重定向到一个文件,你可以使用 &> 操作符。这是一个方便的简写,它将 stdout(文件描述符 1)和 stderr(文件描述符 2)都发送到指定的文件。
让我们试一试。我们将所有输出重定向到名为 combined.log 的文件中。
ls -l /etc/passwd non_existent_file &> combined.log
这一次,终端上没有打印任何内容。所有输出都已捕获在 combined.log 中。让我们查看其内容:
cat combined.log
你会看到该文件同时包含了标准输出和标准错误:
ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18 2024 /etc/passwd
还有一种更传统但稍微复杂一点的语法可以实现相同的结果:> file 2>&1。让我们分解一下:
> file:这将标准输出(文件描述符 1)重定向到file。2>&1:这将标准错误(文件描述符 2)重定向到与标准输出(文件描述符 1)相同的位置。由于stdout已经指向file,因此stderr也会被发送到那里。
让我们尝试这种方法,将输出保存到 combined_traditional.log。
ls -l /etc/passwd non_existent_file > combined_traditional.log 2>&1
同样,终端上没有出现输出。验证文件内容显示相同的结果:
cat combined_traditional.log
ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18 2024 /etc/passwd
虽然 &> 更短且通常是首选,但你经常会在旧脚本中看到 2>&1,因此理解它的作用非常重要。要追加这两个流,可以使用 &>> 或 >> file 2>&1。
使用 tee 分流输出并使用 < 重定向标准输入
在最后一步中,你将探索两个互补的重定向概念:使用 tee 命令分流输出,以及使用 < 操作符从文件中为命令提供输入。
使用 tee 分流输出
有时,你希望将命令的输出保存到文件中,同时在终端上查看它。> 和 >> 操作符会将输出排他性地重定向到文件,从而在屏幕上隐藏它。tee 命令通过分流输出来解决这个问题,将其同时发送到文件和标准输出(你的屏幕)。它的名字源于管道工程中的 T 型接头,它可以将流分成两条路径。
让我们看看它的实际应用。我们将列出 /etc/ 目录的内容,并使用 tee 将列表显示在屏幕上,同时保存到名为 etc_listing.txt 的文件中。
ls /etc/ | tee etc_listing.txt
你将看到完整的目录列表打印在终端上。与此同时,tee 命令已将完全相同的输出写入 etc_listing.txt。你可以验证这一点:
cat etc_listing.txt
文件的内容将与你在屏幕上看到的内容一致。
默认情况下,tee 会覆盖目标文件。要改为追加到文件,请使用 -a 选项。这对于日志记录非常有用。让我们创建一个日志文件并追加两个条目。
date | tee system_log.txt
echo "User labex performed a system check." | tee -a system_log.txt
第一个命令创建了包含当前日期的 system_log.txt。第二个命令使用 tee -a 追加了一行新内容,而没有删除日期。让我们检查最终的文件:
cat system_log.txt
输出将显示两行内容:
Wed Jun 25 14:56:53 CST 2025
User labex performed a system check.
使用 < 重定向标准输入
现在让我们看看输出重定向的反面:重定向标准输入(stdin)。许多命令(如 sort、wc 或 cat)可以从 stdin(通常是你的键盘)读取数据。< 操作符允许你告诉命令改为从文件中获取输入。
首先,让我们创建一个包含项目列表的简单文件。我们将其命名为 items.txt。
echo "banana" > items.txt
echo "apple" >> items.txt
echo "cherry" >> items.txt
现在我们有一个包含三个未排序项目的 items.txt 文件。sort 命令可以对文本行进行排序。让我们使用 < 将 items.txt 输入到 sort 命令中。
sort < items.txt
该命令将读取 items.txt 的内容作为其输入,对其进行排序,并将结果打印到其标准输出(终端):
apple
banana
cherry
这在功能上类似于运行 sort items.txt,但它展示了将文件重定向到命令标准输入的强大概念。当处理那些只能从 stdin 读取且不接受文件名作为参数的命令时,这一点变得至关重要。
作为最后一个例子,考虑 cat < items.txt。这告诉 cat 从 items.txt 读取输入,由于 cat 的工作是将输入打印到输出,因此它会在屏幕上显示文件的内容。
cat < items.txt
到此为止,我们完成了对 Linux 中基础 I/O 重定向的介绍。你现在已经掌握了控制命令输入来源和输出去向的工具。
总结
在本实验中,你学习了在 Linux 中重定向命令输出的基础知识。你首先使用 > 操作符将命令的标准输出(stdout)发送到文件,并注意到如果目标文件已存在,该操作符会覆盖它。为了避免覆盖,你使用了 >> 操作符将输出追加到文件末尾。你还练习了使用 2> 操作符将标准错误(stderr)重定向到文件,这对于将错误消息与标准输出分开捕获非常有用。
此外,本实验还演示了如何通过将 stdout 和 stderr 同时重定向到单个文件来结合这些概念,以便进行全面的日志记录。你探索了 tee 命令作为分流输出的方法,使其在保存到文件的同时能够显示在终端上。最后,你学习了使用 < 操作符重定向标准输入(stdin),使命令能够从文件而不是键盘读取输入。



