在Linux下,當一個用戶進程被創建的時候,系統會自動為該進程創建三個數據流,也就是題目中所提到的這三個。
1.三個數據流默認是表現在用戶終端上的
執行一個shell命令行時通常會自動打開三個標准文件:
- 標准輸入文件(stdin),通常對應終端的鍵盤;
- 標准輸出文件(stdout)和標准錯誤輸出文件(stderr),這兩個文件都對應終端的屏幕。
進程將從標准輸入文件中得到輸入數據,將正常輸出數據輸出到標准輸出文件,而將錯誤信息送到標准錯誤文件中。
如下例所示,cat命令的功能是從命令行給出的文件中讀取數據,並將這些數據直接送到標准輸出。
//cat命令行含參數:把文件config的內容依次顯示到屏幕上 [root@localhost ~]# cat config //cat命令行沒有參數:會從標准輸入中讀取數據,並將其送到標准輸出。 #用戶輸入的每一行都立刻被cat命令輸出到屏幕上,直到按Ctrl+d結束【標准輸入接收到EOF(結束)標識符】 [root@localhost ~]# cat Hello world Hello world Bye Bye
2.三個數據流可以重定向到文件中
(1)輸入重定向
輸入重定向是指把命令(或可執行程序)的標准輸入重定向到指定的文件中。也就是說,輸入可以不來自鍵盤,而來自一個指定的文件。
使用“ < ”符號將標准輸入重定向到文件中
如下例所示,wc將返回該文件所包含的行數、單詞數和字符數。
//把wc命令的輸入重定向為/etc/passwd文件
[root@localhost ~]# wc < /etc/passwd 24 30 1061
(2)輸出重定向
輸出重定向是指把命令(或可執行程序)的標准輸出或標准錯誤輸出重新定向到指定文件中。這樣,該命令的輸出就不顯示在屏幕上,而是寫入到指定文件中。
使用 “ > ”符號,將標准輸出重定向到文件中。形式為:命令>文件名
使用“ >> ”符號,將標准輸出結果追加到指定文件后面。形式為:命令>>文件名
使用“ 2> ”符號,將標准錯誤輸出重定向到文件中。形式為:命令 2> 文件名
使用“ 2>> ”符號,將標准錯誤輸出追加到指定文件后面。形式為:命令 2>>文件名
使用“ 2>&1 ”符號或“ &> ”符號,將把標准錯誤輸出stderr重定向到標准輸出stdout
使用“ >/dev/null ”符號,將命令執行結果重定向到空設備中,也就是不顯示任何信息。
[root@localhost ~]# ls > directory.out [root@localhost ~]# ls *.doc>>directory.out [root@localhost ~]# ls /usr/tmp 2> err.file //可在屏幕上看到程序的正常輸出結果,但又將程序的任何錯誤信息送到文件err.file中,以備將來檢查用 [root@localhost ~]# ls /usr/tmp &> output.file [root@localhost ~]# ls /usr/tmp 2>&1 output.file [root@localhost ~]# ls >/dev/null
(3)幾個基本符號及其含義
- /dev/null 表示空設備文件
- 0 表示stdin標准輸入
- 1 表示stdout標准輸出
- 2 表示stderr標准錯誤
stdin,stdout和stderr還是和終端有密切關系,通常在生產環境時,會將這3個流重定向到其它文件。比如編寫守護進程的時候,因為守護進程和終端無關,所以往往會將stdin,stdout和stderr重定向到/dev/null去。
3.stdout和stderr區別
我們知道,標准輸出和標准錯誤默認都是將信息輸出到終端上,那么他們有什么區別呢?讓我們來看個題目:
問題:下面程序的輸出是什么?(intel筆試2011)
int main(){ fprintf(stdout,"Hello "); fprintf(stderr,"World!"); return0; }
解答:這段代碼的輸出是什么呢?你可以快速的將代碼敲入你電腦上(當然,拷貝更快),然后發現輸出是
World!Hello
原理:在默認情況下,stdout是行緩沖的,他的輸出會放在一個buffer里面,只有到換行的時候,才會輸出到屏幕。
而stderr是無緩沖的,會直接輸出,舉例來說就是printf(stdout, "xxxx") 和 printf(stdout, "xxxx\n"),前者會憋住,直到遇到新行才會一起輸出。而printf(stderr, "xxxxx"),不管有么有\n,都輸出。
參考文檔:
