/dev/null 2>&1

解析:

/dev/null:代表空设备文件
> :代表重定向到哪里,例如:echo "123" > /home/123.txt
1 :表示stdout标准输出,系统默认值是1,所以">"等同于"1>"
2 :表示stderr标准错误&
& :表示等同于的意思,2>&1,表示2的输出重定向等同于1
在shell中,每个进程都和三个系统文件 相关联:标准输入stdin,标准输出stdout、标准错误stderr,三个系统文件的文件描述符分别为0,1、2。

command > /dev/null 2>&1 语句含义:

> /dev/null : 表示标准输出重定向到空设备文件
2> &1 :标准错误输出重定向(等同于)标准输出
总的来说就是:将标准输出stdin重定向到/dev/null文件,即输出内容不打印到屏幕上,而是输出到/dev/null文件中。 2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了/dev/null文件,即将标准出错也输出到/dev/null文件中。即 >/dev/null 2>&1 相当于 1>/dev/null 2>/dev/null ,不过两者也存在区别

两者的区别:

  • command >file 2>file:stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖。
  • command >file 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。
  • command >file 2>file相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;
  • command>filel 2>&1 只使用了一个管道FD1,但已经包括了stdout和stderr。
    从IO效率上来讲,command >a 2>&1的效率更高。

下面通过一个例子来展示2>&1的效果:

$ cat test.sh
t
date

test.sh脚本中包含两个命令:
1、(t)是一个不存在的命令,执行会报错,默认情况下,错误会输出到stderr。
2、(date)则能正确执行,并且输出时间信息,默认输出到stdout

$sh test.sh > test1.log
./test.sh: line 1: t: command not found
$ cat test1.log
Wed Jul 10 21:12:02 CST 2013

(date)的执行结果被重定向到test1.log文件中,而(t)无法执行的命令错误则只打印在屏幕上。

$ sh test.sh > test2.log 2>&1
$ cat test2.log
./test.sh: line 1: t: command not found
Tue Oct 9 20:53:44 CST 2007

(date)和(t)的执行结果都被重定向到test2.log文件中。

试想一下1与&1代表什么?

  2>1
     2>代表标准错误重定向,1代表将标准错误重定向到一个文件1,而不代表标准输出;
  2>&1
     2>代表标准错误重定向,&1就代表标准输出stdout了,就变成将标准错误重定向到标准输出。
  测试:
         ls xx >out.txt 2>1测试,没有xx这个文件的标准错误输出到了文件1中,out.txt文件是空的;假如文件1和out.txt不存在,系统会自动创建;
/dev/null 2>&1_第1张图片
stderr输出到文件1.png
         ls xx >out1.txt 2>&1测试,没有文件1生成,没有xx这个标准错误输出在out1.txt文件中;
/dev/null 2>&1_第2张图片
stderr输出到文件out1.txt.png

为何2>&1要写在后面?

 command > file 2>&1 
    首先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出的行为,也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。 
 command 2>&1 >file 
   2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重定向到file,但标准错误仍然保持在终端。

用strace可以看到:

  1. command > file 2>&1
    这个命令中实现重定向的关键系统调用序列是:
    open(file) == 3
    dup2(3,1)
    dup2(1,2)
  1. command 2>&1 >file
    这个命令中实现重定向的关键系统调用序列是:
    dup2(1,2)
    open(file) == 3
    dup2(3,1)

可以考虑一下不同的dup2()调用序列会产生怎样的文件共享结构。参考APUE 3.10, 3.12

你可能感兴趣的:(/dev/null 2>&1)