Shell 重定向详解:从标准流到 tee 命令的完整指南
在 Shell 中,输入输出重定向是控制命令数据流的核心机制,通过灵活处理标准输入(stdin)、标准输出(stdout)和标准错误(stderr),可以实现日志记录、错误屏蔽、批量处理等多种功能。本文将系统讲解重定向的原理、用法及 tee 命令的应用。
标准流与文件描述符
Shell 中所有命令的输入输出都基于三个标准流,每个流对应一个文件描述符(用于在系统中标识流):
| 标准流 | 功能描述 | 文件描述符 | 默认设备 |
|---|---|---|---|
| stdin | 标准输入(命令读取数据) | 0 | 键盘 |
| stdout | 标准输出(命令正常输出) | 1 | 终端屏幕 |
| stderr | 标准错误(命令错误输出) | 2 | 终端屏幕 |
这些流可以被重定向到文件、设备或其他命令,改变数据的默认流向。
输入重定向(<)
输入重定向用于将命令的输入来源从默认的键盘改为指定文件,语法为:命令 < 输入文件
常用场景
- 批量输入数据(如给
mail命令提供邮件内容); - 替代管道传递文件内容(等价于
cat 输入文件 | 命令)。
示例
1 | # 从 file.txt 中读取内容作为 grep 的输入(查找包含 "hello" 的行) |
输出重定向(>、>>、2>、2>>)
输出重定向用于将命令的输出(正常或错误)写入文件,而非终端。根据流类型和操作方式,分为以下几种:
标准输出重定向
命令 > 文件:将标准输出覆盖写入文件(文件不存在则创建,存在则清空)。命令 >> 文件:将标准输出追加写入文件(保留原有内容)。
示例:
1 | # 覆盖写入:将当前目录列表保存到 dir.txt |
标准错误重定向
错误输出需要显式指定文件描述符 2:
命令 2> 文件:将标准错误覆盖写入文件。命令 2>> 文件:将标准错误追加写入文件。
示例:
1 | # 捕获错误信息:删除不存在的文件,错误写入 error.log |
合并输出重定向
实际场景中常需要将标准输出和错误输出合并处理,有两种常用方式:
(1)2>&1:将错误输出重定向到标准输出
- 语法:
命令 > 文件 2>&1(先重定向 stdout 到文件,再将 stderr 指向 stdout)。 - 追加形式:
命令 >> 文件 2>&1。
示例:
1 | # 将所有输出(正常+错误)覆盖写入 all.log |
(2)&> 或 >&:简化的合并写法
命令 &> 文件:等价于命令 > 文件 2>&1(Bash 扩展语法)。命令 &>> 文件:等价于命令 >> 文件 2>&1。
示例:
1 | # 合并输出到 log.txt(覆盖) |
特殊重定向目标
/dev/null:屏蔽输出
- 被称为 “黑洞设备”,所有写入的数据都会被丢弃,常用于屏蔽不需要的输出。
示例:
1 | # 屏蔽所有输出(包括错误) |
/dev/tty:强制输出到终端
- 表示当前终端设备,即使标准输出已被重定向,仍会显示在屏幕上。
示例:
1 | # 正常输出写入文件,但提示信息显示在终端 |
tee 命令:输出分流工具
1 | tee` 命令用于将输入数据同时发送到**标准输出(终端)** 和**指定文件**,实现 “一份输入,多处输出” 的效果,语法为: |
常用选项
-a:追加模式(默认是覆盖模式)。--append:同-a。
示例
1 | # 同时在终端显示日期并写入 time.log(覆盖) |
典型应用:日志实时查看与保存
1 | # 实时跟踪日志文件,同时保存到 archive.log |
重定向的优先级与注意事项
重定向顺序:
- 输出重定向中,
>应在2>&1之前(如> file 2>&1正确,2>&1 > file错误)。 - 输入重定向
<通常放在命令末尾。
- 输出重定向中,
文件权限:
重定向写入文件时,需确保当前用户对目标文件有写权限,否则会报错Permission denied。子 Shell 影响:
管道中的命令在子 Shell 中执行,重定向仅影响子 Shell,不改变父 Shell 的环境:1
2
3# 错误示例:管道中的变量赋值在父Shell中无效
echo "123" | read num
echo $num # 输出为空(num在子Shell中定义)Here Document( heredoc ):
一种特殊的输入重定向,用于在脚本中嵌入多行输入:1
2
3
4
5
6# 将多行文本写入 file.txt
cat > file.txt << EOF
第一行内容
第二行内容
EOF
# 说明:<< EOF 表示从下一行开始读取,直到遇到 EOF 结束