linux 關於標準輸入輸出錯誤 STDIN STDOUT STDEER
入門:
stdout, stdin, stderr的中文名字分別是標準輸出,標準輸入和標準錯誤。
在Linux下,當一個使用者程序被建立的時候,系統會自動為該程序建立三個資料流,也就是題目中所提到的這三個。那麼什麼是資料流呢(stream)?我們知道,一個程式要執行,需要有輸入、輸出,如果出錯,還要能表現出自身的錯誤。這是就要從某個地方讀入資料、將資料輸出到某個地方,這就夠成了資料流。
因此,一個程序初期所擁有的這麼三個資料流,就分別是標準輸出、標準輸入和標準錯誤,分別用stdout, stdin, stderr來表示。對於這三個資料流來說,預設是表現在使用者終端上的,比如我們在c中使用fprintf:
fprintf(stdout, "hello world!\n");
螢幕上將打印出"hello world!"來,同樣,我們使用:
上面的程式碼會接收使用者輸入在終端裡的字元,並存在ptr中。
fread(ptr, 1, 10, stdin);
那麼標準輸入輸出和錯誤是不是隻能反應在終端裡呢?答案是不是的!我們可以將標準輸入和輸出重定位到檔案中:
例如,我們使用ls命令,會把當前目錄下的檔名輸出到終端上:
$lsgcc gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2 linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34 mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
我們可以使用 “ > ”符號,將ls的標準輸出重定向到檔案中:
$ls > lsout //將標準輸出重定向為檔案lsout$more lsout //顯示lsout檔案裡的內容gcc gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2 linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34 mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
同樣,我們也可以使用“ < ”符號將標準輸入重定向到檔案中,以sort為例,以下示例使用 sort 命令對由鍵盤鍵入的文字進行排序。鍵入ctrl-D 結束標準輸入。終端螢幕顯示的標準輸出如下:
$sortmuffyhappybumpyCTRL-D // 結束標準輸入。 bumpyhappymuffy //結束標準輸出。
使用" < "重定向後為:
$ more socks 顯示 socks 的內容。polka dotargyleplaid $ sort < socks 將輸入重定向為從 socks 輸入,並將內容排序。argyleplaidpolka dot
進階:
#man bash 裡面有一段有關重定向的描述:
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard
error was duplicated as standard output before the standard output was
redirected to dirlist.
輾轉各個社群,終於算是略微明白了一點。
上面第一條命令:#ls >dirlist 2>&1
把標準輸出(STDOUT,1)和標準錯誤(STDERR,2)都重定向到檔案 dirlist 的過程如下:
0 命令執行前
(此時:STDOUT指向終端、STDERR 也指向終端)
1 建立名為 dirlist 的空檔案
2 執行 > dirlist
(因為 > 預設為重定向 STDOUT ,即該步驟將 STDOUT 重定向為 檔案dirlist)
(此時:STDOUT指向 檔案dirlist、STDERR 指向終端)
3執行 2>&1 ,簡單的說,就是 STDERR 變得和 STDOUT 一樣。換句話說,就是把 STDERR 重定向為 “STDOUT 所指向的東西”
(因為之前 STDOUT 已經指向了 檔案dirlist,所以執行到該步驟時,STDERR 也重定向到了 檔案dirlist)
(此時:STDOUT指向 檔案dirlist、STDERR 也指向 檔案dirlist)
4 執行 ls,則由於執行 ls 所產生的標準輸出和標準錯誤資訊都被輸出到了 檔案dirlist 裡面。
上面的第二條命令:#ls 2>&1 > dirlist
僅僅把標準輸出重定向到了 檔案dirlist中(標準錯誤依然是終端)
我們依然一步一步走,看看為什麼:
0 命令執行前
(此時:STDOUT指向終端、STDERR 也指向終端)
1 建立名為 dirlist 的空檔案
2 執行 2>&1
(因為原來 STDOUT 和 STDERR 都指向終端,所以相當於,把 STDERR 從終端,重定向為終端……)
(此時:STDOUT指向終端、STDERR 也依然指向終端)
3 執行 > dirlist,把 STDOUT 重定向為 檔案dirlist
(此時:STDOUT指向 檔案dirlist、STDERR 依然指向終端)
4 執行 ls,那麼,產生的 STDOUT 輸出到了 檔案dirlist裡面,而 STDERR 輸出到了終端
另外,要將 STDOUT 和 STDERR 都輸出到檔案,也可以這麼寫:
#ls &> dirlist
這樣還比較方便一點。
關於 2>&1位置的問題:
$ cat cities > cities.copy 2>&1
...writes both stderr andstdout tocities.copy
be careful about this:
$ cat cities 2>&1 > cities.copy
...writes stderr to/dev/tty andstdout tocities.copy
以下是相關討論的地址: