Linux cmd > /dev/null 2>&1 如何工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16995425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does cmd > /dev/null 2>&1 work?
提问by hax0r_n_code
I'm reading up on redirecting data to /dev/null
and so I tried a simple test:
我正在阅读有关将数据重定向到的内容/dev/null
,因此我尝试了一个简单的测试:
ping a.b.c # which results in an address not found
If I try this:
如果我试试这个:
ping a.b.c > /dev/null # prints the same error message as the one above
However, if I do this:
但是,如果我这样做:
ping a.b.c > /dev/null 2>&1 # The error message is gone
That last solution is the desired solution, but what is happening with this 2>&1
? My research so far suggest that 2
represents stderr
and 1
represents stdout
. So if I read it that way, it looks like I'm creating a stderr
file and redirecting stdout
to it?
最后一个解决方案是所需的解决方案,但这是怎么回事2>&1
?到目前为止,我的研究表明2
代表stderr
和1
代表stdout
. 所以如果我这样读,看起来我正在创建一个stderr
文件并重定向stdout
到它?
If that is the case, what does the &
in that command do?
如果是这种情况,&
该命令中的 有什么作用?
采纳答案by msb
You are right, 2
is STDERR
, 1
is STDOUT
. When you do 2>&1
you are saying: "print to STDOUT
(1
) the things that would go to STDERR
(2
)". And before that, you said your STDOUT
would go to /dev/null
. Therefore, nothing is seen. In the examples 1 and 2 you get the output message because it is being printed to STDERR
, as a regular redirection only redirects STDOUT
.
你是对的,2
是STDERR
,1
是STDOUT
。当你做2>&1
你说:“打印到STDOUT
(1
),这将去的东西STDERR
(2
)”。在此之前,你说你STDOUT
会去/dev/null
。因此,什么也看不见。在示例 1 和 2 中,您会收到输出消息,因为它被打印到STDERR
,因为常规重定向仅重定向STDOUT
。
And when you do the redirection, you are not creating a STDERR
, the processes always have a STDERR
and a STDOUT
when they are created.
当您进行重定向时,您不是在创建 a STDERR
,进程在创建时始终具有 aSTDERR
和 a STDOUT
。
回答by Evan Rosica
Consider the following code which prints the word "stdout" to stdout and the word "stderror" to stderror.
考虑以下代码,它将单词“stdout”打印到 stdout,将单词“stderror”打印到 stderror。
$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror
Note that the '&' operator tells bash that 2 is a file descriptor (which points to the stderr) and not a file name. If we left out the '&', this command would print stdout
to stdout, and create a file named "2" and write stderror
there.
请注意,'&' 运算符告诉 bash 2 是文件描述符(指向 stderr)而不是文件名。如果我们省略 '&',该命令将打印stdout
到标准输出,并创建一个名为“2”的文件并stderror
在那里写入。
By experimenting with the code above, you can see for yourself exactly how redirection operators work. For instance, by changing which file which of the two descriptors 1,2, is redirected to /dev/null
the following two lines of code delete everything from the stdout, and everything from stderror respectively (printing what remains).
通过试验上面的代码,您可以亲眼看到重定向操作符是如何工作的。例如,通过更改两个描述符 1,2 中的哪个文件被重定向到/dev/null
以下两行代码,分别删除 stdout 中的所有内容和 stderror 中的所有内容(打印剩余内容)。
$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null
stderror
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null
stdout
Now, we approach the crux of the question (substituting my example for yours), why does
现在,我们接近问题的关键(用我的例子代替你的例子),为什么
(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1
produce no output? To truly understand this, I highly recommend you read this webpage on file descriptor tables. Assuming you have done that reading, we can proceed. Note that Bash processes left to right; thus Bash sees >/dev/null
first (which is the same as 1>/dev/null
), and sets the file descriptor 1 to point to /dev/null instead of the stdout. Having done this, Bash then moves rightwards and sees 2>&1
. This sets the file descriptor 2 to point to the same fileas file descriptor 1 (and not to file descriptor 1 itself!!!! (see this resource on pointersfor more info) . Since file descriptor 1 points to /dev/null, and file descriptor 2 points to the same file as file descriptor 1, file descriptor 2 now also points to /dev/null. Thus both file descriptors point to /dev/null, and this is why no output is rendered.
没有产出?要真正理解这一点,我强烈建议您阅读有关文件描述符表的网页。假设您已完成阅读,我们可以继续。注意 Bash 从左到右处理;因此 Bash>/dev/null
首先看到(与 相同1>/dev/null
),并将文件描述符 1 设置为指向 /dev/null 而不是 stdout。完成此操作后,Bash 然后向右移动并看到2>&1
。这将文件描述符 2 设置为指向与文件描述符 1相同的文件(而不是文件描述符 1 本身!!!(请参阅有关指针的资源)了解更多信息)。由于文件描述符 1 指向 /dev/null,而文件描述符 2 指向与文件描述符 1 相同的文件,因此文件描述符 2 现在也指向 /dev/null。因此,两个文件描述符都指向 /dev/null,这就是不呈现输出的原因。
To test if you really understand the concept, try to guess the output when we switch the redirection order:
为了测试你是否真的理解这个概念,试着猜测我们切换重定向顺序时的输出:
(echo "stdout"; echo "stderror" >&2) 2>&1 >/dev/null
stderror
标准错误
The reasoning here is that evaluating from left to right, Bash sees 2>&1, and thus sets the file descriptor 2 to point to the same place as file descriptor 1, ie stdout. It then sets file descriptor 1 (remember that >/dev/null = 1>/dev/null) to point to >/dev/null, thus deleting everything which would usually be send to to the standard out. Thus all we are left with was that which was not send to stdout in the subshell (the code in the parentheses)- i.e. "stderror".
The interesting thing to note there is that even though 1 is just a pointer to the stdout, redirecting pointer 2 to 1 via 2>&1
does NOT form a chain of pointers 2 -> 1 -> stdout. If it did, as a result of redirecting 1 to /dev/null, the code 2>&1 >/dev/null
would give the pointer chain 2 -> 1 -> /dev/null, and thus the code would generate nothing, in contrast to what we saw above.
这里的推理是从左到右计算,Bash 看到 2>&1,因此将文件描述符 2 设置为与文件描述符 1 指向相同的位置,即 stdout。然后它将文件描述符 1(记住 >/dev/null = 1>/dev/null)设置为指向 >/dev/null,从而删除通常会发送到标准输出的所有内容。因此,我们剩下的就是没有发送到子shell中的标准输出(括号中的代码)-即“标准错误”。有趣的是,即使 1 只是一个指向标准输出的指针,将指针 2 重定向到 12>&1
并不会形成一个指针链 2 -> 1 -> 标准输出。如果是这样,由于将 1 重定向到 /dev/null,代码2>&1 >/dev/null
会给指针链 2 -> 1 -> /dev/null,因此代码不会产生任何东西,与我们上面看到的相反。
Finally, I'd note that there is a simpler way to do this:
最后,我注意到有一种更简单的方法可以做到这一点:
From section 3.6.4 here, we see that we can use the operator &>
to redirect both stdout and stderr. Thus, to redirect both the stderr and stdout output of any command to \dev\null
(which deletes the output), we simply type
$ command &> /dev/null
or in case of my example:
从这里的第 3.6.4 节,我们看到我们可以使用运算符&>
重定向 stdout 和 stderr。因此,要将任何命令的 stderr 和 stdout 输出重定向到\dev\null
(删除输出),我们只需键入
$ command &> /dev/null
或在我的示例中:
$ (echo "stdout"; echo "stderror" >&2) &>/dev/null
Key takeaways:
关键要点:
- File descriptors behave like pointers (although file descriptors are not the same as file pointers)
- Redirecting a file descriptor "a" to a file descriptor "b" which points to file "f", causes file descriptor "a" to point to the same place as file descriptor b - file "f". It DOES NOT form a chain of pointers a -> b -> f
- Because of the above, order matters,
2>&1 >/dev/null
is !=>/dev/null 2>&1
. One generates output and the other does not!
- 文件描述符的行为类似于指针(尽管文件描述符与文件指针不同)
- 将文件描述符“a”重定向到指向文件“f”的文件描述符“b”,会导致文件描述符“a”指向与文件描述符b - 文件“f”相同的位置。它不会形成一个指针链 a -> b -> f
- 由于上述原因,顺序很重要,
2>&1 >/dev/null
是 !=>/dev/null 2>&1
。一个生成输出,另一个不生成!
Finally have a look at these great resources:
最后看看这些很棒的资源:
Bash Documentation on Redirection, An Explanation of File Descriptor Tables, Introduction to Pointers