找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

Linux操作系统-文件重定向详解

admin 2019-11-25 11:09 92人围观 Linux相关

背景:在Linux 环境运行过服务的童鞋可能都使用过这样的指令:

nohup ./需要执行的脚本名称 > /dev/null 2>&1 &

但是不是所有童鞋都很彻底理解后面对输出流的处理是什么意思。这篇文章就准备讲讲 > /dev/null  2>&1 的作用,也是作者想对Linux的知识查漏补缺有感而发。

在理解这个2>&1 之前,我们首先要理解linux 的输出处理方式:流。

一、linux 的输出流

简单来说,linux 的流处理方式和java8 新增的lambda 表达式非常类似,前一个命令的输出,就是下一个命令的输入。

还是从案例入手:我们如何通过一行指令,获取一个centos 系统的ip?

比如 ifconfig 的输出是这样的:



这里我直接放最终指令,感兴趣的可以自己了解其中的head、grep 和 sed 指令的作用

ifconfig | grep inet | head -n 1 | sed 's/.*inet //g' | sed 's/ netmask.*//g'

简单来说逻辑就是先查看网口的信息,然后从整个信息中再提取到最终的ip。

了解了这点,我们再来看看 > /dev/null > 2>&1 这里到底做了什么。

二、标准输出和错误输出,以及/dev/null

1、通过案例来看标准输出和错误输出

标准输出:比如我们正常用echo、cat 来打印变量或者是文件内容,这种正常的输出就是标准输出。

错误输出:指令执行的时候出现错误,比如修改一个不可写文件的内容,又或者是删除一个不存在的目录,这种都是错误输出。

标准输出:正常查看一个目录下的所有内容



错误输出:



另外稍微提一下重定向这个概念:标准输出和错误输出他们相当于是两个socket,这两个socket 本身的信息是相互隔离的,但是我们可以通过重定向,将某个socket 的信息先导入到另一个socket,然后再通过命令行打印出来。

下一节就来看看重定向的具体指令,还是通过示例来理解。

2、流操作的顺序

在讲 /dev/null 之前,我们还是要先理解流操作也是有顺序的,为什么 > /dev/null 要放在 2>&1 前面?肯定是有原因的。

让我们看看下面几个指令:理解一下最后会产生什么结果(尽量自己先猜测下执行效果,再看分析)

(参考博客:

https://www.cnblogs.com/caolisong/archive/2007/04/25/726896.html)

1)ll not_exist_folder > output.txt

命令行输出:

ls: cannot access not_exist_folder: No such file or directory

文件输出:



首先命令行的输出,是来自标准输出和错误输出的。

>output.txt 仅仅是将标准输出 导入到了文件中,并没有将错误输出导入进去。因此命令行还是会打印错误输出,而output.txt 中什么内容都没有。

扩展:如果是执行 ll kafka_2.12-2.3.1 > output.txt ,那么结果就刚好反过来了,标准输出打印到了文件中,而命令行没有任何输出。

2)ll not_exist_folder 2>1

命令行输出:



文件输出:

ls: cannot access not_exist_folder: No such file or directory(1)

注意这里>1 并不是重定向,>&1 才是重定向,因此这句话相当于将错误输出导入到了“1” 这个文件中。

3)ll not_exist_folder 2>&1

命令行输出:

ls: cannot access not_exist_folder: No such file or directory

文件输出:



这个语句就是真正的重定向了,将错误输出重定向到标准输出,因此命令行依然会打印错误信息。

4)ll not_exist_folder 2>output.txt

和2) 的结果是一样的,这里不多赘述。

5)ll not_exist_folder 2>&1 > output.txt

命令行输出:

ls: cannot access not_exist_folder: No such file or directory

文件输出:



这里也许会有一些同学不理解了:最后我不是将输出重定向到了output.txt 文件中么?为什么文件会没有内容呢?

这里就涉及到顺序的问题了,问题就在于输出到文件放到了“最后”。

2>&1 先把错误输出重定向到了标准输出,然而标准输出到这一步,它还是对应命令行输出的,因此错误输出会直接打印出来。最后的 > output.txt ,将标准输出重定向到文件的时候,其实错误输出的流里面已经没有内容了。所以最后文件的内容就是空的。

6)ll not_exist_folder > output.txt 2>&1

命令行输出:



文件输出:

ls: cannot access not_exist_folder: No such file or directory

这个才是将标准输出和错误输出都导入到文件的正确方式。

首先 > output.txt 会将标准输出导入到文件中,然后 2>&1 会按照 错误输出 -> 标准输出 -> output.txt 的顺序,将错误信息导入到文件中。

7)ll not_exist_folder &> output.txt

命令行输出:



文件输出:

ls: cannot access not_exist_folder: No such file or directory

其实效果和6) 是一样的,只不过指令比较方便使用:&> 表示直接将标准输出和错误输出都重定向到同一个目标。

3、/dev/null

(参考博客:

https://www.maketecheasier.com/dev-null-in-linux/)

最后我们来看看 /dev/null 这个文件的作用。

其实 /dev/null 并不是一个真正的文件,它相当于操作系统的一个“黑洞”,所有进去的东西都会被直接丢弃,不占用任何空间。

因此它的用途就是忽略掉我们不关注的日志打印,或者是文件下载等等。

另一个示例:仅测试文件下载速度,不下载实际的文件

wget -O /dev/null https://www-eu.apache.org/dist/kafka/2.3.1/kafka-2.3.1-src.tgz

相信看到这里,同学们应该对linux 的重定向有了一定了解了。当然回过头来看,文章开头的那个指令还是不建议使用的,因为日志完全被丢弃了,有错误啥都看不到。除非你对 nohup 执行的脚本 很有自信,不会出错,否则生产环境不建议使用哈~

扩展:详细了解linux 的文件描述符

https://en.wikipedia.org/wiki/File_descriptor


----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:小李子的小日常,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!

我有话说......