Perl:STDOUT仅作为输入重新打开为FH

时间:2017-08-20 19:35:17

标签: perl logging warnings

我有以下错误消息(使用Perl 5):

Tools.pm: Filehandle STDOUT reopened as FH only for input at /usr/local/lib/perl5/site_perl/mach/5.20/Template/Provider.pm line 967.

我理解它的原因:STDOUT被关闭,后来同样的FD被用于与STDOUT无关的东西。

代码做对了。唯一的问题是不应该记录此错误消息。

如何停止将此错误消息打印到我们的日志文件中?

1 个答案:

答案 0 :(得分:2)

Template::Manual::Config::ERROR概述了错误的详细处理。

可以通过指定异常类型的模板

在构造函数中对其进行分类
my $template = Template->new({  
     ERRORS => {
         user     => 'user/index.html',
         dbi      => 'error/database',
         default  => 'error/default',
     },
});

可以使用THROW指令

引发
  

[%THROW user.login'没有用户ID:请登录'%]

或致电throw方法

$context->throw('user.passwd', 'Incorrect Password');  
$context->throw('Incorrect Password');    # type 'undef'

或Perl代码通过调用die,可能使用Template::Exception对象。

如何使用它来解决问题是一个细节问题,其中没有提供。

但是你真的想找到(用户)触发这个并清理它的代码。例如,如评论中ikegami所述,请勿关闭STDOUT,而是重新打开/dev/null。 (我会说,从不简单地关闭标准流。)例如,如果您不想再看到STDOUT

open STDOUT, '>', '/dev/null';

或者在重新打开之前先保存它,以便以后可以恢复

open my $SAVEOUT, '>&', 'STDOUT';
open STDOUT, '>', '/dev/null';
...
open STDOUT, '>', $SAVEOUT;  # restore STDOUT
close $SAVEOUT;              # if unneeded

(请参阅open),或者如果可行,请创建local *FOO并使用它来保存STDOUT

由于总是使用最低的未使用文件描述符,因此发出警告,并且通过关闭STDOUT来释放fd 1;但它试图用于输入不正常的东西。至于为什么它不正常以及为什么发出警告,this threadold bug report是有用的。这超出了Perl。

一种通用的方法是使用__WARN__ hook

BEGIN {
    $SIG{__WARN__} = sub {
        warn @_ 
            unless $_[0] ~= /Filehandle STDOUT reopened as FH only for input/
    }
};

除非与您要抑制的警告匹配,否则会发出警告。 这个BEGIN块需要在预期影响的模块的use语句之前。如果您知道需要的范围,最好将其本地化,local $SIG{__WARN__} = sub {...};

有关详细信息,请参阅this post及其链接,其他帖子和相关文档。