2011年8月20日

標準輸出入與重新導向

在Unix(Linux)當中,系統將標準輸入輸出分成三個:標準輸入(stdin)、標準輸出(stdout)、以及標準錯誤輸出(stderr),它們的fd (file descriptor, 檔案描述子) 分別是 0,1,2。在標準情形下,這些FD與以下設備關聯:

  • stdin(0): keyboard 
  • stdout(1): monitor 
  • stderr(2): monitor 

而在shell當中「>」的意思其實是,將「>」左邊輸出的東西重新導向到右邊去。當「>」左邊未指定任何東西時,它會讀取左方程式的標準輸出(也就是fd=1)重新導向給右邊的東西,但是也可以指定要重新導向的fd (也就是說「>abc.txt」會等於「1>abc.txt」)。所以可以想見 2>&1 的意思應該是把 fd=2,也就是標準錯誤輸出重新導向給&1。而這邊的 &1 指的其實就是 fd=1。因此以下的結果:
/tmp/test.sh > test.log
如果不使用2>&1的方法,則test.log中只會儲存test.sh的執行結果,而test.sh的錯誤只會顯示在營幕中,反之,若使用了2>&1方法,則執行結果與錯誤訊息都會存在test.log當中。所以由此可知,如果只想儲存錯誤訊息,可用 2> file的方式。

小結一下,2>&1就是將標準錯誤併到標準輸出一起輸出,而1>&2就是將標準輸出併到標準錯誤當中一起輸出。

在crontab中常常見到以下的寫法:
renice -20 cat /home/yoursrcdspath/srcds.pid >/dev/null 2>&1

/dev/null是 Unix 底下的垃圾筒+黑洞。它不帶任何意義,所有丟進去的東西都會被吃掉然後不見,反正你不想看到的東西丟給 null 就對了。
根據「man bash」裡 REDIRECTION 段落裡的說明,重新導向的順序是由左至右。也就是說「>/dev/null 2>&1」會先處理「>/dev/null」再處理「2>&1」。所以其意思就是將標準輸出和標準錯誤全部都丟到/dev/null中,眼不見為淨。