Linux/Unix 中的标准输出与错误输出

在 Linux/Unix 系统中,屏幕上显示的信息通常来源于 stdout(Standard Output,标准输出)或者 stderr(Standard Error,标准错误输出)。

许多人会问:output 就是 output,直接送到屏幕上不就行了,为什么要分成 stdout 和 stderr 呢?

这是因为在服务器工作环境下,几乎所有的程序都是运行在后台(background)的。为了方便调试(debug),一般在设计程序时,会将正常的 stdout 送到一个文件,而将错误的信息 stderr 存到不同的文件中。

  • 正常的 output:例如程序开始运行的时间、当前在线人数等。
  • 错误的 output:例如无法找到用户想要访问的 URL,或者信用卡认证失败等。

什么是 /dev/null

有了上述认知后,我们再来看什么是 > /dev/null

这条命令的意思是将 stdout 送到 /dev/null 里面。

那么,什么是 /dev/null 呢?/dev/null 是 Unix/Linux 里的「无底洞」。任何 output 送去了「无底洞」就再也无法找回了。相信我,数据真的消失了!

那么,在什么情况下要把 output 送去这个无底洞呢?这里没有标准答案,但通常来说,如果你不想看到 output,或者 output 太多太大,有可能把硬盘占满的时候,程序设计就会考虑将 output 送到 /dev/null

重定向语法详解:>/dev/null 2>&1

在 Shell 脚本中,经常能看到 >/dev/null 2>&1 这样的写法。这条命令的意思是将标准输出错误输出全部重定向到 /dev/null 中,也就是将产生的所有信息丢弃。

命令的结果可以通过 %> 的形式来定义输出。我们可以将这个组合 >/dev/null 2>&1 分解为五个部分来理解:

  1. >:代表重定向到哪里。例如:echo "123" > /home/123.txt
  2. /dev/null:代表空设备文件。
  3. 2>:表示 stderr(标准错误)。
  4. &:表示等同于的意思。2>&1 表示 2 的输出重定向等同于 1。
  5. 1:表示 stdout(标准输出)。系统默认值是 1,所以 >/dev/null 等同于 1>/dev/null

因此,>/dev/null 2>&1 也可以写成 1>/dev/null 2>&1

执行过程解析

上述语句的执行过程如下:

  1. 1>/dev/null:首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
  2. 2>&1:接着,标准错误输出重定向到标准输出。因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也随之重定向到空设备文件。

command > file 2>filecommand > file 2>&1 的区别

下面就为大家说明一下,command > file 2>filecommand > file 2>&1 有什么不同的地方。

  • command > file 2>file
    意思是将命令所产生的标准输出信息,和错误的输出信息送到 file 中。这样的写法,stdout 和 stderr 都直接送到 file 中,file 会被打开两次。这样 stdout 和 stderr 会互相覆盖,相当使用了 FD1 和 FD2 两个文件描述符同时去抢占 file 的管道。
  • command > file 2>&1
    这条命令将 stdout 直接送向 file,stderr 继承了 FD1 管道后,再被送往 file。此时,file 只被打开了一次,也只使用了一个管道 FD1,它包括了 stdout 和 stderr 的内容。

从 I/O 效率上来看,前一条命令的效率要比后一条命令的效率低。所以在编写 Shell 脚本的时候,较多的时候我们会用 command > file 2>&1 这样的写法。

说明:本文所述重定向语法适用于大多数 Bourne Again Shell (Bash) 及兼容的 POSIX Shell 环境。