主题
重定向与管道:> >> < 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.txttext
hello
echo本来打印到屏幕,被>改存进了out1.txt。
示例 2:>> 追加而不覆盖
bash
echo "line A" >> out2.txt
echo "line B" >> out2.txt
cat out2.txttext
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.txttext
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.txttext
ls: cannot access 'nosuchfile.txt': No such file or directory
&>是"stdout 和 stderr 都写进文件"的简写,等价于> 文件 2>&1。
示例 6:< 从文件读输入
bash
cat < out1.txttext
hello平时是
cat out1.txt把文件名当参数;这里用<把文件内容喂进cat的标准输入,效果一样。
示例 7:管道 | 串联命令
bash
echo -e "a\nb\na" | sort | uniq -ctext
2 a
1 b
echo的三行输出,先经sort排序,再经uniq -c计数。管道把它们像流水线一样串起来。
示例 8:tee 既看屏幕又存文件
bash
echo "teed line" | tee teeout.txttext
teed line屏幕上立刻看到
teed line,同时它被写进了teeout.txt。想保留日志又不想错过屏幕输出时用它。
示例 9:tee -a 追加
bash
echo "second" | tee -a teeout.txt
cat teeout.txttext
teed line
second
tee默认覆盖,加-a才是追加。常用于命令 | tee -a 日志.log。
示例 10:tee 同时写多个文件
bash
echo "multi" | tee f1.txt f2.txt >/dev/null
cat f1.txt f2.txttext
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 通用,写法不变。
七、新手易错点
>会先清空文件:命令 > 文件如果命令就是读这个文件本身,会先把文件清空!要写回用tee或临时文件。2>&1的顺序很关键:必须写成> 文件 2>&1;写成2>&1 > 文件会先让 stderr 指向当前屏幕,再把 stdout 改去文件,结果报错还是上屏幕。- 管道默认不传 stderr:
cmd | less看不到cmd的报错,要cmd 2>&1 | less。 tee默认覆盖:想累加日志记得-a。>>才是追加:>是覆盖,写错会把原有日志冲掉。/dev/null是黑洞:命令 > /dev/null表示"别给我看输出",常配合2>&1变成&> /dev/null。- 危险提示:
>指向的目标文件若已有重要内容会被直接清空,重定向前确认目标路径。
八、相关命令与文档
- 速查页:Linux 命令速查
- 管线上游的查看命令:
cat(cat)、head(head)、tail(tail) - 管线下游的处理命令:
grep(grep)、sort(sort)、uniq(uniq)、awk(awk) - Shell 输入输出与环境基础:见 Linux Shell 专题