默认情况下,Perl 不包含 @INC 中的当前目录吗?

Posted

技术标签:

【中文标题】默认情况下,Perl 不包含 @INC 中的当前目录吗?【英文标题】:Doesn't Perl include current directory in @INC by default? 【发布时间】:2022-01-13 04:12:30 【问题描述】:

我从来没有完全理解 Perl 对包名称的解析,但我一直认为以下内容应该总是有效的,假设您是从包含它的目录中执行 myscript.pl:

myscript.pl (contains the following statement: use Class1::Class2::Class3)
Class1/
    Class2/
        Class3.pm (contains the following package declaration: package Class1::Class2::Class3;)

但是,这在我的代码中不起作用,因为找不到 Class3.pm。看@INC,不包括当前目录,只包括我的Strawberry Perl安装的各个目录。

解决此问题的推荐方法是什么?我想我可以修改@INC,或者我可以开始使用 FindBin,但我不确定哪个最好。我继承了这段代码,只是将它迁移到一个新位置,但看起来旧代码不需要这样的解决方案(我可能错了,还在寻找......)

【问题讨论】:

v5.26 removes dot from @INC 【参考方案1】:

Perl 不会在当前目录中搜索模块,也不会在脚本目录中搜索模块,至少现在不会。出于安全原因,当前目录在 5.26 中已从 @INC 中删除。

但是,任何依赖于当前目录位于 @INC 中的代码在 5.26 之前都存在缺陷。这样做的代码,就像你的一样,错误地使用当前目录作为脚本目录的代理。这种假设通常是不正确的。

要告诉 Perl 在脚本目录中查找模块,请使用以下命令:

use FindBin 1.51 qw( $RealBin );
use lib $RealBin;

use Cwd qw( abs_path );
use File::Basename qw( dirname );
use lib dirname(abs_path($0));

【讨论】:

一个切题的问题,但为什么$RealBin 而不仅仅是$Bin?解决这些链接是否给我们带来了任何好处,或者您在这里使用它只是一种一般的良好做法? @sundar, $Bin 如果有人创建了指向脚本的符号链接,则将不起作用。 FindBin 的 1.51 参数是什么?我没有看到 perldoc for FindBin 中提到的类似用法。 @Greg Kennedy,这是版本检查。请参阅useuse Module VERSION LIST 语法。 @textral,__FILE__$0 之间没有区别(除非你更改了$0,所以__FILE__ 稍微好一点)。那不是问题。问题是您使用了realpath(dirname(__FILE__)) 而不是dirname(realpath(__FILE__))。如果使用符号链接,您的方式将失败。【参考方案2】:

出于安全原因,@INC 中的 .(当前目录)为 removed in 5.26 (CVE-2016-1238)。一些 Linux 发行版已经向后移植了这个变化,所以即使你使用例如,你也可能会遇到这个问题。 5.24.

【讨论】:

@ikegami 哦,有趣。我不知道 FindBin 是固定的。 search $PATH 直到 1.51 版,与 perl 5.16 一起发布。 @ikegami 我撤回了我的代码。您的 FindBin 解决方案更好(假设它至少是 1.51 版,所以 use FindBin 1.51 qw($RealBin) 可能是个好主意)。【参考方案3】:

Perl 5.26 删除了在@INC 中的当前工作目录作为安全措施。

在5.26 perldelta notes中有解释。

【讨论】:

以上是关于默认情况下,Perl 不包含 @INC 中的当前目录吗?的主要内容,如果未能解决你的问题,请参考以下文章

Perl:将当前目录包含到@INC吗?

如何解决 Perl 中的 @INC 相关问题

[Perl] 模块搜索路径变量 @INC

如何包含位于不同目录中的 Perl 模块?

默认情况下为啥没有设置线程化 perl(带有 usethreads)?

如何在不使用 Sybase/Perl 中的游标的情况下从表/文件中的 2 行中获取结果集中的一行