tee
tee 从标准输入读取数据,原样写到标准输出,同时复制一份写入一个或多个文件。名字来自水管的 T 形三通接头:数据一路继续流向屏幕或下一个命令,另一路分出来存进文件,常用于“既要看到输出,又要留下记录”的场景。
command | tee [选项] [文件...]文件:输出目标,可以写多个;默认覆盖已有内容- 不给文件时,tee 等同于
cat,只把输入原样输出
tee 只从标准输入读数据,命令行上的文件参数全部是写入目标,不是输入来源
┌──────────► 标准输出(屏幕 / 下一个命令)stdin ──► tee ──┤ └──────────► 文件1、文件2 ...tee 每读到一块数据,就依次写给标准输出和所有文件。它只能接到管道传过来的 stdout,stderr 默认不经过管道,需要先用 2>&1 合并,见 标准 IO 与重定向
| 选项 | 含义 |
|---|---|
-a |
追加到文件末尾,而不是覆盖 |
-i |
忽略中断信号 SIGINT(Ctrl + C) |
-p |
下游管道关闭时不报错退出,继续写其余文件(GNU coreutils) |
1. 边看边保存
ls /etc | tee etc-list.txt屏幕上照常显示目录列表,同时完整保存到 etc-list.txt
2. 追加而不是覆盖(-a)
echo "第一行" | tee log.txtecho "第二行" | tee -a log.txtcat log.txtlog.txt 的内容:
第一行第二行不加
-a时,第二条命令会把log.txt清空后再写入,只剩“第二行”
3. 同时写入多个文件
echo hello | tee a.txt b.txt屏幕输出一行 hello,a.txt 和 b.txt 里也各有一行 hello
4. 在管道中间保存中间结果
grep "ERROR" app.log | tee errors.txt | wc -l输出:
2errors.txt:保存了所有 ERROR 行- 屏幕:只显示
wc -l统计出的行数
tee 放在管道中间不会截断数据流,下游命令拿到的是完整输入
5. 连同错误输出一起记录(2>&1)
make 2>&1 | tee build.log- 不加
2>&1:编译错误走 stderr,不经过管道,屏幕上能看到,但build.log里没有 - 加了
2>&1:stderr 合并进 stdout,一起交给 tee,日志才完整
6. 用 sudo 写入需要 root 权限的文件
# 错误:Permission deniedsudo echo "127.0.0.1 test.local" >> /etc/hosts
# 正确echo "127.0.0.1 test.local" | sudo tee -a /etc/hosts > /dev/null- 第一种写法里,
>>重定向由当前 shell(普通用户)处理,sudo 只提升了echo的权限 - 第二种写法里,真正打开文件的是
tee,而tee以 root 身份运行 - 末尾
> /dev/null:丢弃 tee 打印到屏幕的那一份
同样的道理,在 vim 里忘了用 sudo 打开文件时,可以用
:w !sudo tee % > /dev/null保存
7. 把同一份数据交给多个命令(进程替换)
cat access.log | tee >(grep -c 404 > n404.txt) | wc -l>(...)是 bash / zsh 的进程替换,tee 把它当作一个“文件”写入- 一份输入同时被
grep -c 404和wc -l处理,不用读两遍文件
进程替换里的命令是异步执行的,主命令结束时它可能还没写完
管道的退出状态
Section titled “管道的退出状态”管道的退出状态默认取最后一个命令,tee 几乎总是成功,所以前面的命令失败会被掩盖:
make 2>&1 | tee build.logecho $? # 0,即使 make 失败了
echo ${PIPESTATUS[0]} # bash:取管道中第 1 个命令的退出状态set -o pipefail # 或者:管道中任一命令失败,整个管道就失败在脚本里用
cmd | tee log时,记得加set -o pipefail,否则&&和if的判断都会失效
tee 与重定向的区别
Section titled “tee 与重定向的区别”| 写法 | 屏幕显示 | 文件 |
|---|---|---|
cmd > file |
否 | 覆盖写入 |
cmd >> file |
否 | 追加写入 |
cmd | tee file |
是 | 覆盖写入 |
cmd | tee -a file |
是 | 追加写入 |
man tee- GNU Coreutils - tee