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 вещи, когда это не нужно.

Другие вопросы по тегам