Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux cmd>/开发/空2>&;1工作?_Linux_Bash_Shell_Unix - Fatal编程技术网

Linux cmd>/开发/空2>&;1工作?

Linux cmd>/开发/空2>&;1工作?,linux,bash,shell,unix,Linux,Bash,Shell,Unix,我正在阅读将数据重定向到/dev/null,因此我尝试了一个简单的测试: ping a.b.c # which results in an address not found 如果我尝试这样做: ping a.b.c > /dev/null # prints the same error message as the one above 但是,如果我这样做: ping a.b.c > /dev/null 2>&1 # The error message is go

我正在阅读将数据重定向到
/dev/null
,因此我尝试了一个简单的测试:

ping a.b.c  # which results in an address not found
如果我尝试这样做:

ping a.b.c > /dev/null # prints the same error message as the one above
但是,如果我这样做:

ping a.b.c > /dev/null 2>&1 # The error message is gone
最后一个解决方案是所需的解决方案,但此
2>&1
发生了什么?到目前为止,我的研究表明
2
代表
stderr
1
代表
stdout
。所以如果我这样读的话,它看起来就像我正在创建一个
stderr
文件,并将
stdout
重定向到它


如果是这种情况,那么该命令中的
&
是做什么的

你说得对,
2
STDERR
1
STDOUT
。当您执行
2>&1
时,您是在说:“打印到
STDOUT
1
)将要转到
STDERR
2
)的内容。”。在此之前,您说过您的
标准输出将转到
/dev/null
。因此,什么也看不见。在示例1和2中,您得到输出消息是因为它被打印到
STDERR
,作为常规重定向,它只重定向
STDOUT


当您执行重定向时,您不是在创建
STDERR
,进程在创建时总是有
STDERR
STDOUT

考虑下面的代码,它将单词“stdout”打印到stdout,将单词“stderror”打印到stderror

$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror
注意,&运算符告诉bash 2是一个文件描述符(指向stderr),而不是一个文件名。如果我们省略了“&”,这个命令将把
stdout
打印到stdout,并创建一个名为“2”的文件,然后在那里写入
stderror

通过使用上面的代码进行实验,您可以清楚地看到重定向操作符是如何工作的。例如,通过更改将两个描述符1,2中的哪一个重定向到
/dev/null
的文件,以下两行代码将分别删除stdout和stderror中的所有内容(打印剩余内容)

现在,我们接近问题的关键(用我的例子代替你的),为什么

(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1
没有产出?为了真正理解这一点,我强烈建议您阅读本文。假设你已经读过了,我们可以继续。注意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,这就是不呈现输出的原因


为了测试您是否真正理解这个概念,请在切换重定向顺序时尝试猜测输出:

(echo "stdout"; echo "stderror" >&2)  2>&1 >/dev/null
斯特德罗

这里的理由是,从左到右求值,Bash看到2>&1,因此将文件描述符2设置为指向与文件描述符1相同的位置,即stdout。然后设置文件描述符1(请记住>/dev/null=1>/dev/null)指向>/dev/null,从而删除通常发送到标准输出的所有内容。因此,我们只剩下子shell(括号中的代码)中没有发送到标准输出的内容,即“stderror”。 值得注意的是,尽管1只是一个指向标准输出的指针,但通过
2>&1
将指针2重定向到1并不会形成指针链2->1->标准输出。如果是这样,则由于将1重定向到/dev/null,代码
2>&1>/dev/null
将给出指针链2->1->/dev/null,从而得到与我们上面看到的相反,de不会产生任何结果


最后,我要指出,有一种更简单的方法:

从第3.6.4节中,我们可以看到,我们可以使用操作符
&>
重定向stdout和stderr。因此,要将任何命令的stderr和stdout输出重定向到
\dev\null
(删除输出),只需键入
$command&>/dev/null
或者以我为例:

$ (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知道
1
不是文件名,而是
stderr
。顺便说一句,你不必使用
ping a.b.c 2>/dev/null
ping a.b.c&>/dev/null
应该这样做。@Joketster谢谢!如果
1
不是文件名,那是什么?只是内存?你应该得到的“/dev/null:权限被拒绝",因为您试图将
/dev/null
作为一个命令执行。它应该是
/dev/null
,而不是
/dev/null
@nkon,shell使用相同的约定。请注意,您可以编写:
ping abc.example.com 2>/dev/null
,以便在不丢弃标准输出的情况下丢弃错误消息。@nkon如果需要,您实际上可以看到哪个文件描述符附加到进程。要做到这一点,请找到pid——例如,
pgrep firefox
。然后
ls-l/proc//fd
——注意,fd实际上在目录中表示为符号链接
$ (echo "stdout"; echo "stderror" >&2) &>/dev/null