默认情况下,Perl 不包含 @INC 中的当前目录吗?
Posted
技术标签:
【中文标题】默认情况下,Perl 不包含 @INC 中的当前目录吗?【英文标题】:Doesn't Perl include current directory in @INC by default? 【发布时间】:2018-03-14 22:48:50 【问题描述】:我从来没有完全理解 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
中删除。
但是,在 5.26 之前,任何依赖于当前目录位于 @INC
中的代码都存在缺陷。这样做的代码,就像你的一样,错误地使用当前目录作为脚本目录的代理。这种假设通常是不正确的。
要告诉 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,这是版本检查。请参阅use
的use 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 中的当前目录吗?的主要内容,如果未能解决你的问题,请参考以下文章