> 技术文档 > Linux tee 指令详解:从基础到高级用法

Linux tee 指令详解:从基础到高级用法


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.txtcat 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.txtdrwxr-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.txtdrwxr-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.txtecho \"Second entry\" | tee -a log.txtcat log.txt
解释
  • -a:追加到 log.txt,不覆盖。
  • 多次执行追加内容。
输出示例
  • 终端(每次 echo):

    First entrySecond entry
  • log.txt:

    First entrySecond entry

示例 3:写入多个文件

命令
ps aux | tee file1.txt file2.txtcat file1.txtcat file2.txt
解释
  • ps aux:列出所有进程。
  • tee file1.txt file2.txt:将输入写入两个文件并显示。
输出示例
  • 终端:

    user 12345 0.0 0.1 123456 7890 ? Ss 19:00 0:00 /usr/bin/bashuser 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/bashuser 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.txtdrwxr-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.txtcat /root/dir_list.txt
解释
  • sudo tee:以 root 权限写入 /root 目录。
  • 管道允许非 root 用户的 ls 输出通过 tee 写入受限文件。
输出示例
  • 终端(需 root 权限查看):

    -rw-r--r-- 1 user user 123 May 31 19:00 file1.txtdrwxr-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.txtcat output.txt
解释
  • 2>&1:将 stderr(FD 2)重定向到 stdout(FD 1)。
  • tee output.txt:捕获合并的 stdout 和 stderr。
输出示例
  • 终端和 output.txt:

    /home/user:file1.txt dir1 file2.txtls: 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.txtcat ps_output.txtcat 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/bashuser 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.logcat 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.05Tasks: 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=localhostport=8080EOFcat config.txt
解释
  • << EOF:Here Document 提供多行输入。
  • tee config.txt:将输入写入文件并显示。
输出示例
  • 终端和 config.txt:

    [app]host=localhostport=8080

🔐 5. 权限管理与 tee

命令
echo \"test\" | sudo tee -a /etc/test.confcat /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/bashLOG_FILE=/var/log/monitor.log# 监控系统状态while true; do top -b -n 1 | tee -a \"$LOG_FILE\" sleep 5done
解释
  • 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/bashINPUT_FILE=data.txtINTERMEDIATE=intermediate.txtOUTPUT_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:

    applebananaapplecherry
  • processed.txt:

    applecherry

🔒 案例 3:错误日志分离

脚本
#!/bin/bashLOG_FILE=/tmp/output.logERROR_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/bashCONFIG_FILE=/tmp/app.confTIMESTAMP=$(date \'+%Y-%m-%d %H:%M:%S\')# 生成配置文件tee \"$CONFIG_FILE\" << EOF# Generated at $TIMESTAMP[app]host=localhostport=8080debug=trueEOF# 显示结果cat \"$CONFIG_FILE\"
解释
  • 使用 Here Document 和 tee 创建配置文件。
  • 包含时间戳。
输出示例(app.conf)
# Generated at 2025-05-31 19:37:00[app]host=localhostport=8080debug=true

🔧 案例 5:自动化备份监控

脚本
#!/bin/bashBACKUP_DIR=/tmp/backupLOG_FILE=/tmp/backup.logERROR_LOG=/tmp/backup_error.logTIMESTAMP=$(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.txthome/user/dir1home/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 中处理数据流的分流工具,通过从标准输入读取数据并同时写入文件和标准输出,提供了强大的日志记录和数据处理能力。

更多技术分享,关注公众号:halugin