Skip to content

重定向与管道:> >> < 2> 2>&1 与 tee 详解 ​

本文是 Linux 命令速查 中"重定向 / 管道 / tee"的从 0 到 1 详解,本篇一次讲清 shell 的输入输出重定向符号 < > >> 2> 2>&1、管道 | 以及 tee 命令。 目标:把这些"看不见的数据流方向"讲清楚,多看几遍后,你就明白为什么 ls > out.txt 能把结果存文件、cmd 2>&1 | less 能连报错一起翻。 环境依据:重定向符号是 Bash shell 语法(bash 5.1.16,随 bash 提供,参考 bash 手册);tee 属 GNU coreutils 8.32(RHEL/Rocky 用法一致)。

一、命令是干什么的 ​

Linux 里每个命令默认都连着三个"通道":

  • 标准输入(stdin,编号 0):命令从这里读数据,默认是键盘;
  • 标准输出(stdout,编号 1):命令把正常结果输出到这里,默认是屏幕;
  • 标准错误(stderr,编号 2):命令把报错信息输出到这里,默认也是屏幕。

重定向就是改这些通道的指向:把本来打到屏幕的输出,改存到文件;把本来从键盘读的输入,改从文件读。管道 | 则是把上一个命令的 stdout,直接接到下一个命令的 stdin。tee 是个"三通":一份输出既给屏幕、又存进文件。

类比:普通命令像"对着屏幕说话"。> 是把它说的话录进文件;| 是把 A 说的话直接塞进 B 的耳朵让 B 接着处理;tee 像个录音笔,一边让你听见、一边录进文件。

二、命令语法 ​

重定向不是独立命令,而是写在任意命令旁边的符号:

bash
命令 < 文件          # 把文件内容作为命令的标准输入
命令 > 文件          # 把命令的标准输出写进文件(覆盖)
命令 >> 文件         # 把命令的标准输出追加到文件末尾
命令 2> 文件         # 把标准错误写进文件
命令 > 文件 2>&1     # 标准输出写文件,标准错误也并入标准输出
命令1 | 命令2        # 把命令1的输出作为命令2的输入
命令 | tee 文件      # 输出既显示在屏幕,又存进文件

三、符号与 tee 选项全表(对照 tee --help) ​

1. 输入输出重定向符号(shell 语法) ​

符号中文含义什么场景用
>把标准输出覆盖写入文件(文件不存在则新建,存在则清空)把结果存进新文件
>>把标准输出追加到文件末尾(不清空原内容)往日志里累加内容
<把文件内容作为命令的标准输入让命令从文件读而不是键盘
2>把标准错误(报错)写进文件单独保存报错日志
2>>把标准错误追加进文件累加报错日志
2>&1把标准错误并入标准输出(让两者走同一个地方)想把报错和正常输出放一起
&>标准输出和标准错误全部写进文件(> 简写)一把梭丢弃/保存全部输出
&>>全部输出追加进文件追加全部输出
> /dev/null把输出丢弃(黑洞)不想看到输出时

注意顺序:> 文件 2>&1 不能写成 2>&1 > 文件,顺序反了效果就错了(详见易错点)。

2. 管道 | ​

符号中文含义什么场景用
``把左边命令的 stdout 接到右边命令的 stdin

默认管道只传 stdout,不传 stderr;想连报错一起传,要写 2>&1 |。

3. tee 命令选项(coreutils) ​

tee 的作用是:从标准输入读,一边原样打到屏幕,一边写进文件。

选项中文含义什么场景用
-a,--append追加到文件而不是覆盖想往已有日志里累加
-i,--ignore-interrupts忽略中断信号(Ctrl+C)不想被中断打断写入
-p写非管道输出出错时给出诊断排查写入失败
--output-error=MODE设定写错误时的行为(warn/exit 等)脚本里精细控制

四、由浅入深的典型示例 ​

演示在 /tmp/sre_shard_txt 下进行。

示例 1:> 把输出存进文件(覆盖) ​

bash
echo "hello" > out1.txt
cat out1.txt
text
hello

echo 本来打印到屏幕,被 > 改存进了 out1.txt。

示例 2:>> 追加而不覆盖 ​

bash
echo "line A" >> out2.txt
echo "line B" >> out2.txt
cat out2.txt
text
line A
line B

