What does “ 2>&1 “ mean?
技术背景
在Linux或Unix系统中,程序通常会将输出发送到两个地方:标准输出(stdout
)和标准错误(stderr
)。标准输出用于正常的程序输出,而标准错误则用于输出程序运行过程中产生的错误信息。文件描述符是一个非负整数,用于标识一个打开的文件,其中0
代表标准输入(stdin
),1
代表标准输出(stdout
),2
代表标准错误(stderr
)。2>&1
是一种输出重定向的语法,用于将标准错误输出重定向到标准输出的当前位置。
实现步骤
基本概念理解
- 文件描述符:在Unix/Linux系统中,文件描述符是一个正整数,代表一个打开的文件。
0
为 stdin
,1
为 stdout
,2
为 stderr
。 - 重定向符号:
>
:将输出重定向到文件,如果文件存在则覆盖。>>
:将输出追加到文件末尾。2>
:将标准错误输出重定向到文件。>&
:将一个文件描述符的输出重定向到另一个文件描述符。
重定向示例
- 将标准输出重定向到文件:
这等价于:
- 将标准错误输出重定向到文件:
- 将标准错误输出重定向到标准输出:
命令行顺序的影响
在Bash中,命令行的重定向顺序很重要。例如:
1
| ls -ld /tmp /tnt >/dev/null 2>&1
|
这个命令将标准输出和标准错误输出都重定向到 /dev/null
。而:
1
| ls -ld /tmp /tnt 2>&1 >/dev/null
|
这个命令只会将标准输出重定向到 /dev/null
,标准错误输出仍然会显示在终端。
核心代码
重定向标准错误到标准输出
同时重定向标准输出和标准错误到文件
1 2 3 4
| ls -ld /tmp /tnt >file.txt 2>&1
ls -ld /tmp /tnt &>file.txt
|
不同操作处理标准输出和标准错误
1 2 3 4
| ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2 2>&1 | sed 's/^/E: /'
ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
|
最佳实践
合并输出进行处理
当需要对标准输出和标准错误输出进行统一处理时,可以使用 2>&1
将它们合并。例如,查找标准输出和标准错误中包含 ERROR
的行:
避免错误信息干扰输出
当使用分页工具查看输出时,为了避免标准错误信息干扰输出,可以将标准错误重定向到标准输出:
同时记录输出到文件和显示在终端
使用 tee
命令将标准输出和标准错误输出同时记录到文件并显示在终端:
1
| foo 2>&1 | tee /dev/tty >>outfile
|
常见问题
重定向顺序错误
在Bash中,重定向操作是从左到右处理的。因此,command >file 2>&1
和 command 2>&1 >file
的效果不同。前者将标准输出和标准错误都重定向到文件,而后者只将标准输出重定向到文件,标准错误仍然输出到终端。
noclobber
选项影响
当设置了 set -o noclobber
选项后,Bash 不会覆盖已存在的文件。此时可以使用 >|
语法来强制覆盖文件:
1 2 3
| set -o noclobber date > $testfile date >| $testfile
|
1>&2
和 2>&1
不能互换
1>&2
是将标准输出重定向到标准错误,而 2>&1
是将标准错误重定向到标准输出。在使用管道时,它们的效果不同。例如:
1 2
| docker logs 1b3e97c49e39 2>&1 | grep "some log" docker logs 1b3e97c49e39 1>&2 | grep "some log"
|