文章482
标签257
分类63

Linux输出流重定向

在shell中可能经常能看到类似的命令:echo log > /dev/null 2>&1,将输出流重定向;

本文介绍了这些重定向符号的含义;


Linux输出流重定向

对于一个命令的结果,可以通过%>的形式来定义;

下面来看这条命令echo log > /dev/null 2>&1

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

因此,1 > /dev/null 2>&1语句的含义就是:

  • 1 > /dev/null:首先,将标准输出重定向到空设备文件,也就是不输出任何信息到终端;
  • 2>&1 :接着,标准错误输出重定向(等同于)标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件;

所以,命令的标志输出、标准错误输出都不显示!


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

cmd >a 2>a:stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖!

cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a,因此a文件只被打开一遍,就是FD1将其打开!

两者的不同点在于:

cmd >a 2>a相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;

cmd >a 2>&1只使用了一个管道FD1,但已经包括了stdout和stderr;

同时,从IO效率上来讲,cmd >a 2>&1的效率更高;


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

对于命令command > file 2>&1

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

对于命令command 2>&1 > file:表示2>&1标准错误首先拷贝了标准输出的行为,但此时标准输出还是在终端,>file后的输出才被重定向到file,因此此时标准错误仍然保持在终端;

使用strace可以看到:

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

不同的dup2()调用序列会产生不同的文件共享结构;


典型案例

在将一些程序后台启动时,我们通常需要将输出写入日志文件,此时就需要用到重定向:

例如:

python main.py > ./log.txt 2>&1 &

这样,命令python main.py在后台执行,并同时将标准和错误日志输出至文件:log.txt中;


附录

文章参考:



本文作者:Jasonkay
本文链接:https://jasonkayzk.github.io/2021/06/24/Linux输出流重定向/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可