Shell,冲突的重定向行为

时间:2019-03-07 15:29:34

标签: shell redirect

我正面临一个无法解释的问题。我必须重新编码外壳程序,这对我来说是一种奇怪的行为。

echo test >&2 2>&1

这种命令是在stderr上编写的(因此使用第一个重定向),为什么第二个重定向不影响输出目标?为什么输出不在stdout上?

我看到一些东西在执行命令之前发生了重定向,从左到右,所以为什么第二个重定向没有取消第一个呢?

谢谢。

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

2 个答案:

答案 0 :(得分:2)

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

因此,>&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

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

$ fdtest 1>/dev/null
test to stdout

答案 1 :(得分:1)

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