tee 是什么
tee 是管道上的三岔口:把从标准输入收到的内容,同时写到标准输出和一个或多个文件。它有两个高频用途——把耗时命令的输出既留在屏幕上又存进日志;以及配合 sudo 写系统文件,因为重定向是 shell 执行的,sudo 管不到 shell 的重定向,而 tee 是真正以提权身份运行的命令。
基本信息
| 用途 | 把标准输入分流到标准输出与文件 |
|---|---|
| 语法 | 命令 | tee [选项] 文件... |
| 常用选项 | -a 追加而不是覆盖、-i 忽略中断信号、-p 诊断写入非管道目标的错误 |
| 所属 | GNU coreutils(busybox 也提供精简版) |
典型使用场景
- 构建与部署留痕:把完整输出存成带日期的日志,同时保留屏幕实时反馈
- 权限写文件:以 root 身份写 /etc 下的配置,绕开 shell 重定向的权限问题
- 边看边存:长时间跑的命令既能即时观察,又留下可回溯的记录
- 多路输出:同一份内容同时写入多个文件,例如一份明细加一份汇总
- 管道排障:在管道中间插一个 tee,把中间结果落盘,定位是哪一步出了问题
常用示例
常用示例
deploy.sh 2>&1 | tee deploy-$(date +%F).log # 屏幕与日志同时保留
make 2>&1 | tee -a build.log # 追加到已有日志
ps aux | tee /tmp/ps-$(date +%H%M).txt | wc -l # 顺手留一份现场
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-forward.conf # 提权写文件
printf 'nameserver 1.1.1.1\n' | sudo tee -a /etc/resolv.conf # 追加写法管道退出码与写入失败
管道退出码与写入失败
set -o pipefail # 让管道返回第一个失败命令的状态
cmd | tee out.log
echo "${PIPESTATUS[0]}" # pipefail 未开时,单独取源命令的退出码
cmd 2>&1 | tee out.log | grep -q ERROR # tee 后的下游提前退出时要留意写入错误常用选项对照
| 选项 | 作用 | 注意 |
|---|---|---|
| -a | 追加到文件末尾 | 不加则是覆盖,日志会丢历史 |
| -i | 忽略 SIGINT | 按 Ctrl+C 时 tee 不退出,适合必须写完整段的场景 |
| -p | 诊断非管道目标的写入错误 | 下游提前退出时更容易发现问题 |
| 多文件参数 | 同时写入多个文件 | 任一路写入失败都会影响退出码 |
tee 在排障时非常实用:把管道中段的输出落盘,就能判断是上游没产出、还是下游处理出错。相比事后翻终端回滚缓冲,落盘的结果更可靠。
管道的退出码默认取最后一个命令(也就是 tee),源命令失败会被悄悄吞掉。脚本里应开启 pipefail,或者显式读取 PIPESTATUS 里的第一个元素。