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;
}

这不会按预期执行(每次读取 1M 缓冲区时写入一行)。我最终看到了第一行(空白值为 $xferred),然后什么都没有,直到第 7 行和第 8 行(在 8MB 传输中)所有内容都刷新。我已经为此绞尽脑汁了几个小时 - 我已经阅读了 perldocs,我已经阅读了经典的“Suffering from Buffering”文章,我已经尝试了从 select 和 $|++ 到 IO::Handle 到 binmode( STDERR, "::unix") 给它命名。我还尝试使用 IO::Handle (TARGET->flush) 用每一行刷新 TARGET。没有骰子。

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

FWIW,无论我是输出到 STDERR 还是 STDOUT,问题都完全相同。

最佳答案

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

这意味着它通过 libc 并且可能使用比你的更大的内部缓冲区;即,它获取所有要接收的数据,然后以 1MB 的增量快速将其扔给您。

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

关于Perl - 无法刷新 STDOUT 或 STDERR,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17280713/

10-16 05:00