我面临一个我无法解释的问题。我要重新编写一个shell,对我来说有一种奇怪的行为。
echo test >&2 2>&1
这种命令是在stderr上写的(所以第一次重定向),为什么第二次重定向不会影响输出目的地?为什么输出不在stdout上?
我看到一些在执行命令之前发生重定向的事情,从左到右,那么为什么第二次重定向没有取消第一次?
提前致谢。
编辑:我在bash上运行我的脚本。
cmd >&2 2>&1
与cmd 2>&1 >&2
非常不同,因为重定向以不同的顺序发生。假设从一个进程调用该命令,该进程将fd 1附加到名为'output'的文件,并将fd 2附加到名为'error'的文件中。然后cmd >&2 2>&1
将cmd
的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。
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