How does cmd > /dev/null 2>&1 work?
我正在阅读将数据重定向到
1 | ping a.b.c # which results in an address not found |
如果我试试这个:
1 | ping a.b.c > /dev/null # prints the same error message as the one above |
但是,如果我这样做:
1 | ping a.b.c > /dev/null 2>&1 # The error message is gone |
最后一个解决方案是理想的解决方案,但是这个
如果是这种情况,该命令中的
你是对的,
当您进行重定向时,您没有创建
考虑下面的代码,它将单词"stdout"打印到stdout,将单词"stderror"打印到stderror。
1 2 3 | $ (echo"stdout"; echo"stderror">&2) stdout stderror |
请注意'&' operator告诉bash 2是文件描述符(指向stderr)而不是文件名。如果我们省略'&',这个命令会将
通过试验上面的代码,您可以准确地了解重定向运算符的工作原理。例如,通过将哪两个描述符1,2中的哪个文件重定向到
1 2 3 4 | $ (echo"stdout"; echo"stderror">&2) 1>/dev/null stderror $ (echo"stdout"; echo"stderror">&2) 2>/dev/null stdout |
现在,我们接近问题的关键(用我的例子代替你的),为什么呢
1 | (echo"stdout"; echo"stderror">&2) >/dev/null 2>&1 |
没有产出?要真正理解这一点,我强烈建议您在文件描述符表上阅读此网页。假设你已经完成了阅读,我们就可以继续了。请注意Bash从左到右处理;因此,Bash首先看到
要测试您是否真的理解这个概念,请在切换重定向顺序时尝试猜测输出:
1 | (echo"stdout"; echo"stderror">&2) 2>&1 >/dev/null |
stderror
BLOCKQUOTE>
这里的推理是从左到右进行评估,Bash看到2>& 1,因此将文件描述符2设置为指向与文件描述符1相同的位置,即stdout。然后它设置文件描述符1(记住> / dev / null = 1> / dev / null)指向> / dev / null,从而删除通常发送到标准输出的所有内容。因此我们剩下的就是那些没有发送到子shell中的stdout(括号中的代码) - 即"stderror"。
值得注意的是,即使1只是指向stdout的指针,通过2>&1 将指针2重定向到1也不会形成指针链2 - > 1 - > stdout。如果是这样,由于将1重定向到/ dev / null,代码2>&1 >/dev/null 会给指针链2 - > 1 - > / dev / null,因此代码不会产生任何东西,与我们的对比见过上面。最后,我注意到有一种更简单的方法可以做到这一点:
从这里的3.6.4节,我们看到我们可以使用operator
&> 来重定向stdout和stderr。因此,要将任何命令的stderr和stdout输出重定向到\dev (删除输出),我们只需键入
ull
$ command &> /dev/null
或者在我的例子中:
1 $ (echo"stdout"; echo"stderror">&2) &>/dev/null关键要点:
- 文件描述符的行为类似于指针(尽管文件描述符与文件指针不同)
- 将文件描述符"a"重定向到指向文件"f"的文件描述符"b",使文件描述符"a"指向与文件描述符b-文件"f"相同的位置。它不会形成一个指针链a - > b - > f
- 由于上述原因,订单很重要,
2>&1 >/dev/null 是!=>/dev/null 2>&1 。一个产生输出而另一个不产生!最后看看这些很棒的资源:
有关重定向的Bash文档,文件描述符表的说明,指针简介