本文聚焦 Linux Shell 中文件描述符及其引用符的核心机制。
• 文件描述符是操作系统为进程预分配的“通道编号”( 0标准输入、1标准输出、2标准错误),它将所有输入输出资源抽象为统一接口,是重定向与管道功能的底层基石。• 文件描述符引用符( &)则是重定向语法中的关键操作符,用于建立描述符之间的引用关系(如2>&1),从而实现输出流的合并、分离与高级控制。二者共同构成 Shell 精确指挥数据流向的核心能力,无论是将错误日志单独保存、将命令输出静默丢弃,还是在复杂脚本中临时保存与恢复输出流,都依赖这套灵活而强大的 I/O 控制体系。理解它们是从基础命令操作迈向高级 Shell 编程的关键一步。
[本文基于 CentOS Linux release 7 系统环境]
前情提要:通过往期文章《【Linux·基础篇】Shell 基础|重定向:数据流的指挥棒(一)》的内容,我们了解了重定向的核心概念和使用方法。
在往期文章里,我们只是简单介绍了重定向的符号,并没有深入探究它。重定向的符号通常由数字(如 0、1、2 等)和特殊符号(>、<、& 等)构成,例如常见的重定向组合 2>&1。其中,重定向里的数字是“文件描述符”,特殊字符 >、< 分别是“输出方向指示符”和“输入方向指示符”,特殊字符 & 是“文件描述符引用符”。
可见重定向的符号不止一个,不知道你是否经常会忘记或混淆它们。
接下来我们就简单地了解一下这些符号的具体含义,这有助于我们更加灵活熟练地使用重定向。
【注】本文将主要介绍“文件描述符”和“文件描述符引用符”。由于“方向指示符”比较形象,很容易被理解,这里就不作赘述了。
文件描述符是操作系统内核用来跟踪和管理已打开文件或输入输出流的一种抽象标识符。我们可以把它理解为:一个由操作系统分配的、简单的“通道编号”。
例如,当程序需要读写文件、从键盘获取输入,或向屏幕输出内容时,它并不直接操作具体的设备或文件,而是向操作系统申请:“我需要一个输入通道”。操作系统内核会创建相应的资源,并返回一个整数编号(即文件描述符)给程序。程序后续只需通过这个编号来操作,所有复杂的底层细节都由操作系统内核处理。
操作系统为每个新创建的进程自动预分配的三个基础输入/输出通道,即标准文件描述符。其中,在通常情况下,文件描述符 0 是标准输入,1 是标准输出,2 是标准错误输出。
0:标准输入(STDIN)1:标准输出(STDOUT):2:标准错误(STDERR):Shell 的重定向本质上就是在操作这些文件描述符。
0< | < | 0 | |
1> | > | 1 | |
2> | 2 | 2>) |
> 是 1> 的省略形式,默认操作的就是文件描述符 1(标准输出);< 是 0< 的省略形式,默认操作的就是文件描述符 0(标准输入);2> 没有省略形式。
< 或 0< 时,就是在指挥:请让程序的 0 号通道(标准输入)从文件读取,而不是键盘。> 或 1> 时,就是在指挥:请把 1 号通道(标准输出)的目的地,从屏幕改为某个文件。2> 时,就是在指挥:请把 2 号通道(标准错误)的目的地,从屏幕改为某个文件。【注】 一些具体示例可参考往期文章《【Linux·基础篇】Shell 基础|重定向:数据流的指挥棒(一)》。
文件描述符引用符是 Shell 重定向语法中的一个关键符号,用 & 表示。
文件描述符引用符的核心功能是建立文件描述符之间的引用关系,而不是与文件的关系。它的作用是告诉 Shell:“我后面的数字不是普通的文件名,而是另一个文件描述符的编号”。它让 Shell 能够:
这里给出文件描述符引用符的一些常见用法:
2>&1 | &1 | 2)重定向到标准输出(1)当前指向的位置 |
1>&2 | &2 | 1)重定向到标准错误(2)当前指向的位置 |
&> 文件名 | &> | 1)和标准错误(2)都覆盖重定向到指定文件 |
&>> 文件名 | &>> | 1)和标准错误(2)都追加重定向到指定文件 |
接下来将详细介绍这些用法。
2>&1:将标准输出和标准错误都重定向到同一文件command > output.txt 2>&12>&1,即将标准错误(2)重定向到标准输出(1)当前指向的位置。&1> output.txt 将标准输出(1)重定向到 output.txt;2>&1 将标准错误(2)重定向到标准输出(1)当前位置(即 output.txt)。【注意】重定向操作的顺序
若将命令写成 command 2>&1 > output.txt,则只有标准输出到文件,标准错误仍在屏幕。因为文件描述符引用符 & 引用的是当前指向的位置,此时标准错误(2)指向标准输出(1)的原始位置(屏幕),而不是 output.txt。
2>&1 将标准错误(2)重定向到标准输出(1)当前位置(屏幕);> output.txt 将标准输出(1)重定向到 output.txt。1>&2:将标准输出重定向到标准错误command 1>&21>&2,即将标准输出(1)重定向到标准错误(2)当前指向的位置。&2【注】1>&2 常用于脚本中
1>&2 常用于脚本中,将某些消息输出到错误流。例如,在脚本中可能希望将调试信息或某些状态消息输出到标准错误,以便与正常输出分离:
echo "这是一条调试信息" 1>&2&>:将标准输出和标准错误都重定向到同一文件(覆盖模式)command &> file&>,即将标准输出和标准错误都覆盖重定向到指定文件。&> file 是 > file 2>&1 的现代简写形式,两者效果相同。但 &> 更简洁,且避免了顺序问题。【注意】重定向表达式的书写
重定向表达式是一个整体操作符。文件描述符引用符 & 与数字之间不能有空格,例如在命令 command & > file中 & 可能会被解释为后台运行符号,而在命令 command 2> &1 中 Shell 通常会提示语法错误(例如提示“-bash: syntax error near unexpected token '&'”),不会将其视为有效重定向。
&>>:将标准输出和标准错误都重定向到同一文件(追加模式)command &>> file&>>,即将标准输出和标准错误都追加重定向到指定文件。&>> file 是 >> file 2>&1 的现代简写形式,两者效果相同。但 &>> 更简洁,且避免了顺序问题。【注】&>> 适用于持续记录日志的场景
与 &> 的覆盖模式不同,&>> 是追加模式,适合用于累积记录命令的输出和错误,例如日志记录:
# 每次运行都追加日志,不会覆盖之前的记录command1 &>> all_logs.txtcommand2 &>> all_logs.txt文件描述符与文件描述符引用符共同构成了 Shell 世界中精准指挥数据流向的底层基石。
文件描述符是操作系统为进程预分配的“通道编号”,将文件、设备、网络套接字等各类 I/O 资源抽象为统一的整数接口,实现了“一切皆文件”的 Linux 哲学。而文件描述符引用符& 则是重定向语法中的关键操作符,通过建立描述符间的引用关系,使得输出流的分离、合并与重定向成为可能。
理解文件描述符的抽象本质,掌握文件描述符引用符的灵活运用,便是掌握了 Shell 编程中高效控制数据输入输出的核心密钥——从简单的日志保存到复杂的进程通信,无不建立在这套简洁而强大的机制之上,让数据在命令与文件、命令与命令之间真正实现“指哪儿打哪儿”。
此番炼器手札,炉火尚未全熄。若道友观之有趣,或可暂留此间,结一尘缘。待下回开炉铸器,新得感悟,必先与同道分享。