Perl - 无法刷新STDOUT或STDERR

Jim*_*ter 3 perl

Perl 5.14现货Ubuntu Precise回购.尝试编写一个简单的包装器来监视从一个流复制到另一个流的进度:

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

这不会按预期执行(每次读取1M缓冲区时写一行).我最终看到了第一行(空白值为$ xferred),然后在第7行和第8行(8MB传输)上的所有内容都没有任何内容.几个小时以来我的脑子都在敲打 - 我读过perldocs,我读过经典的"遭受缓冲"的文章,我尝试了从select和$ | ++到IO :: Handle到binmode的所有内容( STDERR,":: unix")给你起名.我也尝试使用IO :: Handle(TARGET-> flush)在每一行中刷新TARGET.没有骰子.

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

FWIW,无论我输出到STDERR还是STDOUT,问题都完全一样.

sds*_*sds 5

Perl read打电话fread(3),不是read(2).

这意味着它通过libc并且可能正在使用比您大的内部缓冲区; 即,它获取所有要接收的数据,然后以1MB的增量快速向您发送数据.

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