输入输出重定向与管道

在 Linux 中,每个程序运行时,系统默认会提供三条标准数据流通道:

  1. 标准输入(stdin,通道 0):程序读取输入的来源,默认来自键盘;
  2. 标准输出(stdout,通道 1):程序输出正常结果的数据流,默认显示在终端屏幕上;
  3. 标准错误(stderr,通道 2):程序输出报错信息的数据流,默认也显示在终端屏幕上。

grep 的标准输出显示在终端中

输出重定向:把结果保存到文件

在日常运维和开发中,我们经常需要把命令输出保存下来,方便后续查看、统计或分析。

最常用的重定向符号有两个:

  • >:覆盖重定向 将命令的标准输出写入指定文件。如果目标文件已经存在,会先清空旧内容,再写入新内容。

  • >>:追加重定向 将命令的标准输出追加到目标文件末尾,原有内容会被保留。

crow@opsbox:~/work$ cd ~/work
crow@opsbox:~/work$ grep -F 'member' /srv/ops/backups/2026-06/db-2026-06-30.sql > members.txt
crow@opsbox:~/work$ wc -l members.txt
160 members.txt
crow@opsbox:~/work$ head -n 2 members.txt
INSERT INTO users VALUES (4001, 'user001', 'member');
INSERT INTO users VALUES (4002, 'user002', 'member');

同一份 grep 输出改为写入 members.txt

执行重定向后,终端屏幕上不再直接显示那 160 行结果,因为它们已经被写入到了 members.txt 文件中。

管道符(|):让命令接力处理

如果我们的目标只是统计六月份备份中有多少条 member 记录,其实没必要先生成一个中间文件,再调用 wc -l 统计。

这时可以使用管道符 |,把前一个命令的输出直接作为后一个命令的输入:

crow@opsbox:~/work$ grep -F 'member' /srv/ops/backups/2026-06/db-2026-06-30.sql | wc -l
160

grep 的输出经管道成为 wc 的标准输入,最终显示 160

管道的作用,就是在内存中把命令连成一条处理流水线:左侧命令产生的数据,不需要先落盘,会直接交给右侧命令继续处理。

捕获标准错误:报错信息为什么会漏出来

有时我们会疑惑:明明已经用了 > 重定向,为什么屏幕上还是会显示报错信息?

crow@opsbox:~/work$ cat notes.txt missing-demo.txt > copied.txt
cat: missing-demo.txt: No such file or directory

原因在于,> 默认重定向的是标准输出(stdout),也就是通道 1;而程序报错通常走的是标准错误(stderr),也就是通道 2。两者默认目标并不相同。

如果希望单独保存错误信息,可以使用 2>:

crow@opsbox:~/work$ cat notes.txt missing-demo.txt > copied.txt 2> read-errors.txt
crow@opsbox:~/work$ cat read-errors.txt
cat: missing-demo.txt: No such file or directory

这样一来:

  • copied.txt 保存的是程序正常输出的内容;
  • read-errors.txt 保存的是程序报错信息。

错误去了哪里

练习

在可读的 notes.txt 和不存在的 missing-demo.txt 上执行 cat notes.txt missing-demo.txt > copied.txt 2> read-errors.txt。哪一个文件会保存“没有那个文件”的报错?只提交文件名。

提交答案

题解 Hint

如果想把正常输出和报错信息合并保存到同一个文件中,可以使用:

command > combined.txt 2>&1

这里的 2>&1 表示:把标准错误重定向到标准输出当前所在的位置。换句话说,两条数据流最终都会进入 combined.txt。