在我們接觸的 shell 指令碼中,對 2>&1
一定不陌生,比如 ls foo > /dev/null 2>&1
。
本文就來解釋下 2>&1
究竟做了什麼,並且是如何起作用的。
一、I/O 重定向簡介
「重定向」是計算機用來把命令的輸出從一個地方,輸出到另一個地方。舉個例子,預設情況下,我們使用 cat
指令可以把一個檔案的內容列印到終端:
$ cat foo.txt
foo
bar
baz
但是,我們可以把輸出重定向到另外地方。此例中,我們可以把輸出重定向到 output.txt
中:
$ cat foo.txt > output.txt
$ cat output.txt
foo
bar
baz
注意,在執行第一行命令 cat foo.txt > output.txt
時,我們在螢幕上看不到任何輸出。我們把原來應該列印到螢幕的內容,重定向到 output.txt
了,所以螢幕上不會有任何輸出了。
這裡,「本來應該列印到螢幕的內容」,就是標準輸出,即 stdout(standard output)。
除了標準輸出可以接收程式的輸出之外,還有一個地方可以,叫 標準錯誤輸出,即 stderr(standard error)。stderr 用來接收程式的錯誤訊息。例如,我們 cat
了一個不存在的檔案:
$ cat nop.txt > output.txt
cat: nop.txt: No such file or directory
我們看到,雖然我們要求程式把輸出重定向到 output.txt
,但是我們還是在螢幕上看到了錯誤訊息輸出。這是因為我們只是重定向了 standard output,而不是 standard error。
二、檔案描述符(fd)簡介
檔案描述符(file descriptor)簡單來說,就是一個正整數,用來代表一個開啟的檔案。比如當前我們有 100 各開啟的檔案,那麼就有 100 個檔案描述符。
唯一需要補充的是,在 Unix 系統中,「一切皆檔案」。
同時我們還應該知道,對於標準輸出(stdout)和標準錯誤輸出(stderr),也有對應的檔案描述符。我們使用 1 和 2 來分別表示 stdout 和 stderr 所在的位置。
三、融合上述知識
回到我們的第一個示例,我們還可以有另外一種寫法
# 寫法一
$ cat foo.txt > output.txt
# 等價寫法二
$ cat foo.txt 1> output.txt
這裡的 1 就是用來代表 stdout 的檔案描述符。語法是 [FILE_DESCRIPTOR]>
。我們看到把 1 省略的寫法 >
只是 1>
的快捷寫法而已。
對於重定向到 stderr 的場景,我們只需要在右邊的檔案前面加上檔案描述符即可
$ cat nop.txt 2> error.txt
$ cat error.txt
cat: nop.txt: No such file or directory
你看,這樣就生效了。這會兒,你大概知道 2>&1
是怎樣工作的,讓我們來總結總結。
我們使用 &1
來表示檔案描述符1(stdout)的地址。當你使用 2>&1
時,其實就是在說:把 stderr 的輸出重定向到 stdout 的地方。這樣,我們就可以把程式的標準輸出和錯誤輸出都輸出到同一個地方了。
$ cat foo.txt > output.txt 2>&1
$ cat output.txt
foo
bar
baz
$ cat nop.txt > output.txt 2>&1
$ cat output.txt
cat: nop.txt: No such file or directory
四、總結
- 程式可以把輸出傳送到兩個地方:標準輸出(stdout,standard output)和標準錯誤輸出(stderr,standard error)。
- 你可以把輸出重定向到另一個地方(比如檔案)
- 檔案描述符1和2 可以分別用來表示 stdout 和 stderr
command > output
是command 1> output
的縮寫- 可以使用
&[FILE_DESCRIPTOR]
來引用檔案描述符的值(或者叫指向檔案描述符的地址) - 使用
2>&1
來重定向 stderr 的輸出至 stdout 的地方(你可以用1>&2
來進行反向操作)
本作品採用《CC 協議》,轉載必須註明作者和本文連結