Bash為什麼
為什麼 command 1>file.txt 2>file.txt
的行為與 command 1>file.txt 2>&1
不同?
如果要將 stdout 和 stderr 都重定向到同一個文件,可以使用
command 1>file.txt 2>&1
, 或command &>file.txt
. 但是為什麼command 1>file.txt 2>file.txt
與上述兩個命令的行為不同呢?以下是驗證命令。
$ cat redirect.sh #!/bin/bash { echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file.txt 2>&1 { echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file1.txt 2>file1.txt { echo -e "error" 1>&2 && echo -e "output\noutput"; } 1>file2.txt 2>file2.txt { echo -e "output" && echo -e "error\nerror" 1>&2; } 1>file3.txt 2>file3.txt { echo -e "error\nerror" 1>&2 && echo -e "output"; } 1>file4.txt 2>file4.txt $ ./redirect.sh $ echo "---file.txt---"; cat file.txt;\ echo "---file1.txt---"; cat file1.txt; \ echo "---file2.txt---"; cat file2.txt; \ echo "---file3.txt---"; cat file3.txt; \ echo "---file4.txt----"; cat file4.txt; ---file.txt--- output output error ---file1.txt--- error output ---file2.txt--- output output ---file3.txt--- error error ---file4.txt---- output rror
就結果而言,看起來第二個回顯字元串在您執行時會覆蓋第一個回顯字元串
command 1>file.txt 2>file.txt
,但我不知道為什麼會這樣。(在某處有參考嗎?)
你需要知道兩件事:
- 程序的應用程序模式端已知的打開文件描述符引用稱為文件描述的內部核心對象,它是打開文件的實例。每個文件可以有多個文件描述,並且多個文件描述符共享一個文件描述。
- 目前文件位置是**文件描述的一個屬性。因此,如果多個文件描述符映射到一個文件描述,它們都共享相同的目前文件位置,並且使用一個這樣的文件描述符對文件位置的更改會影響所有其他這樣的文件描述符。此類更改由呼叫
read()
/readv()
、write()
/writev()
、lseek()
和類似系統呼叫的程序執行。該echo
命令呼叫write()
/writev()
當然。所以會發生這樣的事情:
command 1>file.txt 2>&1
只創建一個文件描述,因為 shell 只打開一個文件一次。Shell 使標準輸出和標準錯誤文件描述符都映射到該單個文件描述。它將標準輸出複製到標準錯誤上。因此,通過任一文件描述符的寫入將移動共享的目前文件位置:每次寫入都在前一次寫入公共文件描述之後。正如您所看到的,echo
命令的結果不會相互覆蓋。command 1>file.txt 2>file.txt
創建兩個文件描述,因為 shell 打開同一個文件兩次,以響應兩個顯式重定向。標準輸出和標準錯誤文件描述符映射到兩個不同的文件描述,然後又映射到同一個文件。這兩個文件描述具有完全獨立的目前文件位置,並且每次寫入都會立即執行同一文件描述上的前一次寫入。正如您所看到的,結果是通過一個寫入的內容可以覆蓋通過另一個寫入的內容,根據您執行寫入的順序以各種不同的方式。進一步閱讀