2013-06-29 38 views
4

我完全不理解這種行爲。爲什麼在STDERR行之後打印STDOUT行?

我有一個非常簡單的Perl腳本:

#!/usr/bin/perl 

use strict; 
use warnings; 

print "line 1\n"; 
print STDERR "line 2\n"; 

如果我從控制檯運行它,我會得到我的期望:

$ perl a.pl 
line 1 
line 2 

但是,如果我把它重定向到文件,我會得到在相反的順序線︰

$ perl a.pl &> a 
$ cat a 
line 2 
line 1 

如何捕獲所有輸出STDOUT + STDERR到相同的文件 命令我進入控制檯?

回答

10

這是緩衝的效果。當輸出到終端時,Perl(就像stdio一樣)使用基於行的緩衝,這會產生預期的效果。輸出到文件時,它使用塊緩衝(通常爲4k或8k塊),因此它只會在程序結束時刷新。

您正在觀察的差異是因爲STDERR是無緩衝的,與大多數其他手柄不同。

解決此問題的最簡單方法是使用$|特殊變量在STDOUT上啓用自動填充。有關更多詳細信息,請參見perlvar

+0

+1。究竟。做'$ | ++'會達到理想的結果。 – devnull

+0

謝謝,Leon!您的回答完美地解釋了問題以及如何解決問題。 – bessarabov

0

不要使用$ |,而是使用autoflush。

STDOUT->autoflush(1); 
STDERR->autoflush(1); 

http://perldoc.perl.org/IO/Handle.html

+0

你知道autoflush只是'$ |'的包裝嗎?另外,在perl的<5.14上,你必須首先加載FileHandle/IO :: Handle。 –

+0

這裏是封裝:'{my $ old = select STDOUT; $ | = 1; select $ old}'如果你沒有選擇舊的文件句柄,那麼沒有顯式文件句柄的任何打印都會去它。所以,你應該總是將選擇重置爲之前的狀態。 – shawnhcorey

相關問題