是否可以得出 4 種類型的結論?流輸出如果我們不希望它們在執行命令後出現在 CLI 中,我們可以引用 Linux 中的檔案嗎?
對文件的可能引用:
- 所有流輸出
- 僅標準誤差
- 僅標準輸出(包括標準輸出的最終結果)。
- stdout 和 stderr(不包括 stdout 的最終結果)。
筆記:
數字 4 的一個例子可能是find / -type f -name php.ini 2>/dev/null
。據我了解,使用這個指令我們沒有得到標準誤差,也沒有標準輸出(除了標準輸出的最終結果在本例中,這是我們搜尋的文件(如果找到)。
答案1
有兩個輸出流連接到 Unix 系統上的每個進程:標準輸出(標準輸出,檔案描述符 1)和標準誤(stderr,檔案描述符 2)。這些可以彼此獨立地重定向。標準輸入使用檔案描述符 0。
- 若要將標準輸出重定向到文件
file
,請使用>file
或更明確的1>file
。替換file
為/dev/null
丟棄資料。 - 若要將標準錯誤重定向到文件
file
,請使用2>file
. - 若要將標準誤差重定向到標準輸出所在的位置,請使用
2>&1
. - 若要將標準輸出重定向到標準錯誤所在的位置,請使用
1>&2
.
不存在流或過程的“最終結果”概念。我想發送到標準輸出的任何內容都可以被視為進程的“結果”,除非它也將數據輸出到它自己打開的某個文件或具有其他副作用(例如從目錄中取消文件鏈接,在這種情況下)的rm
,或在 ) 的情況下處理多個網路連線sshd
。進程也返回退出狀態(零表示“成功”,非零表示“失敗”),可以將其視為該進程的“結果”,但這不一定與進程的輸出流相關。
流也可以重定向到附加模式,這意味著如果重定向到文件,則該文件最初不會被截斷,並且流上的任何資料都會附加到文件末尾。透過使用>>file
而不是來做到這一點>file
。
在問題的註釋中,命令
find / -type f -name php.ini 2>/dev/null
給出。這會重定向(丟棄)僅有的標準誤差。標準輸出流根本不重定向,因此在控制台或終端中完整可見。如果它是管道的中間部分,則標準輸出流將輸入到管道中下一個命令的標準輸入中。
總而言之,我想說有二(不是四個)輸出流。這些可以以各種方式獨立地重新導向,其中包括丟棄它們的內容。
答案2
每一個流程按照慣例,可以使用三個標準檔案描述符。這些檔案描述符可作為流使用:stdin
、stdout
和stderr
。
預設情況下,當您從 shell (CLI) 啟動進程時,第一個進程連接到終端(或終端模擬器,如 xterm)的輸入,另外兩個連接到終端的輸出。
您可以指示 shell 將它們重新導向到其他地方,例如/dev/null
(它們被吞噬的地方)。您可以獨立為stdout
和執行此操作stderr
。那麼對於這種情況,確實有四種可能:
command
command > /dev/null
command 2> /dev/null
command > /dev/null 2> /dev/null
但沒有什麼可以阻止您將其中一個或兩個重定向到其他地方:
command > /tmp/myout 2> /tmp/myerr
在這種情況下,您的終端也不會得到任何輸出,但您可以稍後在檔案/tmp/myout
和中讀取它/tmp/myerr
。
答案3
情況比你的問題所暗示的更簡單,也更複雜。來解釋一下什麼善行難陀說在他的回答,有兩個按慣例配置並用於輸出的標準(常規)I/O 流(文件描述符):stdout(文件描述符 1)和 stderr(文件描述符 2)。我們的規範問題, shell 的控制和重定向運算子是什麼?,討論如何重定向它們。天真地,我們可以列舉五種不同的組合:
╔══════════════════════════════╦═════════════════════════════════════════════╗
║ ║ stderr ║
║ ╟─────────────────────┬───────────────────────╢
║ ║ default │ ║
║ ║ (same as the shell) │ redirected ║
╠════════╤═════════════════════╬═════════════════════╦═══════════════════════╣
║ │ default ║ ║ ║
║ │ (same as the shell) ║ 1 ║ 2 ║
║ ├─────────────────────╠═════════════════════╬═══════════════════════╣
║ stdout │ ║ ║ 4. redirected ║
║ │ ║ ║ to the same file ║
║ │ redirected ║ 3 ╟───────────────────────╢
║ │ ║ ║ 5. redirected ║
║ │ ║ ║ to different files ║
╚════════╧═════════════════════╩═════════════════════╩═══════════════════════╝
但如果你算是/dev/null
與文件不同,追加模式作為一種特殊情況,讀寫模式與只寫模式不同,管道與文件不同,那麼組合的數量就會呈指數級增長。然而,正如反覆指出的,「stdout 的最終結果」不是標準的 Unix/Linux/bash 短語。
只有兩個?
其他答案(也許是明智的)將自己限制為 stdout 和 stderr (文件描述符 1 和 2)。我(魯莽地?)相信這個問題的完整答案應該解決其他文件描述符可用的事實 - 多達數百,數千,甚至超過一百萬。例如,如果執行類似 的命令diff file1 file2
,diff
程式將開啟file1
和file2
,核心可能會分配檔案描述符 3 和 4。以下位置討論了重定向大於 2 的檔案描述符:
- Bash 參考手冊:第 3.6 節重定向
- 進階 Bash 腳本指南:第 20 章 I/O 重定向
- 2>&-、2>/dev/null、|&、&>/dev/null 和 >/dev/null 2>&1 之間的區別(U&L問題)
- 除了通常的 stdin/stdout/stderr (0, 1, 2) 之外,我們還能有更多的檔案描述符嗎?(堆疊溢位問題)
例如,請參閱以下高檔案描述符範例:
$ 貓犬.c #include <stdio.h> #include <字串.h> 主要的() { int i,len; char msg[] = "你好,狗。\n"; len = strlen(msg); 我=寫(17,味精,長度); 如果 (i == len) printf("成功!i = %d = len\n", i); 否則如果 (i == -1) { printf("錯誤!i = %d (len = %d)\n", i, len); 錯誤(“”); } 別的 printf("意外結果:i = %d, len = %d\n", i, len); } $ 製作犬類 cc 犬.c -o 犬 $ ./犬類 錯誤!我 = -1 (len = 12) 錯誤的文件描述符 $ ./canine 17> 動物 成功!我 = 12 = 長度 $ ls -l 總計 70 -rw-r--r-- 1我的用戶名 我的群組名 2012年4月12日 13:36 動物 -rwxr-xr-x 1我的用戶名 我的群組名67067 4 月 12 日 13:36 犬 -rw-r--r-- 1我的用戶名 我的群組名 358 四月 12 日 13:36 犬.c $ 貓 動物 你好,狗。
警告:我不確定上述內容是否適用於所有 shell 的所有版本。
標準程式不會寫入大於 2 的檔案描述符(除非它們透過開啟檔案、建立網路連線或類似方式從核心取得該檔案描述符)。但是,如果您有一個(非標準)程序可以執行此操作,則可以重新導向這些檔案描述符。
而且,如果您只有 100 個檔案描述符,並且只考慮每個檔案描述符是否被重新導向,那麼您就有超過十億 (1,000,000,000,000,000,000,000,000,000,000) 種可能的組合。