在任何文件中没有 'use warnings' 或 -w 打印的 Perl 警告

Perl warning printed without 'use warnings' or -w in any files

我有很多经常调用的旧 Perl 代码,我一直在编写一个新模块,突然间我在我的 error_log 中收到了很多针对 Apache 的警告,它们是对于当前正在使用的每个模块。例如,

"my" variable $variable masks earlier declaration in same statement at
    /path/to/module.pm line 40 (#1)

Useless use of hash element in void context at
    /path/to/another/module.pm line 212 (#2)

代码库的主要布局是一个巨大的脚本,其中包含模块并将请求定向到为网站创建特定页面所需的模块,然后主脚本处理菜单等静态元素。

我当前的项目与这个主脚本分开并且不使用它,但是每次我使用 ajax 调用我的代码时,还有一些其他 ajax 调用将使用主脚本并且警告似乎只出现在那些请求中,但只有在我调用我的项目时才会出现。

我已经对每个模块进行了 grep,其中 none 其中有使用警告(或 -w),我也尝试过在主脚本和我自己的项目中不使用警告 'all' 但是它什么也没做。

在这一点上,我不知道下一步该怎么做,所以感谢所有帮助,我只是想取消警告,代码库很旧而且写得不好所以继续并纠正每个问题导致警告首先是不可行的。

Apache 服务器也是 运行 mod_perl,如果这可能有所不同,我感觉它可能与 CGI 有关,但我似乎找不到任何证据。

我认为代码被 运行 某些顶级 Perl 脚本调用。

然后在这些脚本中使用 __WARN__ 挂钩停止打印警告

BEGIN { $SIG{__WARN__} = sub {} };

将此 BEGIN 块放在 use 语句之前,以便也影响模块。

空子例程是消除警告的方法,因为 __WARN__ 不支持 'IGNORE'

参见 warn and %SIG in perlvar。 请参阅 and 以获取评论和一些示例。


要进一步调查并跟踪警告,您可以使用 Carp

BEGIN {
    $SIG{__WARN__} = \&Carp::cluck;  # or Carp::confess; to also die
}

这将使它打印完整的堆栈跟踪。这可以根据您的喜好进行微调,因为我们可以编写自己的 sub 来调用。或者使用 Carp::Always.

this post 对于一些更严厉的措施(比如覆盖 CORE::GLOBAL::warn

一旦找到更精确的抑制警告级别,那么 local $SIG{__WARN__} 就是可行的方法。这是在上面链接的post中使用的,这里是。只在需要的地方而不是在所有地方抑制警告当然要好得多。

更多详情

  • Getting stack traces in Perl?

  • How can I get a call stack listing in Perl?

请注意,不幸的是,longmess 不再那么标准且得到很好的支持。