Perl:STDOUT 重新打开为 FH 仅用于输入
Perl: STDOUT reopened as FH only for input
我收到以下错误消息(使用 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无关的事情。
代码做正确的事。唯一的问题是不应记录此错误消息。
如何停止将此错误消息打印到我们的日志文件中?
Template::Manual::Config::ERROR 中概述了错误的详细处理。
在构造函数中可以通过为异常类型指定模板来分类
my $template = Template->new({
ERRORS => {
user => 'user/index.html',
dbi => 'error/database',
default => 'error/default',
},
});
可以使用 THROW
指令引发
[% THROW user.login 'no user id: please login' %]
或调用throw
方法
$context->throw('user.passwd', 'Incorrect Password');
$context->throw('Incorrect Password'); # type 'undef'
或通过调用 die
的 Perl 代码,可能使用 Template::Exception
对象。
如何使用这个来解决问题是一个细节问题,其中提供了none。
但您真的想找到触发它的(用户)代码并清理它。其一,正如 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 thread and an old 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 {...};
有关更多详细信息,请参阅 及其指向其他帖子和相关文档的链接。
我收到以下错误消息(使用 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无关的事情。
代码做正确的事。唯一的问题是不应记录此错误消息。
如何停止将此错误消息打印到我们的日志文件中?
Template::Manual::Config::ERROR 中概述了错误的详细处理。
在构造函数中可以通过为异常类型指定模板来分类
my $template = Template->new({ ERRORS => { user => 'user/index.html', dbi => 'error/database', default => 'error/default', }, });
可以使用 THROW
指令引发
[% THROW user.login 'no user id: please login' %]
或调用throw
方法
$context->throw('user.passwd', 'Incorrect Password'); $context->throw('Incorrect Password'); # type 'undef'
或通过调用 die
的 Perl 代码,可能使用 Template::Exception
对象。
如何使用这个来解决问题是一个细节问题,其中提供了none。
但您真的想找到触发它的(用户)代码并清理它。其一,正如 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 thread and an old 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 {...};
有关更多详细信息,请参阅