Shell,冲突重定向的行为

问题描述 投票:0回答:2

我面临一个我无法解释的问题。我要重新编写一个shell,对我来说有一种奇怪的行为。

echo test >&2 2>&1

这种命令是在stderr上写的(所以第一次重定向),为什么第二次重定向不会影响输出目的地?为什么输出不在stdout上?

我看到一些在执行命令之前发生重定向的事情,从左到右,那么为什么第二次重定向没有取消第一次?

提前致谢。

编辑:我在bash上运行我的脚本。

shell redirect
2个回答
1
投票

cmd >&2 2>&1cmd 2>&1 >&2非常不同,因为重定向以不同的顺序发生。假设从一个进程调用该命令,该进程将fd 1附加到名为'output'的文件,并将fd 2附加到名为'error'的文件中。然后cmd >&2 2>&1cmd的stdout重定向到名为error的文件,然后将cmd的stderr重定向到fd 1所连接的任何内容,即名为error的文件。但cmd 2>&1 >&2将首先将fd 2重定向到'output'并将fd 1重定向到同一个地方。换句话说,cmd >&2 2>&1将所有内容写入stderr,cmd 2>&1 >&2将所有内容写入stdout。


2
投票

x>&y的意思是“将文件描述符x重定向到当前指向的fd y。 重定向严格从左到右处理。

因此,>&2 2>&1将fd 1指向/ dev / stderr,然后将fd 2指向/ dev / stderr。

如果要交换stderr和stdout,则需要第三个文件描述符:

(echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-
# ................................................ A .. B .. C .. D
# A. fd 3 = /dev/stdout
# B. fd 1 = /dev/stderr
# C. fd 2 = /dev/stdout
# D. fd 3 is closed

让我们把它放在一个函数中,以便于测试

fdtest() { (echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-; }

运行

$ fdtest
test to stdout
test to stderr

抛弃标准错误(我们希望在标准输出上看到“stderr”消息)。

$ fdtest 2>/dev/null
test to stderr

抛弃标准输出(我们希望在标准错误上看到“stdout”消息)。

$ fdtest 1>/dev/null
test to stdout
© www.soinside.com 2019 - 2024. All rights reserved.