Linux tee 指令详解:从基础到高级用法
tee 是 Linux 系统中一个强大的命令行工具,用于从标准输入(stdin)读取数据,并同时将数据写入标准输出(stdout)和一个或多个指定文件。它在管道(pipe)操作中尤为有用,允许用户在处理数据流时保存中间结果。tee 的名称来源于其功能类似于管道系统中的 T 形接头(tee),将数据流“分流”到多个目标。tee 广泛应用于日志记录、数据处理、脚本自动化和调试场景。
📚 什么是 tee 指令?
概述
tee 是一个 Linux 命令行工具,设计用于从标准输入读取数据,并将其同时输出到标准输出和一个或多个文件。它通常在管道操作中作为中间节点,允许用户在查看数据流的同时将其保存到文件中。tee 是 Linux/Unix 系统中的标准工具,预装于大多数发行版(如 Ubuntu、CentOS),是 shell 脚本和命令行工作流中的重要组成部分。
核心概念
- 标准输入(stdin):tee 从管道或命令读取输入。
- 标准输出(stdout):tee 将输入数据回显到终端。
- 文件输出:tee 将输入数据写入指定文件。
- 文件描述符:tee 主要操作 stdin(FD 0)和 stdout(FD 1),文件写入使用普通文件描述符。
- 管道集成:tee 常用于管道链中,连接前后命令。
核心特点
- 数据分流:同时输出到终端和文件。
- 多文件支持:可写入多个目标文件。
- 灵活性:支持覆盖或追加文件内容。
- 兼容性:适用于 Bash、Zsh 等 shell 环境。
- 自动化:在脚本中实现日志记录和数据捕获。
基本语法
tee [选项] [文件...]
常用选项
- -a:追加到文件,而不是覆盖。
- -i:忽略中断信号(如 Ctrl+C)。
- –help:显示帮助信息。
- –version:显示版本信息。
输入输出流程
- 输入:从 stdin 读取(通常通过管道 |)。
- 输出:
- 写入指定的文件(覆盖或追加)。
- 回显到 stdout(终端或下一个管道命令)。
注意事项
- 权限要求:写入文件需要相应权限,写入受限目录(如 /etc)需 sudo。
- 覆盖风险:默认覆盖目标文件,需用 -a 追加。
- 管道依赖:tee 通常与管道配合,无管道时需显式输入(如 echo)。
- 中断处理:Ctrl+C 默认终止 tee,可用 -i 忽略。
- 编码支持:确保终端和文件编码一致(如 UTF-8)。
🔧 tee 的常见用途
应用场景
- 日志记录:实时查看命令输出并保存到日志文件。
- 数据处理:在管道链中保存中间结果。
- 调试分析:捕获命令输出以排查问题。
- 脚本自动化:构建复杂工作流,记录关键数据。
- 权限提升:结合 sudo 将输出写入受限文件。
🛠️ 基础用法与示例
准备工作
以下示例假设运行在 Bash shell(如 Ubuntu 22.04 或 CentOS 8,当前时间为 2025-05-31 19:37 CST)。我们将使用常见命令(如 ls、echo、ps)演示 tee 的功能。假设当前目录为 /home/user。
示例 1:将输出保存到文件并显示
命令
ls -l | tee dir_list.txt
cat dir_list.txt
解释
- ls -l:列出当前目录的详细信息。
- |:将 stdout 传递给 tee。
- tee dir_list.txt:将输入同时写入 dir_list.txt 和终端。
- cat dir_list.txt:验证文件内容。
输出示例
-
终端:
-rw-r--r-- 1 user user 123 May 31 19:00 file1.txt drwxr-xr-x 2 user user 4096 May 31 19:00 dir1 -rw-r--r-- 1 user user 456 May 31 19:00 file2.txt
-
dir_list.txt(同终端输出):
-rw-r--r-- 1 user user 123 May 31 19:00 file1.txt drwxr-xr-x 2 user user 4096 May 31 19:00 dir1 -rw-r--r-- 1 user user 456 May 31 19:00 file2.txt
说明
- 文件不存在时自动创建。
- 默认覆盖 dir_list.txt。
示例 2:追加到文件
命令
echo "First entry" | tee -a log.txt
echo "Second entry" | tee -a log.txt
cat log.txt
解释
- -a:追加到 log.txt,不覆盖。
- 多次执行追加内容。
输出示例
-
终端(每次 echo):
First entry Second entry
-
log.txt:
First entry Second entry
示例 3:写入多个文件
命令
ps aux | tee file1.txt file2.txt
cat file1.txt
cat file2.txt
解释
- ps aux:列出所有进程。
- tee file1.txt file2.txt:将输入写入两个文件并显示。
输出示例
-
终端:
user 12345 0.0 0.1 123456 7890 ? Ss 19:00 0:00 /usr/bin/bash user 12346 0.0 0.2 456789 12345 ? S 19:00 0:00 ps aux
-
file1.txt 和 file2.txt(内容相同):
user 12345 0.0 0.1 123456 7890 ? Ss 19:00 0:00 /usr/bin/bash user 12346 0.0 0.2 456789 12345 ? S 19:00 0:00 ps aux
示例 4:结合管道继续处理
命令
ls -l | tee dir_list.txt | grep ".txt"
解释
- tee dir_list.txt:保存 ls -l 输出到文件并传递到 stdout。
- grep “.txt”:从 tee 的 stdout 过滤 .txt 文件。
输出示例
-
终端:
-rw-r--r-- 1 user user 123 May 31 19:00 file1.txt -rw-r--r-- 1 user user 456 May 31 19:00 file2.txt
-
dir_list.txt:
-rw-r--r-- 1 user user 123 May 31 19:00 file1.txt drwxr-xr-x 2 user user 4096 May 31 19:00 dir1 -rw-r--r-- 1 user user 456 May 31 19:00 file2.txt
示例 5:忽略中断信号
命令
echo "Processing..." | tee -i output.txt
# 按 Ctrl+C 中断
cat output.txt
解释
- -i:忽略中断信号(SIGINT,Ctrl+C)。
- 即使中断,tee 仍完成写入。
输出示例
-
终端:
Processing... ^C
-
output.txt:
Processing...
示例 6:结合 sudo 写入受限文件
命令
ls -l | sudo tee /root/dir_list.txt
cat /root/dir_list.txt
解释
- sudo tee:以 root 权限写入 /root 目录。
- 管道允许非 root 用户的 ls 输出通过 tee 写入受限文件。
输出示例
-
终端(需 root 权限查看):
-rw-r--r-- 1 user user 123 May 31 19:00 file1.txt drwxr-xr-x 2 user user 4096 May 31 19:00 dir1 -rw-r--r-- 1 user user 456 May 31 19:00 file2.txt
-
/root/dir_list.txt(同上)。
🚀 高级用法
概述
tee 的高级用法涉及复杂管道、文件描述符操作、脚本集成和错误处理,适合日志管理、数据处理和自动化场景。
🛡️ 1. 捕获 stderr 和 stdout
命令
ls /home/user /nonexistent 2>&1 | tee output.txt
cat output.txt
解释
- 2>&1:将 stderr(FD 2)重定向到 stdout(FD 1)。
- tee output.txt:捕获合并的 stdout 和 stderr。
输出示例
-
终端和 output.txt:
/home/user: file1.txt dir1 file2.txt ls: cannot access '/nonexistent': No such file or directory
补充
-
仅捕获 stderr:
ls /home/user /nonexistent 2> >(tee error.txt) cat error.txt
输出(error.txt):
ls: cannot access '/nonexistent': No such file or directory
🔍 2. 多重管道与 tee
命令
ps aux | tee ps_output.txt | grep "bash" | tee bash_output.txt
cat ps_output.txt
cat bash_output.txt
解释
- 第一个 tee:保存 ps aux 输出。
- grep “bash”:过滤包含 “bash” 的行。
- 第二个 tee:保存过滤结果。
输出示例
-
ps_output.txt:
user 12345 0.0 0.1 123456 7890 ? Ss 19:00 0:00 /usr/bin/bash user 12346 0.0 0.2 456789 12345 ? S 19:00 0:00 ps aux
-
bash_output.txt:
user 12345 0.0 0.1 123456 7890 ? Ss 19:00 0:00 /usr/bin/bash
🔄 3. 动态日志记录
命令
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
top -b -n 1 | tee system_$TIMESTAMP.log
cat system_$TIMESTAMP.log
解释
- top -b -n 1:批处理模式运行一次 top。
- tee system_$TIMESTAMP.log:保存带时间戳的系统状态。
输出示例(system_20250531_193700.log)
top - 19:37:00 up 1:00, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 100 total, 1 running, 99 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 100.0 id, 0.0 wa, 0.0 hi, 0.0 si
...
用途
- 定期记录系统状态。
⚡ 4. 结合 Here Document
命令
tee config.txt << EOF
[app]
host=localhost
port=8080
EOF
cat config.txt
解释
- << EOF:Here Document 提供多行输入。
- tee config.txt:将输入写入文件并显示。
输出示例
-
终端和 config.txt:
[app] host=localhost port=8080
🔐 5. 权限管理与 tee
命令
echo "test" | sudo tee -a /etc/test.conf
cat /etc/test.conf
解释
- sudo tee -a:以 root 权限追加到受限文件。
- 管道允许非 root 用户提供输入。
输出示例
-
终端和 /etc/test.conf:
test
⚠️ 使用 tee 时的注意事项
关键提示
-
覆盖风险:
- 默认覆盖目标文件,需用 -a 追加。
-
权限要求:
-
写入受限文件需 sudo tee:
echo "data" | sudo tee /root/file.txt
-
-
管道依赖:
- 无管道输入时,tee 等待 stdin(需 Ctrl+D 结束)。
-
中断处理:
- Ctrl+C 默认终止,-i 可忽略。
-
性能影响:
- 写入多个文件或大型数据可能增加 I/O 开销。
-
编码问题:
- 确保终端和文件编码一致,避免乱码。
🌟 高级技巧与实战案例
概述
以下是高级技巧和实战案例,展示 tee 在复杂场景中的应用。
🖥️ 案例 1:实时日志监控
脚本
#!/bin/bash
LOG_FILE=/var/log/monitor.log
# 监控系统状态
while true; do
top -b -n 1 | tee -a "$LOG_FILE"
sleep 5
done
解释
- top -b -n 1:每 5 秒捕获系统状态。
- tee -a:追加到日志并显示。
- 按 Ctrl+C 终止。
输出示例(monitor.log)
top - 19:37:00 up 1:00, 1 user, load average: 0.00, 0.01, 0.05
...
top - 19:37:05 up 1:00, 1 user, load average: 0.00, 0.01, 0.05
...
用途
- 实时监控并记录系统性能。
📦 案例 2:数据处理流水线
脚本
#!/bin/bash
INPUT_FILE=data.txt
INTERMEDIATE=intermediate.txt
OUTPUT_FILE=processed.txt
# 创建输入文件
echo -e "apple\nbanana\napple\ncherry" > "$INPUT_FILE"
# 处理数据
cat "$INPUT_FILE" | tee "$INTERMEDIATE" | grep -v "banana" | sort | uniq | tee "$OUTPUT_FILE"
# 显示结果
echo "Intermediate:"
cat "$INTERMEDIATE"
echo "Final Output:"
cat "$OUTPUT_FILE"
解释
- 保存中间结果(tee “$INTERMEDIATE”)。
- 过滤、排序、去重后保存最终结果。
输出示例
-
intermediate.txt:
apple banana apple cherry
-
processed.txt:
apple cherry
🔒 案例 3:错误日志分离
脚本
#!/bin/bash
LOG_FILE=/tmp/output.log
ERROR_LOG=/tmp/error.log
# 运行命令
ls /home/user /nonexistent 2> >(tee "$ERROR_LOG" >&2) | tee "$LOG_FILE"
# 显示结果
echo "Standard Output:"
cat "$LOG_FILE"
echo "Error Output:"
cat "$ERROR_LOG"
解释
- 2> >(…):将 stderr 送入 tee,保存并显示。
- | tee:保存 stdout。
输出示例
-
LOG_FILE:
/home/user: file1.txt dir1 file2.txt
-
ERROR_LOG:
ls: cannot access '/nonexistent': No such file or directory
📈 案例 4:动态配置文件生成
脚本
#!/bin/bash
CONFIG_FILE=/tmp/app.conf
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# 生成配置文件
tee "$CONFIG_FILE" << EOF
# Generated at $TIMESTAMP
[app]
host=localhost
port=8080
debug=true
EOF
# 显示结果
cat "$CONFIG_FILE"
解释
- 使用 Here Document 和 tee 创建配置文件。
- 包含时间戳。
输出示例(app.conf)
# Generated at 2025-05-31 19:37:00
[app]
host=localhost
port=8080
debug=true
🔧 案例 5:自动化备份监控
脚本
#!/bin/bash
BACKUP_DIR=/tmp/backup
LOG_FILE=/tmp/backup.log
ERROR_LOG=/tmp/backup_error.log
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 执行备份
tar -czf "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" /home/user 2> >(tee -a "$ERROR_LOG" >&2) | tee -a "$LOG_FILE"
# 检查错误
if [ -s "$ERROR_LOG" ]; then
echo "Backup errors occurred, check $ERROR_LOG"
else
echo "Backup completed, log in $LOG_FILE"
fi
加入 cron
crontab -e
添加任务
0 2 * * * /path/to/backup.sh
解释
- 备份 /home/user,分离 stdout 和 stderr。
- tee -a:追加日志。
- 每天凌晨 2 点执行。
输出示例
-
LOG_FILE:
home/user/file1.txt home/user/dir1 home/user/file2.txt
-
ERROR_LOG(若有错误):
tar: /home/user/restricted: Permission denied
🔗 结合其他工具
概述
tee 常与其他工具结合,增强功能。
与 grep 结合
ls -l | tee dir_list.txt | grep ".txt"
解释
- 保存完整输出,过滤特定内容。
与 awk 结合
ps aux | tee ps_output.txt | awk '{print $1, $2}'
解释
- 保存进程信息,提取字段。
与 sudo 结合
echo "data" | sudo tee /root/file.txt
解释
- 写入受限文件。
与 cron 结合
0 0 * * * top -b -n 1 | tee -a /var/log/system_monitor.log
解释
- 定时记录系统状态。
📝 总结
tee 是 Linux 中处理数据流的分流工具,通过从标准输入读取数据并同时写入文件和标准输出,提供了强大的日志记录和数据处理能力。