导读小文:【http://www.ibm.com/developerworks/cn/linux/l-iotips/】 html
技巧:Linux I/O重定向的一些小技巧 linux
简介: Linux I/O 重定向虽然很简单,但在脚本编写、系统管理时却要经常打交道,搞清其中使用技巧很是有用。 shell
首先说一下什么是I/O重定向,所谓I/O重定向简单来讲就是一个过程,这个过程捕捉一个文件,或者命令,程序,脚本,甚至脚本中的代码块(code block)的输出,而后把捕捉到的输出,做为输入发送给另一个文件,命令,程序,或者脚本。 centos
标准输入一般指键盘的输入标准错误一般也是定向到显示器 app
#ls /dev 1>filename #注意:"1"和">"中间没有空格 学习
以上命令会把命令的标准输出从新定向到一个文件filename,而不是显示到屏幕上,若是不指明文件标识符, 系统默认的就是1, 所以1能够省略#ls /dev &>filename :"&"在这里表明标准输出和标准错误,这里不管是正常输出仍是错误信息都写到filename中了。 spa
从新定义文件标识符能够用i>&j命令,表示把文件标识符i从新定向到j,你能够把"&"理解为"取地址"请看如下例子 code
#exec 5>&1 :表示把文件标识符5定向到标准输出,这个命令一般用来临时保存标准输入。 htm
"&-"表示关闭文件标识符 blog
有关关闭文件标识符的操做请参考下面
在了解重定向以前,咱们先来看看linux 的文件描述符。
linux文件描述符:能够理解为linux跟踪打开文件,而分配的一个数字,这个数字有点相似c语言操做文件时候的句柄,经过句柄就能够实现文件的读写操做。 用户能够自定义文件描述符范围是:3-num,这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。
linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2
之后打开文件后。新增文件绑定描述符 能够依次增长。 一条shell命令执行,都会继承父进程的文件描述符。所以,全部运行的shell命令,都会有默认3个文件描述符。
对于任何一条linux 命令执行,它会是这样一个过程:
一个命令执行了:
先有一个输入:输入能够从键盘,也能够从文件获得
命令执行完成:成功了,会把成功结果输出到屏幕:standard output默认是屏幕
命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕
文件输入输出由追踪为一个给定的进程全部打开文件的整数句柄来完成。这些数字值就是文件描述符。最为人们所知的文件米描述符是 stdin, stdout 和 stderr,文件描述符的数字分别是0,1和2。这些数字和各自的设备是保留的。一个命令执行前,先会准备好全部输入输出,默认分别绑定(stdin,stdout,stderr),若是这个时候出现错误,命令将终止,不会执行。命令解析过程,能够参考:Linux Shell 通配符、元字符、转义符使用实例介绍
这些默认的输出,输入都是linux系统内定的,咱们在使用过程当中,有时候并不但愿执行结果输出到屏幕。我想输出到文件或其它设备。这个时候咱们就须要进行输出重定向了。
linux shell下经常使用输入输出操做符是:
1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ; /dev/stdin -> /proc/self/fd/0 0表明:/dev/stdin
2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ; /dev/stdout -> /proc/self/fd/1 1表明:/dev/stdout
3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ; /dev/stderr -> /proc/self/fd/2 2表明:/dev/stderr
格式:
command-line1 [1-n] > file或文件操做符或设备
上面命令意思是:将一条命令执行结果(标准输出,或者错误输出,原本都要打印到屏幕上面的) 重定向其它输出设备(文件,打开文件操做符,或打印机等等)1,2分别是标准输出,错误输出。
实例:
1234567891011121314151617181920212223242526272829303132333435363738 #显示当前目录文件 test.sh test1.sh test1.sh实际不存在[chengmo@centos5 shell]$ls test.sh test1.shls: test1.sh: 没有这个文件和目录test.sh#正确输出与错误输出都显示在屏幕了,如今须要把正确输出写入suc.txt# 1>能够省略,不写,默认所至标准输出[chengmo@centos5 shell]$ls test.sh test1.sh 1>suc.txtls: test1.sh: 没有这个文件和目录[chengmo@centos5 shell]$cat suc.txttest.sh#把错误输出,不输出到屏幕,输出到err.txt[chengmo@centos5 shell]$ls test.sh test1.sh 1>suc.txt 2>err.txt[chengmo@centos5 shell]$cat suc.txt err.txttest.shls: test1.sh: 没有这个文件和目录#继续追加把输出写入suc.txt err.txt “>>”追加操做符[chengmo@centos5 shell]$ls test.sh test1.sh 1>>suc.txt 2>>err.txt#将错误输出信息关闭掉[chengmo@centos5 shell]$ls test.sh test1.sh 2>&-test.sh[chengmo@centos5 shell]$ls test.sh test1.sh 2>/dev/nulltest.sh#&[n] 表明是已经存在的文件描述符,&1 表明输出 &2表明错误输出 &-表明关闭与它绑定的描述符#/dev/null 这个设备,是linux 中黑洞设备,什么信息只要输出给这个设备,都会给吃掉#关闭全部输出[chengmo@centos5 shell]$ls test.sh test1.sh 1>&- 2>&-#关闭 1 ,2 文件描述符[chengmo@centos5 shell]$ls test.sh test1.sh 2>/dev/null 1>/dev/null#将1,2 输出转发给/dev/null设备[chengmo@centos5 shell]$ ls test.sh test1.sh >/dev/null 2>&1#将错误输出2 绑定给 正确输出 1,而后将 正确输出 发送给 /dev/null设备 这种经常使用<p>[chengmo@centos5 shell]$ls test.sh test1.sh &>/dev/null#& 表明标准输出 ,错误输出 将全部标准输出与错误输出 输入到/dev/null文件</p>
注意:
一、shell遇到”>”操做符,会判断右边文件是否存在,若是存在就先删除,而且建立新文件。不存在直接建立。 不管左边命令执行是否成功。右边文件都会变为空。
二、“>>”操做符,判断右边文件,若是不存在,先建立。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1,2]而后,与左边的标准输出(1)或错误输出(2) 绑定。
三、当命令:执行完,绑定文件的描述符也自动失效。0,1,2又会空闲。
四、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,1,2文件描述符。
五、一条命令在执行前,先会检查输出是否正确,若是输出设备错误,将不会进行命令执行
格式:
command-line [n] <file或文件描述符&设备
将然有,命令默认从键盘得到的输入,改为从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定。将由它进行输入。
实例:
12345678910111213141516 [chengmo@centos5 shell]# cat > catfiletestingcat file test#这里按下 [ctrl]+d 离开#从标准输入【键盘】得到数据,而后输出给catfile文件[chengmo@centos5 shell]$cat>catfile <test.sh#cat 从test.sh 得到输入数据,而后输出给文件catfile[chengmo@centos5 shell]$cat>catfile <<eoftest afiletest!eof#<< 这个连续两个小符号, 他表明的是『结束的输入字符』的意思。
#这样当空行输入eof字符,输入自动结束,不用ctrl+D
格式:
exec 文件描述符[n] <或> file或文件描述符或设备
在上面讲的输入,输出重定向 将输入,输出绑定文件或设备后。只对当前那条指令是有效的。若是须要在绑定以后,接下来的全部命令都支持的话。就须要用exec命令
实例:
12345678910111213141516171819202122 [chengmo@centos5 shell]$exec 6>&1#将标准输出与fd 6绑定[chengmo@centos5 shell]$ls /proc/self/fd/0 1 2 3 6#出现文件描述符6[chengmo@centos5 shell]$exec 1>suc.txt#将接下来全部命令标准输出,绑定到suc.txt文件(输出到该文件)[chengmo@centos5 shell]$ls -al#执行命令,发现什么都不返回了,由于标准输出已经输出到suc.txt文件了[chengmo@centos5 shell]$exec 1>&6#恢复标准输出[chengmo@centos5 shell]$exec 6>&-#关闭fd 6描述符[chengmo@centos5 ~]$ls /proc/self/fd/0 1 2 3说明:使用前先将标准输入保存到文件描述符6,这里说明下,文件描述符默认会打开0,1,2 还可使用自定义描述符 。而后对标准输出绑定到文件,接下来全部输出都会发生到文件。 使用完后,恢复标准的输出,关闭打开文件描述符6。
【个人理解:&1表示输出符1的地址,因此“exec 6>&1”便是将6描述符重定向到1描述符的地址(标准输出地址),因而6的地址也就是系统中标准输出的地址;而后将1描述符重定向到文件:“exec 1>suc.txt”;以后又将1定向到6的地址:“exec 1>&6”;最后禁用6描述符,也就是删除6描述符的指向,这个指向以前被定义指到标准输出地址,这个地址是不变的,若是以前不利用6来接替1的指向,后面想1指回标准输出地址就很难办到了。】
有趣事情:
可能有朋友会这样用:exec 1>suc.txt ,接下来全部输出都绑定到suc.txt 文件,那么怎么样恢复原来的呢? 试试你就会发现问题所在……
1234567891011 exec 3<>test.sh;#打开test.sh可读写操做,与文件描述符3绑定while read line<&3doecho $line;done#循环读取文件描述符3(读取的是test.sh内容)exec 3>&-exec 3<&-#关闭文件的,输入,输出绑定
学习就要总结,总结才能够提升了。哈哈!
估计还有一些朋友是头晕晕的。怎么linux的重定向这么复杂呢,又是文件打开描述符又是读,还有些,还有默认标准输入输出。
其实,总结一下,重定向应用一般就如下两点:
一、从新设置命令的默认输入,输出,指向到本身文件(文件,文件描述符,设备其实都是文件,由于linux就是基于设备也是文件,描述符也指向是文件,哈哈)
二、扩展本身新的描述符,对文件进行读写操做