Perl "do", относительный путь начинается с "." или же ".."
Я пытаюсь использовать Perl's 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 дляdo
дает много полезных советов об относительных путях - поиск в @INC и изменение%INC, специальные предупреждения о том, что 5.26 не выполняет поиск "." и так далее. Но у этого также есть эти биты:
# загрузить точно указанный файл (./ и../ в специальном регистре)...
Использование do с относительным путем (кроме./ и../), например...
И тогда на самом деле никогда не стоит объяснять обработку пути в Особом случае для "./" или "../" - важное упущение!
Так что мой вопрос (ы) все варианты "что на самом деле происходит, когда вы do './file.pl';
"? Например...
- Этот синтаксис все еще работает в 5.26, хотя CWD удален из @INC?
- В любом случае, с какой точки зрения "./": двоичный файл Perl, исполняемый скрипт Perl, CWD из пользовательской оболочки или что-то еще?
- Существуют ли угрозы безопасности, о которых следует знать?
- Это лучше или хуже, чем модифицировать @INC и просто использовать базовое имя файла?
Любое понимание приветствуется.
1 ответ
Хорошо, так что - для начала, я не уверен, что ваш 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;
Напишите ваш "config" в виде определенного синтаксического формата, а не исполняемого кода.
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 $!;
И тогда вы узнаете, что вы читаете тот же каталог, что и ваш скрипт, независимо от того, откуда он вызывается.
конкретные вопросы:
В любом случае, с какой точки зрения "./": двоичный файл Perl, исполняемый скрипт Perl, CWD из пользовательской оболочки или что-то еще?
Текущий рабочий каталог проходит через процессы. Таким образом, оболочка пользователя по умолчанию, если сценарий perl не выполняет chdir
Существуют ли угрозы безопасности, о которых следует знать?
Каждый раз, когда вы "оцениваете" что-то, как будто это исполняемый код (и EXPR
может быть) есть угроза безопасности. Вероятно, он невелик, потому что скрипт будет работать как пользователь, а пользователь - это тот, кто может вмешиваться CWD
, Основные риски:
- Пользователь находится в "другом" каталоге, где кто-то другой поместил вредоносную вещь для запуска. (например, представьте, что "config.pl" имел
rm -rf /*
в этом например). Может быть, есть "config.pl" в/tmp
что они "бегают" случайно?- То, что вы
eval
У ing есть опечатка, и он ломает скрипт неожиданным и неожиданным образом. (Например, может быть, это переопределяет$[
и впредь мешает логике программы способами, которые трудно отлаживать)
- То, что вы
- скрипт делает все что угодно в привилегированном контексте. Который, кажется, не имеет место, но посмотрите предыдущий пункт и представьте, если вы
root
или другой привилегированный пользователь.
Это лучше или хуже, чем модифицировать @INC и просто использовать базовое имя файла?
Хуже ИМО. На самом деле просто не модифицируйте @INC
и использовать полный путь, или относительный путь, используя FindBin
, И не eval
вещи, когда это не нужно.