Perl STDOUT 重定向到管道,调用 sleep() 后没有输出

标签 perl pipe stdout sleep tee

在将脚本 STDOUT 重定向到管道并使用 sleep() 时,Windows 上的 Perl(ActivePerl 和 Strawberry)出现问题。试试这个:

perl -e "for (;;) { print 'Printing line ', $i++, \"\n\"; sleep(1); }"

这按预期工作。现在将其通过管道传输到 Tee(或某些文件,结果相同):

perl -e "for (;;) { print 'Printing line ', $i++, \"\n\"; sleep(1); }" | tee

根本没有输出,tee 没有捕捉到任何东西。然而,perl 脚本仍在运行,只是在脚本完成之前 STDOUT 上没有任何内容,然后所有输出都被转储到 tee。除非,如果 STDOUT 缓冲区已满,脚本可能会挂起。

现在,如果您删除 sleep(call),管道将按预期工作!怎么回事?

我找到了解决方法;使用 $|=1 禁用 STDOUT 缓冲会使管道在使用 sleep 时工作,但是......为什么?谁能解释并提供更好的解决方案?

最佳答案

您正在遭受缓冲。添加 $| = 1; 取消缓冲 STDOUT。

除了 STDERR 之外的所有文件句柄都默认缓冲,但 STDOUT 在连接到终端时使用最小形式的缓冲(由换行符刷新)。通过用管道替换终端,可以恢复正常的缓冲。

移除 sleep 调用除了加快速度之外没有任何改变。不需要花费几分钟来填满缓冲区,而是需要几毫秒。不管有没有它,输出仍然以 4k 或 8k block 的形式写入(取决于您的 Perl 版本)。

关于Perl STDOUT 重定向到管道,调用 sleep() 后没有输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21681505/

相关文章:

c - 如何动态创建 Unix 管道?

c - 用管道模拟 linux 命令不起作用

bash - 使用 grep 在不同的行上搜索多个关键字

node.js - child_process.spawn 标准输出成 block 出现

apache - Apache mod_perl 中的 Mojolicious

linux - Perl 中不区分大小写的 GREP

perl - 帮助 perl 中的正则表达式

linux - 八个字符的模式识别

c++ - 如何从 MFC 程序写入标准输出?

C++ ReadFile、CreateProcess、管道标准输出重定向、双倍输出