在我們設置定時任務的時候經常會使用標准輸出和標准錯誤輸出。這個在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
共勉之