編輯

編輯

編輯

請不僅查看已接受的答案,還請查看其他答案。

問題

為什麼將 STDOUT 和 STDERR 重定向到同一檔案不起作用,儘管它看起來與 1>[FILENAME] 2>&1 相同?

這是一個例子:

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>a.txt
cat a.txt
# outputs '1' only.

嗯,為什麼?我認為這是有效的,因為... STDOUT 被重定向到 a.txt,STDERR 也是如此。 STDERR 發生了什麼事?

答案1

您的兩個重定向都會截斷文件,因此第二個(按執行時間順序)將覆蓋第一個。嘗試

rm a.txt ; touch a.txt ; perl -e 'print "1\n" ; warn "2\n";' 1>>a.txt 2>>a.txt

或只是使用相同的檔案描述符

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>&1

答案2

對於1>a.txt 2>&1,檔案描述符 #1 是重複的到#2。它們都引用相同的“開啟檔案”,並且共享當前位置和讀取/寫入模式。 (實際上使用 2>&1 和 2<&1 之間沒有任何區別。)

對於1>a.txt 2>a.txt,兩個檔案描述符都是獨立開設並具有單獨的遊標位置。 (該檔案也會被截斷兩次。)如果您向fd #1 寫入“Hello”,其位置將提前到位元組5,但fd #2 仍保留在位元組0。覆蓋從0 開始的資料。

很容易看出第二次寫入是否更短:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>a.txt

$ cat a.txt 
123defg

請注意,Perl 具有內部緩衝,因此在本例中需要明確的flush() 來確保fd #1 資料在fd #2 資料之前寫入。否則,流在退出時將以不可預測的順序刷新。

為了進行比較,如果檔案描述子是共享的,則寫入會相互跟隨:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>&1

$ cat a.txt 
abcdefg
123

相關內容