[英]Perl “do”, with relative path beginning with “.” or “..”
我正在尝试使用Perl的do EXPR
函数作为穷人的配置解析器,使用第二个.pl文件,它只返回一个列表作为配置信息。 (我想这大概是为理想的使用do
,不仅是因为我可以写“ do or die
在我的代码”。)下面是一个例子:
main.pl
# Go read the config file
my %config = do './config.pl';
# do something with it
$web_object->login($config{username}, $config{password});
config.pl
# Configuration file for main script
(
username => "username",
password => "none_of_your_business",
favorite_color => "0x0000FF",
);
阅读Perldoc for do
提供了很多关于相对路径的有用建议 - 搜索@INC和修改%INC,关于5.26不搜索的特殊警告“。” 更多,等等。但它也有这些位:
#加载确切的指定文件(./和../ special-cased) ...
使用do与相对路径(./和../除外) ,如...
然后它实际上从来没有麻烦解释“./”或“../”的特殊情况路径处理 - 一个重要的遗漏!
所以我的问题是“你do './file.pl';
什么时真正发生的事情do './file.pl';
所有变化do './file.pl';
“? 例如...
任何见解都表示赞赏。
好吧,所以 - 首先,我不确定你的config.pl
是否是正确的方法 - 它不是初学者的perl
,因为它不能编译。 无论哪种方式,尝试评估“解析配置”的东西通常不是一个很好的计划 - 它很容易出现令人不快的故障和安全漏洞,因此应该在需要时保留。
我敦促你以不同方式做到:
像这样的东西:
package MyConfig;
# Configuration file for main script
our %config = (
username => "username",
password => "none_of_your_business",
favorite_color => "0x0000FF",
);
然后你可以在你的主脚本中:
use MyConfig; #note - the file needs to be the same name, and in @INC
并将其访问为:
print $MyConfig::config{username},"\n";
如果你不能把它放在现有的@INC
- 这可能是你不能的原因, FindBin
允许你使用相对于你的脚本位置的路径:
use FindBin;
use lib "$FindBin::Bin";
use MyConfig;
YAML
特别适用于配置文件:
use YAML::XS;
open ( my $config_file, '<', 'config.yml' ) or die $!;
my $config = Load ( do { local $/; <$config_file> });
print $config -> {username};
你的配置文件看起来像:
username: "username"
password: "password_here"
favourite_color: "green"
air_speed_of_unladen_swallow: "african_or_european?"
(YAML也支持多维数据结构,数组等。但您似乎并不需要这些。)
基于JSON
看起来大致相同,只是输入是:
{
"username": "username",
"password": "password_here",
"favourite_color": "green",
"air_speed_of_unladen_swallow": "african_or_european?"
}
你读它:
use JSON;
open ( my $config_file, '<', 'config.json' ) or die $!;
my $config = from_json ( do { local $/; <$config_file> });
您根本不必担心@INC
。 您可以简单地使用基于相对路径...但更好的选择是不要这样做,而是使用FindBin
- 这可以让您指定“相对于我的脚本路径”,而且更加健壮。
use FindBin;
open ( my $config_file, '<', "$FindBin::Bin/config.yml" ) or die $!;
然后你就会知道你正在读取与你的脚本在同一目录中的那个,无论它从哪里被调用。
从哪个角度看是“./”:Perl二进制文件,执行的Perl脚本,来自用户shell的CWD,还是别的东西?
当前工作目录向下传递进程。 默认情况下是用户的shell,除非perl脚本执行chdir
是否存在安全隐患?
任何时候你'评估'某些东西就好像它是可执行代码(和EXPR
可能)一样,存在安全风险。 它可能不是很大,因为脚本将以用户身份运行,并且用户是可以篡改CWD
。 核心风险是:
rm -rf /*
)。 也许在/tmp
中有一个'config.pl'它们会意外地“运行”?
eval
的东西有一个错字,并以时髦和意想不到的方式打破脚本。 (例如,它可能会重新定义$[
并且以后面的程序逻辑混乱,难以调试) root
还是其他特权用户。 这比修改@INC和使用基本文件名更好还是更差?
更糟糕的IMO。 实际上只是根本不修改@INC
,并使用完整路径或使用FindBin
相对路径。 并且在没有必要时不要eval
事物。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.