【问题标题】:Perl: STDOUT reopened as FH only for inputPerl:STDOUT 重新打开为 FH 仅用于输入
【发布时间】:2017-08-20 19:35:16
【问题描述】:

我收到以下错误消息(使用 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 无关的东西。

代码做正确的事。唯一的问题是不应记录此错误消息。

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

【问题讨论】:

  • 这些是自定义模块吗?是什么决定了是否应该记录错误?
  • 这些是我们与标准模板工具包一起使用的自定义模块。根据我老板的要求,不应该记录错误
  • 好的。我的意思是,什么代码记录了错误?必须有一些东西可以记录错误。是在模板工具包(我不使用它)中设置的,还是由您的模块设置的? (一种方法是使用__WARN__ 钩子,但希望有更清洁的方法)
  • @zdim 该错误由 Template Toolkit 发行版中的一个模块记录,该模块在我们的一个自定义模块中打开一个位于 close(STDOUT); 之后的文件。是的,错误是由模板工具包记录的,而不是由我们的自定义模块记录的。我的问题是如何使模板工具包不记录错误
  • 您不应该关闭 STDOUT。将其重新打开到 /dev/null

标签: perl logging warnings


【解决方案1】:

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

或在重新打开之前先复制它(使用dup2),以便稍后恢复

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

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

警告的出现是因为始终使用最低的未使用文件描述符,并且这里 fd 1 通过关闭 STDOUT 被腾出;但它试图用于输入不正确的内容。至于为什么不正常以及为什么发出警告,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 及其指向其他帖子和相关文档的链接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多