Io-Redirection

一個命令怎麼可能有多個輸出?

  • September 12, 2018

這個答案的最底部,吉爾斯提到一個命令可以有多個輸出或輸入。

是的,有cat foo bar | something, 用於同時具有foobar作為輸入,還有tee用於輸出;但這似乎並不是他所說的。

一個程序怎麼可能有多個輸入或輸出?

這個cat foo bar例子不是我的意思。這裡cat一次只有一個輸入和一個輸出。

tee是一個例子:它輸出到所有參數,同時加上它的標準輸出。使用與我之前的答案相同的 ASCII 藝術圖,這是tee foo bar它在終端中執行時的樣子。

  +------------------+    
  |       tee        |    
===|<stdin            |         +------------+
→  |                  |         |  terminal  |
  |           stdout>|=========|<input      |
  |                  |   → ##==|<           |
  |                  |     ||  +------------+
  |           stderr>|=====##
  |                  |   →
  |                  |       +-------------+
  |                3>|=======|> file "foo" |
  |                  |   →   +-------------+
  |                  |       +-------------+
  |                4>|=======|> file "bar" |
  |                  |   →   +-------------+
  |                  |    
  +------------------+    

在這個例子中,tee發送“有用的”輸出到三個通道:到終端(因為這是它的標準輸出連接到的地方),以及到兩個文件。此外,tee還有一個錯誤輸出通道。

一個程序通常具有三個輸入/輸出通道,由它們的文件描述符編號標識:

  • 標準輸入(簡稱stdin,文件描述符編號為0);
  • 標準輸出(簡稱stdout,文件描述符編號1);
  • 標準錯誤(簡稱stderr,文件描述符編號2)。

文件描述符 0、1 和 2 的用途只是一個約定問題——沒有任何東西強製程序不能嘗試寫入文件描述符 0 或從描述符 1 和 2 讀取——但這是一個幾乎普遍遵循的約定。

如果您從終端執行程序,文件描述符 0、1 和 2 開始連接到該終端,除非它們已被重定向。其他文件描述符開始關閉,如果程序打開其他文件將使用。

特別是,所有命令都有兩個輸出:標準輸出(對於命令的有效負載,“有用的”輸出)和標準錯誤(對於錯誤或資訊性消息)。

shell ( command1 | command2 | command3 | …) 中的管道將每個命令的標準輸出連接到下一個命令的標準輸入。所有命令的標準錯誤都會發送到終端(除非重定向)。

Shell 提供了重定向其他文件描述符的方法。您可能已經遇到2>&12>file重定向標準錯誤。請參閱 何時使用額外的文件描述符?以及它連結到的其他文章,以獲取其他文件描述符的操作範例。

功能豐富的 shell 還提供程序替換以將文件重定向推廣到管道命令,這樣您就不會局限於每個命令都有一個輸入和一個輸出的線性管道。

很少有命令會嘗試訪問大於 2 的文件描述符,除非它們打開了文件(打開文件會選擇一個空閒的文件描述符並將其編號返回給應用程序)。一個例子是 GnuPG,它希望讀取數據以對其標準輸入進行加密/解密/簽名/驗證,並將結果寫入標準輸出。--passphrase-fd可以告訴它使用該選項讀取不同文件描述符上的密碼。GnuPG 還具有報告其他文件描述符狀態數據的選項,因此您可以在 stdout 上輸出有效負載,在 stderr 上輸出錯誤消息,並在另一個文件描述符上顯示狀態資訊。這是一個將管道命令的輸出用作密碼的範例:

echo fjbeqsvfu | rot13 | gpg -d --passphrase-fd=3 3<&0 <file.encrypted >file.plaintext

引用自:https://unix.stackexchange.com/questions/96724