linux shell 数据重定向详细解析

系统的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 (其中<换做其他的<< 或者> >都一样的道理),也就是在操作符前边的文件描述符直接用,在操作符之后的文件描述符加个& ,这估计就是我看了、实践一上午的总的收获了,后面根据这点来解释很多就好懂很多了。不过这点只是我从实践中总结出来的,不知道是不是正确的,如果有错误指导到的地方望见谅。

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

输出重定向

linux shell 数据重定向详细解析_第1张图片

 输入重定向

linux shell 数据重定向详细解析_第2张图片

 绑定重定向

linux shell 数据重定向详细解析_第3张图片

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

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

#显示当前目录下的opr.sh及a,其中a是不存在的,正确输出与错误都显示在屏幕(默认)
[root@localhost Desktop]# ls opr.sh  a
ls: cannot access a: No such file or directory
opr.sh
#将正确的结果存到out.txt 错误输出依旧在屏幕
[root@localhost Desktop]# ls opr.sh  a > out.txt
ls: 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.txt
opr.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 directory
opr.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.sh
ls: cannot access a: No such file or directory
ls: 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 directory
ls: cannot access a: No such file or directory
[root@localhost Desktop]#

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

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

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

#将标准输出输出到空设备,所以屏幕只输出错误
[root@localhost Desktop]# ls opr.sh  a >/dev/null
ls: 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/null
ls: 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]# 
输入重定向

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

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

[root@localhost Desktop]# echo "hello ,this is an input file"> a.txt
#将输入重定向到命令
[root@localhost Desktop]# cat out.txt

自定义文件描述符

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

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

#查看下现在系统中有的文件描述符
[root@localhost Desktop]# ls /proc/self/fd
0	1  2  3
[root@localhost Desktop]# echo "this is a test input">input.txt
#使用文件描述符4打开并读取文件
[root@localhost Desktop]# exec 4&-
[root@localhost Desktop]# ls /proc/self/fd
0  1  2  3
同样,我们创建一个文件描述符用于写入(假定我们使用的是追加模式)

#追加模式创建一个描述符文件用于写入
[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 test
append to it
[root@localhost Desktop]# exec 5>&-

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

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

使用方法: cmd | tee file1 file 

例如:

[root@localhost Desktop]# cat *txt | tee log | cat -n
     1	hello ,this is an input file
     2	ls: cannot access a: No such file or directory
     3	ls: cannot access a: No such file or directory
     4	this is a test line
     5	this is a test input
     6	#include 
     7	#include 
     8	#include 
     9	#include 
    10	OF 
    11	this is a outut test
    12	append to it
    13	hello ,this is an input file
[root@localhost Desktop]# cat log
hello ,this is an input file
ls: cannot access a: No such file or directory
ls: cannot access a: No such file or directory
this is a test line
this is a test input
#include 
#include 
#include 
#include 
OF 
this is a outut test
append to it
hello ,this is an input file
tee接收来自stdin的数据,将stdout的一份副本写入到log文件,同时将另一份副本作为后续命令的stdin, 命令cat -n 是从stdin收到的每行数据前边加上行号(课查看man)并写到stdout(默认的屏幕)

你可能感兴趣的:(脚本)