在我们设置定时任务的时候经常会使用标准输出和标准错误输出。这个在Linux是一个非常重要的概念,而且这个很有用。程序应该有数据库的来源端、数据的目的端,以及报告问题的地方,它们被称为标准输入、标准输出以及标准错误输出。
程序启动的时候,默认情况下,标准输出、输入都会已经打开,且已准备好供其使用。我们使用Xshell连接并登陆上服务器的时候,默认下终端就是标准输入、输出端。可以试试cat命令。
$ cat #未指定任何的参数是,读取默认的标准输入、写入到默认的标准输出 建华是可以玩耍的小伙伴 #用户输入(此时终端默认是标准输入) 建华是可以玩耍的小伙伴 #程序将内容输出到标准输出(此时终端默认为标准输出) ^D #输入Ctrl-D 告诉程序文件结尾
重定向与管道
Shell提供了数种语法,可以修改默认的IO的来源端和目的端,就是标准输入和输出的地方。
< | 修改标准输入 | sort < ucid.txt | 默认下,标准输入为终端,此时可以更改为你想要的地方 |
<< | Command << delimiter | 从标准输入中读入,直到遇到delimiter分割符 | |
> | 修改标准输出 | ls -l > listinfo.txt | 默认下,标准输出为终端,此时可以修改默认输出的地方。譬如可以将标准输出的内容写在文件中。 如果文件已存在,会被覆盖掉。 |
>> | 输出附件到文件 | ls -l >> listinfo.txt | 与[>]不一样的是,[>]会清空原来的内容,而[>>]只是将标准输出追加到文件结尾处。 |
| | 建立管道 | program1 | program2 | 1. program1的标准输出为program2的标准输入; 2. 管道的执行效率比使用临时文件的程序起码高一个数量级; |
[<]例子
场景:对文件内容的信息进行排序
[nemo@name tool]$ cat show.txt 7291418 2233803 8031001 1258962 [weiyg@name tool]$ sort < show.txt 1258962 2233803 7291418 8031001
[>]例子
场景:打印内容到文件
[weiyg@name script]$ ll total 20 -rw-rw-r--. 1 weiyg weiyg 254 Dec 31 13:45 ssh.rb -rw-r--r--. 1 weiyg weiyg 476 Dec 30 11:48 sshx.rb -rw-rw-r--. 1 weiyg weiyg 12 Dec 26 16:57 test.rb [weiyg@name script]$ ls -l > listinfo.txt [weiyg@name script]$ cat listinfo.txt total 20 -rw-rw-r--. 1 weiyg weiyg 0 Jan 22 21:35 listinfo.txt -rw-rw-r--. 1 weiyg weiyg 254 Dec 31 13:45 ssh.rb -rw-r--r--. 1 weiyg weiyg 476 Dec 30 11:48 sshx.rb -rw-rw-r--. 1 weiyg weiyg 12 Dec 26 16:57 test.rb
在定时任务上面经常使用。因为定时任务执行的内容,不会打印到终端。如果需要查看结果的话就很麻烦。而打印到文件中的话,随时都可以查看了。不过这里往往用[>>]追加比较多。
[>>]例子
没啥好说的,跟[>]就是一个[>]会覆盖原有的文件,而[>>]只是追加。
[|]管道例子
场景:查询id为19217xxxx的玩家在1月15日使用道具的日志
[weiyg@name flash]$ bzcat *useprop.log.2014-01-15.bz2 |grep ‘19217xxxx‘ 1389717003317|19217xxxx|2|304|305|0| 1389717005097|19217xxxx|2|303|304|0|
这是查询游戏日志的一个例子。默认下,系统会将游戏5天前的日志进行打包压缩。而此时需要查询5天前的日志的话,使用上面的方法无论在效率上还是方便上,管道都有使用临时文件无法比拟的又是。当然使用下面的方法:
[weiyg@name flash]$ bzcat *useprop.log.2014-01-15.bz2 > tem.log [weiyg@name flash]$ grep ‘19217xxxx‘ tem.log 1389717003317|19217xxxx|2|304|305|0| 1389717005097|19217xxxx|2|303|304|0|
也可以达到相同的结果,但相比使用管道,一、需要使用临时文件,读写在磁盘需要时间;二、临时文件还需要手动删除,比较麻烦。
注:bzcat 可以直接显示压缩文件的内容
特殊文件:/dev/null
与/dev/tty
/dev/null 传送到此文件的数据都会被系统丢掉,,就是输出到一个空设备的意思。
/dev/tty 程序打开此文件时,Linux会自动将它重定向到一个终端。
文件描述符
在定时任务,我们经常在重定向的时候,喜欢这样操作。
33 1 * * * /home/weiyg/crontab/clear_logs.sh > /dev/null 2>&1
后面的 2>&1是什么意思呢,这里就要理解文件描述符和绑定重定向的概念了。
文件 | 文件描述符 |
输入文件——标准输入 | 0(默认为终端(网上有说默认为键盘的)) |
输出文件——标准输出 | 1(默认为终端) |
错误输出文件——标准错误 | 2(默认为终端) |
绑定重定向
Commond >&m | 标准输出重定向到文件描述符m中 |
Command <&- | 关闭标准输入 |
Command 0>&- | 关闭标准输出 |
此时我们再去理解[2>&1],就容易多了。[2]是标准错误的文件描述符,而[>&1]的意思重定向到标准输出。那么定时任务的解释就是,将[clear_logs.sh]执行的标准输出和标准错误重定向到[/dev/null](就是丢掉输出的内容)。
我是这样理解(不一定正确)上面的定时任务的(分2部分):
clear_logs.sh > /dev/null #将clear_logs.sh执行的标准输出输出到/dev/null clear_logs.sh 2> /dev/null #将clear_logs.sh执行的标准错误输出到/dev/null,只是clear_logs.sh不是执行了2次,只是1次。这里的&1代表的就是/dev/null
//-----------------------
以上为本次学习I/O重定向的笔记。
参考资料:1. 《Shell脚本学习指南》 Arnold Robbins & Nelson H.F.
Beebe著 机械工业出版社
2.
《Linux shell的标准输入、输出和错误 》
http://blog.csdn.net/cjfeii/article/details/10084343
共勉之