【问题标题】:Why is the STDOUT line printed after the STDERR line?为什么在 STDERR 行之后打印 STDOUT 行?
【发布时间】:2013-06-27 00:32:52
【问题描述】:

我完全不理解这种行为。

我有一个非常简单的 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 捕获到文件中 命令我进入控制台?

【问题讨论】:

    标签: perl bash stdout stderr io-redirection


    【解决方案1】:

    这是缓冲的效果。当输出到终端时,Perl(就像 stdio 一样)使用基于行的缓冲,这将产生预期的效果。输出到文件时,它使用块缓冲(通常是 4k 或 8k 块),因此它只会在程序结束时刷新。

    您观察到的差异是因为 STDERR 是无缓冲的,与大多数其他句柄不同。

    规避此问题的最简单方法是在 STDOUT 上启用自动刷新,使用 $| 特殊变量。详情请见perlvar

    【讨论】:

    • +1。确切地。执行$|++ 会达到预期的效果。
    • 谢谢你,莱昂!您的回答完美地解释了问题以及解决方法。
    【解决方案2】:

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

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

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

    【讨论】:

    • 您确实意识到 autoflush 只是 $| 的包装器?此外,在 perl 的
    • 这里是包装器:{my$old=select STDOUT;$|=1;select$old} 如果您不选择旧文件句柄,任何没有显式文件句柄的打印都会转到它。因此,您应该始终将选择重置为之前的状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 2012-06-23
    • 2020-01-11
    相关资源
    最近更新 更多