linux shell 数据重定向详细解析

来源:互联网 发布:扫描录入软件 编辑:程序博客网 时间:2024/09/21 08:15

系统的stdin,stdout,stderr

以前一直了解的linux数据重定向就是> ,>>, <,<<这样的,今天刚好在看linux shell 脚本攻略时候发现重定向还是大有文章的,于是结合书跟网上一些博客,再一些实践,应该是对其各种情况比较清晰了。做个总结。

首先说到数据重定向,得先说到文件描述符,文件描述符是用来跟踪已经打开的文件, 其实就像我们在C语言中使用open等文件操作函数后会返回一个fd的整数一样,我们使用这些文件描述符来操作文件。linux中,最常见的文件描述符是stdin, stdout, stderr。下面我们详细讲下各种情况。

inux启动后,会默认打开3个文件描述。如下:

1) 0——stdin (标准输入)      对应/dev/stdin

2) 1 ——stdout(标准输出)   对应/dev/stdout

3) 2 ——stderr (标准错误)   对应 /dev/stderr

以后打开文件后。新增文件绑定描述符 可以依次增加。 一条shell命令执行,都会继承父进程的文件描述符。因此,所有运行的shell命令,都会有默认3个文件描述符。

而一个命令的执行过程是这样的:

先有一个输入:输入可以从键盘,也可以从文件得到。

命令执行完成:成功了,会把成功结果输出到屏幕:standard output默认是屏幕

命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕

在说这个之前,一定要先说一个点,那就是 > 是等同于 1> ,<等同于 0<   因为这样就不会对后面在<前出现个文件描述符就有点懵了。其实就是如果想使用特定的文件描述符,那么必须将描述符编号放在操作符之后,而在操作符之后涉及另一个文件描述符,那么就是在操作符之后使用&m,也就是 n<&m (其中<换做其他的<< 或者> >都一样的道理),也就是在操作符前边的文件描述符直接用,在操作符之后的文件描述符加个& ,这估计就是我看了、实践一上午的总的收获了,后面根据这点来解释很多就好懂很多了。不过这点只是我从实践中总结出来的,不知道是不是正确的,如果有错误指导到的地方望见谅。

下面先用表格列出常用形式,后面用的时候再说。

输出重定向

 输入重定向

 绑定重定向

用上面的红色字体就很好解释上面的这些用法了,例如就不会突然对cmd 2 > filename 迷糊了,也不会对 2>&1迷糊了(将pd=2的错误输出给定向到pd=1的标准输出中) 看上面在使用 文件描述符时候,都是在操作符前的就直接用,在操作符之后的加个&

下面用一些实践的例子来实践:

<span style="font-size:14px;"><span style="font-size:18px;">#显示当前目录下的opr.sh及a,其中a是不存在的,正确输出与错误都显示在屏幕(默认)[root@localhost Desktop]# ls opr.sh  als: cannot access a: No such file or directoryopr.sh#将正确的结果存到out.txt 错误输出依旧在屏幕[root@localhost Desktop]# ls opr.sh  a > out.txtls: cannot access a: No such file or directory[root@localhost Desktop]# cat out.txt opr.sh#将错误输出重定向到err.txt中,这时候正确的输出在屏幕上[root@localhost Desktop]# ls opr.sh  a 2> err.txtopr.sh[root@localhost Desktop]# cat err.txt ls: cannot access a: No such file or directory#将stderr重定向到stdout中,这样错误与正确的输出都输出到out.txt[root@localhost Desktop]# ls opr.sh  a > out.txt 2>&1[root@localhost Desktop]# cat out.txt ls: cannot access a: No such file or directoryopr.sh#将stdout重定向到out.txt  stderr重定向追加到err.txt[root@localhost Desktop]# ls opr.sh  a > out.txt 2>>err.txt [root@localhost Desktop]# cat out.txt err.txt opr.shls: cannot access a: No such file or directoryls: cannot access a: No such file or directory[root@localhost Desktop]# cat out.txt opr.sh[root@localhost Desktop]# cat err.txt ls: cannot access a: No such file or directoryls: cannot access a: No such file or directory[root@localhost Desktop]#</span></span>

利用追加方式也可以进行类似的实践,感兴趣的童靴自己动手吧~结合上面的表格,实践下功能

总结:默认的标准输出跟标准错误默认都是屏幕。如果你已经将标准输出定位到了新的文件,如果屏幕还输出了信息,那么那些是没执行成功的错误信息

如果有些输出太多,我们不希望他们刷屏了,我们可是使用关闭标准输出,错误或者将要屏蔽的信息给输出到空设备/dev/null中

