shell 标准流重定向顺序 OR 2>&1 1>/dev/null vs 1>/dev/null 2>&1

Wak*_*nka 4 bash redirection stderr stdout stdin

有人可以澄清差异吗?其中一些被认为是最佳实践吗?如果我没记错的话,我以某种方式在 SO 上读到这1>/dev/null应该在此之前:2>&1

ls -al /doesNotExists 2>&1 1>/dev/null
ls -al /doesNotExists 1>/dev/null 2>&1

ls -al /doesNotExists 1>&2 2>/dev/null
ls -al /doesNotExists 2>/dev/null 1>&2

ls -la /doesNotExists 2<&1 1>/dev/null
ls -la /doesNotExists 2<&1 2>/dev/null

ls -la /doesNotExists 1<&2 1>/dev/null
ls -la /doesNotExists 1<&2 2>/dev/null

ls -la /doesNotExists 1>/dev/null 2<&1
ls -la /doesNotExists 2>/dev/null 2<&1

ls -la /doesNotExists 1>/dev/null 1<&2
ls -la /doesNotExists 2>/dev/null 1<&2
Run Code Online (Sandbox Code Playgroud)

Dav*_*ill 8

shell 标准流重定向顺序

顺序很重要,因为结果不同。拿你的第一个例子:

ls -al /doesNotExists 2>&1 1>/dev/null
Run Code Online (Sandbox Code Playgroud)

这仅将标准输出定向到 nul,因为标准输出重定向到 dirlist之前,标准错误已复制到标准输出。

ls -al /doesNotExists 1>/dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)

这将标准输出和标准错误都指向空。


Bash 参考手册:重定向

请注意,重定向的顺序很重要。例如,命令

ls > dirlist 2>&1
Run Code Online (Sandbox Code Playgroud)

将标准输出(文件描述符 1)和标准错误(文件描述符 2)都定向到文件 dirlist,而命令

ls 2>&1 > dirlist
Run Code Online (Sandbox Code Playgroud)

仅将标准输出定向到文件 dirlist,因为在将标准输出重定向到 dirlist 之前,标准错误是标准输出的副本。

Source Bash 参考手册:重定向


教程

Illustrated Redirection Tutorial 中有一个很好的插图教程,它使这更容易理解:

重定向顺序,即“> file 2>&1”与“2>&1 >file”

虽然重定向出现在命令行的哪个位置并不重要,但它们的顺序确实很重要。它们是从左到右设置的。

2>&1 >file
Run Code Online (Sandbox Code Playgroud)

一个常见的错误是执行命令 2>&1 > file 将 stderr 和 stdout 都重定向到文件。让我们看看发生了什么。首先,我们在典型的终端中键入命令,描述符如下所示:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+
Run Code Online (Sandbox Code Playgroud)

然后我们的 shell,Bash 看到 2>&1 所以它复制了 1,文件描述符看起来像这样:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+
Run Code Online (Sandbox Code Playgroud)

没错,什么都没有改变,2 已经和 1 指向了同一个地方。现在 Bash 看到了 > file 并因此改变了标准输出:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+
Run Code Online (Sandbox Code Playgroud)

这不是我们想要的。

>file 2>&1
Run Code Online (Sandbox Code Playgroud)

现在让我们看看正确的命令>file 2>&1。我们像前面的例子一样开始,Bash 看到 > 文件:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+
Run Code Online (Sandbox Code Playgroud)

然后它看到我们的重复 2>&1:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| file                  |
                  ---       +-----------------------+
Run Code Online (Sandbox Code Playgroud)

瞧,1 和 2 都被重定向到文件。