我们在编程中经常会使用一些固定语句来解决对应固定的问题,在 shell 脚本中一个被经常使用但不太好理解的短句就是 2>&1,例如:

ls foo > /dev/null 2>&1

下面我们一步步了解下这种结构的含义。

I/O redirection 重定向

简单理解,redirection 重定向就是将一个命令的 output 输出发送到另一个地方。例如,我们通过 cat 命令打印一个文件的内容到屏幕:

$ cat foo.txt
foo
bar
baz

我们也可以将输出的内容发送到其他地方,例如将内容重定向到另一个文件 file.txt:

$ cat foo.txt > output.txt

$ cat output.txt
foo
bar
baz

执行第一条 cat 命令,我们不会看到任何输出信息,因为我们修改了 standard output (stdout)标准输出到一个文件,所以它就不会输出到屏幕了。

需要注意的是还有另一个地方:standard error (stderr)标准错误,当有错误时会输出信息。所以当我们通过 cat 命令输出一个不存在的文件内容时:

$ cat nop.txt > output.txt
cat: nop.txt: No such file or directory

以上示例中即使我们将 stdout 重定向到一个文件了,由于 output.txt 不存在,stderr 依然会输出错误信息到屏幕。因为我们重定向的只是 stdout 而不包括 stderr

file descriptors 文件描述器

一个文件描述器是一个正整数,用来表示一个打开文件的。每个文件都有其各自的文件描述器。这里我们只需要知道 stdoutstderr 有其各自的文件描述器 id 定义了它们各自的地址。

stdout1stderr2

在之前的示例中,我们可以修改命令为如下结构:

cat foo.txt 1> output.txt

这里的 1 就是 stdout 的文件描述器,通过重定向语法 [FILE_DESCRIPTOR]>stdout 重定向到另一个文件。注意 1> 可以简写为 >

类似的,可以将 stderr 重定向到指定的目的地:

$ cat nop.txt 2> error.txt

$ cat error.txt
cat: nop.txt: No such file or directory

这样就会将 error 存入 error.txt 文件,屏幕上不会输出任何信息。

下面我们理解下 2>&1 的意义。我们使用 &1 来指向 stdout 的重定向地址,所以 2>&1 表示重定向 stderr 到和 stdout 同样的重定向位置上。所以我们就可以通过下面示例的方法同时将 stdoutstderr 重定向到同一个文件中:

$ cat foo.txt > output.txt 2>&1

$ cat output.txt
foo
bar
baz

$ cat nop.txt > output.txt 2>&1

$ cat output.txt
cat: nop.txt: No such file or directory

总结

  • 有两个地方用来让程序发送输出内容:stdoutstderr
  • 可以单独定义两个输出的重定向目的地
  • 文件描述器用来识别 stdout (1)stderr (2)
  • command > outputcommand 1> output 的简写
  • 通过 &[FILE_DESCRIPTOR] 指向一个文件描述器的重定向目标地址上
  • 2>&1 可以将 stderr 重定向到 stdout 同样的重定向地址上。反之亦然。

参考链接

Understanding Shell Script's idiom: 2>&1
In the shell, what does “ 2>&1 ” mean?

标签: none

添加新评论