转载自:【博客408】“2>/dev/null“ 和 “>/dev/null 2>&1“ 和 “2>&1>/dev/null“ 之间的区别

重点

# 标准输出1  默认行为 输出到屏幕

# 一般都是采用这种写法
# 标准输出、标准错误  都写入到 file 中
command > file 2>&1 :

# 此种写法会导致 标准错误未写入 file
# 标准错误 输出到屏幕,标准输出写入到 file 中 
command 2>&1 >file :

内容讲解

内容:记录linux下的文件输出重定位

/dev/null:

/dev/null是Linux的一个空设备文件,可以将不需要的输出来输出到这里;

这个重要词解析:

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

linux预留的文件描述符:

Linux系统预留可三个文件描述符:012,他们的意义如下所示:
0——标准输入(stdin1——标准输出(stdout2——标准错误(stderr

易混点:

cmd >a 2>a 和 cmd >a 2>&1 有什么不同?

cmd >a 2>a :stdoutstderr都直接送往文件 a ,a文件会被打开两遍,
             由此导致stdoutstderr互相覆盖。
cmd >a 2>&1stdout直接送往文件a ,stderr是继承了FD1的管道之后,
              再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。

两者的不同点在于:
cmd >a 2>a 相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;
cmd >a 2>&1 只使用了一个管道FD1,但已经包括了stdoutstderr。
从IO效率上来讲,cmd >a 2>&1的效率更高。

经常在一些脚本中看到如下用法:

/tmp/test.sh > /tmp/test.log 2>&1

/tmp/test.sh > /tmp/test.log :把标准输出打到文件中
2>&1 :的意思就是将标准错误也输出到标准输出当中,从而一起打到文件中

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

command > file 2>&1 :

command > file将标准输出重定向到file中, 2>&1是标准错误拷贝了标准输出的行为,
也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。
 
command 2>&1 >file :

2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重
定向到file,但标准错误仍然保持在终端。


用strace可以看到: (strace用于追踪命令的真实执行情况)

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

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

“2>/dev/null” 和 “>/dev/null 2>&1” 和 “2>&1>/dev/null” 之间的区别:

12>/dev/null
意思就是把错误输出到“黑洞”

2>/dev/null 2>&1
默认情况是1,也就是等同于1>/dev/null 2>&1。意思就是把标准输出重定向到“黑洞”,
还把错误输出2重定向到标准输出1,也就是标准输出和错误输出都进了“黑洞”

32>&1 >/dev/null
意思就是把错误输出2重定向到标准输出1,也就是屏幕,标准输出进了“黑洞”,也就是标准
输出进了黑洞,错误输出打印到屏幕

容易混淆的地方:>/dev/null 2>&1

shell中可能经常能看到:>/dev/null 2>&1


分解这个组合:“>/dev/null 2>&1” 为五部分:

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

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

执行过程为:
11>/dev/null :首先表示标准输出重定向到空设备文件,即不输出任何信息到终端
22>&1 :接着,标准错误输出重定向 到标准输出,因为之前标准输出已经重定向到了
            空设备文件,所以标准错误输出也重定向到空设备文件。
Logo

更多推荐