<span style="font-size:14px;"><span style="font-size:18px;">#将标准输出输出到空设备,所以屏幕只输出错误[root@localhost Desktop]# ls opr.sh  a >/dev/nullls: cannot access a: No such file or directory#将stdout跟stderr都重定向到空设备,所以都不输出[root@localhost Desktop]# ls opr.sh  a 1>/dev/null  2>/dev/null#功能同上,直接一个& 就代表了stdout及stderr[root@localhost Desktop]# ls opr.sh  a &>/dev/null#将stderr重定向到stdout 然后再将stdout重定向到空设备[root@localhost Desktop]# ls opr.sh  a 1>/dev/null 2>&1 [root@localhost Desktop]# ls opr.sh  a >/dev/nullls: cannot access a: No such file or directory#关闭stderr 利用&-表示关闭某流[root@localhost Desktop]# ls opr.sh  a 2>&-opr.sh#同时关闭stderr 及stdout[root@localhost Desktop]# ls opr.sh  a 2>&- 1>&-[root@localhost Desktop]# </span></span>
输入重定向

默认的输入是从键盘上输入,但是我们同样可以将输入定位为文件或者设备。输入重定向为 <(截断) 或<<(追加)(其实记住< >哪个是输入还是输出的挺好记的,就是看箭头指向方向,a<b,可知由b指向a 那么就是输入是b,输出到a)

看下下面将文件重定向到命令的

<span style="font-size:14px;"><span style="font-size:18px;">[root@localhost Desktop]# echo "hello ,this is an input file"> a.txt#将输入重定向到命令[root@localhost Desktop]# cat <a.txt hello ,this is an input file#将输入重定向到屏幕,再将屏幕的重定向到out.txt[root@localhost Desktop]# cat >out.txt<a.txt [root@localhost Desktop]# cat out.txt hello ,this is an input file[root@localhost Desktop]#</span></span>

自定义文件描述符

我们可以使用exec来自己定义一些文件描述符.

例如 创建一个文件描述符进行文件读取

<span style="font-size:14px;"><span style="font-size:18px;">#查看下现在系统中有的文件描述符[root@localhost Desktop]# ls /proc/self/fd01  2  3[root@localhost Desktop]# echo "this is a test input">input.txt#使用文件描述符4打开并读取文件[root@localhost Desktop]# exec 4<input.txt[root@localhost Desktop]# cat <&4this is a test input#现在系统中的文件描述符多了4[root@localhost Desktop]# ls /proc/self/fd01  2  3  4#用完关闭是个好习惯[root@localhost Desktop]# exec 4>&-[root@localhost Desktop]# ls /proc/self/fd0  1  2  3</span></span>
同样,我们创建一个文件描述符用于写入(假定我们使用的是追加模式)

<span style="font-size:14px;"><span style="font-size:18px;">#追加模式创建一个描述符文件用于写入[root@localhost Desktop]# exec 5>>output.txt[root@localhost Desktop]# echo "this is a outut test">&5[root@localhost Desktop]# echo "append to it">&5[root@localhost Desktop]# cat output.txt this is a outut testappend to it[root@localhost Desktop]# exec 5>&-</span></span>

tee——既将数据重定向,同时提供一份副本给后续命令作为stdin

我们对stderr或者stdout进行重定向后,被重定向的文本会被传入文件,因为已经被重定向到了文件,也就没剩下什么东西可以通过管道传给接下来的命令了。而如果我们希望将stdout,stderr也复制一份副本作为stdin给后续命令,那么可以使用tee

使用方法: cmd | tee file1 file 

例如:

<span style="font-size:14px;"><span style="font-size:18px;">[root@localhost Desktop]# cat *txt | tee log | cat -n     1hello ,this is an input file     2ls: cannot access a: No such file or directory     3ls: cannot access a: No such file or directory     4this is a test line     5this is a test input     6#include <stdio.h>     7#include <string.h>     8#include <math.h>     9#include <myself.h>    10OF     11this is a outut test    12append to it    13hello ,this is an input file[root@localhost Desktop]# cat loghello ,this is an input filels: cannot access a: No such file or directoryls: cannot access a: No such file or directorythis is a test linethis is a test input#include <stdio.h>#include <string.h>#include <math.h>#include <myself.h>OF this is a outut testappend to ithello ,this is an input file</span></span>
tee接收来自stdin的数据,将stdout的一份副本写入到log文件,同时将另一份副本作为后续命令的stdin, 命令cat -n 是从stdin收到的每行数据前边加上行号(课查看man)并写到stdout(默认的屏幕)

0 0
原创粉丝点击