前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >shell 中 "2>&1" 的研究(你以为你会了,其实你根本就不会)

shell 中 "2>&1" 的研究(你以为你会了,其实你根本就不会)

作者头像
小小科
发布2018-05-02 17:14:42
6450
发布2018-05-02 17:14:42
举报
文章被收录于专栏:北京马哥教育北京马哥教育

前言

周五晚上,shuker,hades,我还有几位同事,我们一起加班到两点多,最后hades 在crontab 里添加了一个定时任务。

这本来没什么好说的,但是最后他有加了几个命令,我就看不懂了。

正文 先看看命令吧。

代码语言:javascript
复制
command >/dev/null 2>&1 &

对于 command >/dev/null 我是知道的。 command 是我的一个定时任务 大于号 > 代表重定向输出。 输出到了 /dev/null 了。 command >/dev/null 合起来就是把 command 的标准输出重定向到 /dev/null, 标准输出不显示在屏幕上.

最后面的一个 & 我也知道,代表后台执行。

但是这个 2>&1 是什么意思呢? 我查阅了一下资料,了解了一下,给大家说说我的理解吧。 可能理解有误或说的不够正确,请多多指教。

开始罗嗦

简单的说 2>&1 的含义是将标准出错重定向到标准输出,如果标准输出重定向到 /dev/null 了,标准错误也会重定向到 /dev/null 的。 2>&1 中的大于号 > 还是一个重定向输出。 2>1 代表 错误重定向到一个文件 1, 而不是标准输出。 对于 2>&1, & 与 1 结合就代表标准输出了,也就变成错误重定向到标准输出。 &1 更准确的说应该是文件描述符 1. 1 代表的STDOUT_FILENO. 实际上这个操作就是一个dup2(2)调用 2 STDERR_FILENO 0 从表示键盘输入

所以根据需求,我们可以写 >&0, >&1, >&2 等。

常见的 > 实际上是 1> 的简写。及把标准输出重定向到某个位置。 这样 2> 就是标准错误重定向某个位置了。 命令的结果可以通过“%>”的形式来定向输出 %表示文件描述符:1为标准输出stdout、2为标准错误stderr 系统默认%值是1,也就是“1>”,而1>可以简写为>,也就是默认为>。 stdout的默认目标是终端,stderr的默认目标为也是终端。

其中&需要直接与重定向符号结合使用。

那么 >& 的含义就是把所有输出(stdout,stderr)都重定向到某个地方。 于是我们也可以这样写了。 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的内容. 运行这四个命令就明白了

代码语言:javascript
复制
ls 2>1 #测试一下,不会报没有2文件的错误,但会输出一个空的文件1;
ls xxx 2>1 #测试,没有xxx这个文件的错误输出到了1中;
ls xxx 2>&1 #测试,不会生成1这个文件了,不过错误跑到标准输出了;
ls xxx >out.txt 2>&1 #实际上可换成 ls xxx 1>out.txt 2>&1;重定向符号>默认是1,错误和输出都传到out.txt了

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

代码语言:javascript
复制
command > file 2>&1

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

代码语言:javascript
复制
command 2>&1 >file

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

用strace可以看到:

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

代码语言:javascript
复制
open(file) == 3 
dup2(3,1) 
dup2(1,2)

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

代码语言:javascript
复制
dup2(1,2) 
open(file) == 3 
dup2(3,1)

继续查资料

后来看到有人这样写

代码语言:javascript
复制
command >& /dev/null

然后查阅到资料

代码语言:javascript
复制
重定向操作符    描述
>                将命令输出写入到文件或设备(如打印机),而不是命令提示符窗口或句柄。
<                从文件而不是从键盘或句柄读入命令输入。
>>              将命令输出添加到文件末尾而不删除文件中已有的信息。
>&               将一个句柄的输出写入到另一个句柄的输入中。
<&               从一个句柄读取输入并将其写入到另一个句柄输出中。
|                  从一个命令中读取输出并将其写入另一个命令的输入中。也称作管道。

< 操作符可以打开具有只读访问权限的指定文件名.因此,不能在使用该操作符时向文件中写入信息。 0 是 < 重定向输入操作符的默认句柄 1 是 > 重定向输出操作符的默认句柄。

参考资料

http://www.cnblogs.com/caolisong/archive/2007/04/25/726896.html http://viplin.blog.51cto.com/241472/99568 http://blog.csdn.net/scz123/article/details/1108856

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2014-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马哥Linux运维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档