1. 程式人生 > >linux 關於標準輸入輸出錯誤 STDIN STDOUT STDEER

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


以下是相關討論的地址: