下面以 Ubuntu(实际上是通用 GNU/Linux)环境为背景,系统地讲解 tee 命令的用法和原理。内容会从基础到进阶,包含常见例子和一些实用技巧。
一、tee 是什么?
tee 是一个标准的 Unix/Linux 命令,用来:
从标准输入读取数据,同时把数据输出到标准输出(通常是终端)和一个或多个文件中。
很像英文里的 "T 字接头":
- 一端接收输入(管道中上一个命令的输出),
- 一端继续往下传(标准输出),
- 另一端分流到文件中保存。
典型语法
bash
tee [OPTION]... [FILE]...
常用选项:
-a, --append:以追加方式写入文件(不覆盖原内容)-i, --ignore-interrupts:忽略中断信号(Ctrl+C 等)--help:显示帮助信息--version:显示版本信息(来自 coreutils)
二、最基本用法:边看边保存输出
示例 1:保存命令输出到文件,同时在终端显示
bash
ls -l | tee output.txt
效果:
- 你在终端照样能看到
ls -l的输出; - 同时输出内容被写入到
output.txt中; - 默认是覆盖写入(每次都会重写该文件)。
如果你用的是重定向:
bash
ls -l > output.txt
则输出只会写入文件,不会在屏幕上显示 。
而 tee 是"保留屏幕显示 + 另存为文件"。
三、追加写入而不是覆盖:-a
tee 默认会覆盖文件内容,如果你希望将输出追加到文件末尾,使用 -a。
bash
ls -l | tee -a output.txt
多次执行后,output.txt 会不断增加内容,而不会被清空。
典型场景:
- 一天中多次运行同一脚本,想把每次的日志都追加进同一个日志文件;
- 分步骤执行命令,把每一步的输出续写到一个汇总文件中。
四、写入多个文件
tee 可以同时写入多个文件(包括追加的情况):
bash
echo "hello" | tee file1.txt file2.txt
输出:
- 终端显示
hello file1.txt内容为hellofile2.txt内容为hello
结合 -a:
bash
echo "another line" | tee -a file1.txt file2.txt
两个文件都会追加这行内容。
五、实际应用场景
1. 保存命令执行过程(日志记录)
示例:保存安装日志
bash
sudo apt update | tee apt-update.log
sudo apt upgrade | tee -a apt-update.log
- 第一个命令:新建日志文件并写入
apt update的输出; - 第二个命令:把
apt upgrade的输出追加到同一个日志中。
2. 一边查看日志,一边保存日志
bash
dmesg | tee dmesg.log
- 你能看到
dmesg输出; - 同时保存到
dmesg.log。
比起:
bash
dmesg > dmesg.log
的优点是:操作过程可视化,不用等命令结束后再看文件。
3. 与 sudo 配合:在需要 root 权限写文件时
这是 tee 非常常用、也非常"关键"的用途。
问题:重定向符号 > 不受 sudo 保护
bash
sudo echo "something" > /etc/someconfig.conf
看起来像是"用 root 权限写文件",
但实际上:
sudo只作用在echo;- 重定向
>是由 当前 shell 执行的,仍然用的是普通用户权限; - 这通常会报错:
Permission denied。
正确做法:用 tee 提升写入权限
bash
echo "something" | sudo tee /etc/someconfig.conf
echo以普通用户运行即可;tee在sudo权限下运行,可以写受限文件;- 内容仍会显示在终端。
如果不想让内容在终端重复出现(特别是配置内容很多时),可以重定向 tee 的标准输出到 /dev/null:
bash
echo "something" | sudo tee /etc/someconfig.conf > /dev/null
或
bash
echo "something" | sudo tee -a /etc/someconfig.conf >/dev/null
再强调一遍:需要 root 权限写文件 + 又想用管道 时,几乎都用这类模式。
4. 长时间命令的"实时备份输出"
例如你在运行一个耗时很久的编译命令:
bash
make 2>&1 | tee build.log
这里 2>&1 是把标准错误(2)重定向到标准输出(1),然后一起交给 tee。
好处:
- 终端实时看到所有编译信息(包括错误信息);
- 日志完整 保存到
build.log,方便之后搜索。 - 如果终端断开、滚动太多看不全------没关系,日志都在文件里。
六、tee 与重定向/管道的配合
1. 同时保存和继续做后续处理
tee 输出到标准输出的内容,还可以继续通过管道传给后续命令。
bash
ls -l | tee ls.log | grep "txt"
流程:
ls -l的结果进入tee;tee把结果 写入文件ls.log;- 同时把同样的数据传给下一个命令
grep "txt"; - 最终你只在终端看到
grep过滤后的内容,但ls.log中保存的是完整列表。
这是 tee 一个很典型的作用:
中途拦截数据,做一份"备份",但又不打断原有管道的流程。
七、常见选项:-i 忽略中断
bash
some-command | tee -i output.log
-i (--ignore-interrupts):让 tee 忽略中断信号(SIGINT),一般是避免因为你按了 Ctrl+C 导致 tee 中途退出。
实际使用中这个选项不算特别常用,但在某些长时间运行的管道场景下会涉及。
八、与文本处理工具联合使用的例子
1. 同时统计 + 保存完整数据
假设你有一个很长的日志流:
bash
journalctl -f | tee full.log | grep "error"
full.log:保存全部日志;- 终端上只显示含有
"error"的行; - 日志写入是实时的。
2. 格式化后保存
bash
ps aux | tee ps_raw.log | awk '{print $1, $2, $11}' | tee ps_short.log
这里用了两次 tee:
- 第一次保存"原始的进程信息"到
ps_raw.log; - 然后用
awk抽取字段; - 再保存"简化版的进程列表"到
ps_short.log。
九、tee 与权限、shell 的一些细节
tee写文件的权限 取决于运行tee的用户,而不是管道前面那个命令。>、>>是shell 的内建语法 ,和tee是普通程序有本质区别。- 用
sudo,要注意要放在tee前面 :- ✅
echo xxx | sudo tee file - ❌
sudo echo xxx | tee file(重定向还是普通权限)
- ✅
十、与 /dev/tee 无关
有些人会把 tee 和某些设备节点混淆,实际:
tee是一个用户空间程序(通常在/usr/bin/tee)- 它不是一个设备文件(和
/dev/null、/dev/zero不同)
十一、简单对比:tee vs 重定向
| 功能需求 | 推荐用法 |
|---|---|
| 只写文件,不显示在终端 | cmd > file |
| 只追加文件,不显示终端 | cmd >> file |
| 显示在终端 + 覆盖写文件 | `cmd |
| 显示在终端 + 追加写文件 | `cmd |
| root 权限写文件(管道中) | `cmd |
| 中途"分流"输出给后续命令 | `cmd |
十二、在 Ubuntu 中查看 tee 的帮助
你可以在终端里直接查看完整文档:
bash
man tee
或简单帮助:
bash
tee --help