2013-06-24 21 views
3

Perl 5.14从股票Ubuntu Precise回购。尝试写一个简单的包装并监控对复制从一个流至另一个的进展:Perl - 无法刷新STDOUT或STDERR

use IO::Handle; 
while ($bufsize = read (SOURCE, $buffer, 1048576)) { 
    STDERR->printflush ("Transferred $xferred of $sendsize bytes\n"); 
    $xferred += $bufsize; 
    print TARGET $buffer; 
} 

如预期(写入每个1M缓冲器被读出时间的线)这不执行。我最终看到第一行(空白值为$ xferred),然后什么都没有,直到第7行和第8行(在8MB传输)上刷新。几个小时一直在我的脑海里 - 我读过perldocs,我读过经典的“饱受缓冲”的文章,我试过从select和$ | ++到IO :: Handle到binmode( STDERR,“:: unix”)给你命名。我也尝试使用IO :: Handle(TARGET-> flush)对每行进行TARGET冲洗。没有骰子。

有没有人遇到过这个?我没有任何想法。睡一秒钟“修复”了问题,但显然我不想在每次读取缓冲区时都要睡一会儿,这样我的进度就会在屏幕上输出!

FWIW,无论我输出到STDERR还是STDOUT,问题都是一样的。

+2

最初分配给STDERR的句柄开始自动刷新,所以如果你不弄乱它,只需要一个普通的'print'即可。 – ikegami

+0

@ikegami - 对不起,我打字的时候错过了。我确实看到所有传输8MB的8行(如图所示以1MB块缓存),但在传输结束时它们全部出现。问题编辑得当。 –

+0

@ikegami - 一个正常的打印没有做;我开始使用普通打印,并给了我缓冲的行为,然后我尝试设置$ |,然后我尝试使用IO :: Handle的自动刷新和刷新方法,然后尝试使用syswrite而不是打印,然后尝试如上所示的printflush 。没有什么会改变行为,包括使用STDOUT而不是STDERR - 我得到输出的第一行,然后在传输过程中长时间停顿,然后在传输结束时全部8行同时刷新。 –

回答

5

Perl read调用fread(3)而不是read(2)

这意味着它通过libc可能是使用比你更大的内部缓冲区;即它将获得所有要接收的数据,然后以1MB为增量快速向您发送数据。

如果这个猜想是正确的,可能是的解决方案中使用sysread,这就要求read(2),而不是read

+0

你绝对正确。问题不是STDERR没有冲洗,问题是我的INPUT没有冲洗到常规处理它,尽管在读取调用中规定了缓冲区大小! –