gpt4 book ai didi

Perl "do",相对路径以 "."或 ".."开头

转载 作者:行者123 更新时间:2023-12-01 11:16:49 25 4
gpt4 key购买 nike

我正在尝试使用 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 不搜索“.”的特别警告。等等。但它也有这些位:

# load the exact specified file (./ and ../ special-cased)...


Using do with a relative path (except for ./ and ../), like...

然后它实际上从来没有费心去解释“./”或“../”的特殊情况路径处理——一个重要的遗漏!

所以我的问题都是关于“当你做'./file.pl';真正会发生什么”的所有变体?例如……

  • 虽然 CWD 从 @INC 中删除了,但此语法在 5.26 中是否仍然有效?
  • 无论如何从谁的角度来看“./”:Perl 二进制文件、执行的 Perl 脚本、来自用户 shell 的 CWD,还是其他?
  • 是否存在需要注意的安全风险?
  • 这比修改@INC 并仅使用基本文件名好还是坏?

欢迎任何见解。

最佳答案

好的,所以 - 首先,我不确定你的 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

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

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 $!;

然后您就会知道您正在读取与您的脚本位于同一目录中的脚本,无论它是从何处调用的。

具体问题:

From whose perspective is "./" anyway: the Perl binary, the Perl script executed, CWD from the user's shell, or something else?

当前工作目录通过进程向下传递。所以默认情况下用户的 shell,除非 perl 脚本执行 chdir

Are there security risks to be aware of?

任何时候你“评估”一些东西就好像它是可执行代码(并且 EXPR 可以)都存在安全风险。它可能并不大,因为脚本将作为用户运行,而用户是可以篡改 CWD 的人。核心风险是:

  • 用户在一个“不同的”目录中,其他人在该目录中放置了恶意软件供他们运行。 (例如,假设'config.pl'中有 rm -rf/* )。也许在 /tmp 中有一个他们不小心“运行”的“config.pl”?
    • 您正在评估的东西有错字,并且以古怪和意想不到的方式破坏了脚本。 (例如,它可能会重新定义 $[ 并从此以后以难以调试的方式扰乱程序逻辑)
  • 脚本在特权上下文中做任何事情。情况似乎并非如此,但请参阅上一点并想象一下您是 root 还是其他特权用户。

Is this better or worse than modifying @INC and just using a base filename?

更糟糕的海事组织。实际上根本不修改@INC,而是使用完整路径,或使用FindBin 的相对路径。并且不要在不必要的时候eval 东西。

关于Perl "do",相对路径以 "."或 ".."开头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49787980/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com