如果用 >,第二次会把第一次的内容清掉;用 >> 是在末尾接着加。

示例 3:分开保存正常输出和报错 ​

bash
ls nosuchfile.txt >stdout.txt 2>stderr.txt

ls 找不到文件,报错走 stderr。结果:stdout.txt 是空的(没有正常输出),stderr.txt 里是报错信息:

text
stdout.txt=[] stderr.txt=[ls: cannot access 'nosuchfile.txt': No such file or directory]

这就是 stdout 和 stderr 是两条独立通道的证明。

示例 4:2>&1 把报错也收进同一个文件 ​

bash
ls nosuchfile.txt >all.txt 2>&1
cat all.txt
text
ls: cannot access 'nosuchfile.txt': No such file or directory

>all.txt 先让 stdout 进文件,2>&1 再让 stderr 跟着 stdout 走——于是报错也进了 all.txt。

示例 5:&> 一把梭(等价组合的简写) ​

bash
ls nosuchfile.txt &> all2.txt
cat all2.txt
text
ls: cannot access 'nosuchfile.txt': No such file or directory

&> 是"stdout 和 stderr 都写进文件"的简写,等价于 > 文件 2>&1。

示例 6:< 从文件读输入 ​

bash
cat < out1.txt
text
hello

平时是 cat out1.txt 把文件名当参数;这里用 < 把文件内容喂进 cat 的标准输入,效果一样。

示例 7:管道 | 串联命令 ​

bash
echo -e "a\nb\na" | sort | uniq -c
text
      2 a
      1 b

echo 的三行输出,先经 sort 排序,再经 uniq -c 计数。管道把它们像流水线一样串起来。

示例 8:tee 既看屏幕又存文件 ​

bash
echo "teed line" | tee teeout.txt
text
teed line

屏幕上立刻看到 teed line,同时它被写进了 teeout.txt。想保留日志又不想错过屏幕输出时用它。

示例 9:tee -a 追加 ​

bash
echo "second" | tee -a teeout.txt
cat teeout.txt
text
teed line
second

tee 默认覆盖,加 -a 才是追加。常用于 命令 | tee -a 日志.log。

示例 10:tee 同时写多个文件 ​

bash
echo "multi" | tee f1.txt f2.txt >/dev/null
cat f1.txt f2.txt
text
multi
multi

一份输入同时写进 f1.txt 和 f2.txt。

五、高频组合速记 ​

命令用途
命令 > 文件输出覆盖存文件
命令 >> 文件输出追加存文件
命令 2> 文件报错单独存文件
命令 &> 文件正常输出 + 报错全存文件
命令 > 文件 2>&1同上的老式写法
命令 > /dev/null丢弃输出
命令1 | 命令2把输出交给下一个命令
命令 2>&1 | less连报错一起分页看
命令 | tee 文件屏幕看 + 存一份
命令 | tee -a 日志屏幕看 + 追加进日志

六、RHEL 系与 Debian 系差异 ​

  • 重定向符号是 bash(shell)语法,RHEL 系(bash)与 Debian 系(bash)完全一致;即使换 zsh 也基本兼容。
  • tee 属 coreutils,两系用法一致。
  • 唯一细微差别:有的系统默认 shell 是 sh(dash)而不是 bash,但上面这些基本重定向符号 POSIX 通用,写法不变。

七、新手易错点 ​

  1. > 会先清空文件:命令 > 文件 如果命令就是读这个文件本身,会先把文件清空!要写回用 tee 或临时文件。
  2. 2>&1 的顺序很关键:必须写成 > 文件 2>&1;写成 2>&1 > 文件 会先让 stderr 指向当前屏幕,再把 stdout 改去文件,结果报错还是上屏幕。
  3. 管道默认不传 stderr:cmd | less 看不到 cmd 的报错,要 cmd 2>&1 | less。
  4. tee 默认覆盖:想累加日志记得 -a。
  5. >> 才是追加:> 是覆盖,写错会把原有日志冲掉。
  6. /dev/null 是黑洞:命令 > /dev/null 表示"别给我看输出",常配合 2>&1 变成 &> /dev/null。
  7. 危险提示:> 指向的目标文件若已有重要内容会被直接清空,重定向前确认目标路径。

八、相关命令与文档 ​