Как мой скрипт Perl может найти свой модуль в том же каталоге?

недавно я написал новый скрипт Perl для уничтожения процессов на основе имени процесса / имени пользователя и расширил его с помощью классов, чтобы я мог повторно использовать код процесса в других программах. Мой текущий макет -

/home/mutew/src/prod/pskill       <-- Perl script
/home/mutew/src/prod/Process.pm   <-- Package to handle process descriptions

я добавил ~/src / prod в мою переменную $PATH для доступа к скрипту из любого места. При запуске скрипта из любого каталога, кроме его постоянного каталога, происходит "не удается найти процесс.pm in @INC "(что понятно, учитывая, что кроме общего каталоги в /usr, @INC включает только текущий каталог - '.'). Одним из обходных путей, который я использовал, является директива use lib как so -

use lib '/home/mutew/src/prod';

но это серьезная проблема переносимости. Любые решения, которые также позволят мне экспортировать скрипт в другие системы без изменений?


редактировать

  1. я выбрал ответ "depesz" как правильный из-за его простоты и использования основного модуля.
  2. Брайан ответ D foy, хотя и предлагает другие методы для достижения того же самого (TMTOWTDI), его вклад в perlfaq8 делает этот вопрос абсолютно избыточным.

8 ответов


самый простой подход, который я нашел, чтобы использовать модуль FindBin. Вот так:

use FindBin;
use lib $FindBin::Bin;

обычно я предпочитаю, чтобы мои скрипты предоставлялись таким образом, чтобы программы находились в любом/bin, а библиотеки-в любом/lib

в этих ситуациях я использую несколько более сложный подход:

use Cwd qw(abs_path);
use FindBin;
use lib abs_path("$FindBin::Bin/../lib");

вызов abs_path должен сделать @INC содержать любой/lib, а не любой/bin/../ lib - это всего лишь небольшое изменение, но делает чтение сообщений об ошибках облегчающий.


мне любопытно, почему упрощенное решение

use File::Basename;
use lib dirname (__FILE__);
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule;

не придумали. Модуль FindBin, похоже, имеет некоторые проблемы, если файл не является основным исполняемым скриптом perl, а просто неисполняемым модулем Perl. По крайней мере, так я интерпретирую комментарий документация. На самом деле не проверял.

чтобы иметь любой другой путь относительно местоположения этого файла Perl, сделайте что-то вроде

use File::Basename;
use lib dirname (__FILE__) . "/MyModules";

С perlfaq8, которая отвечает " как добавить каталог в мой путь включения (@INC) во время выполнения?". Есть несколько других ответов на вопросы, связанные с этой проблемой.


как добавить каталог в мой путь включения (@INC) во время выполнения?

вот предлагаемые способы изменения пути включения, включая переменные среды, переключатели времени выполнения и операторы in-code:

среда PERLLIB переменная

$ export PERLLIB=/path/to/my/dir
$ perl program.pl

переменная среды PERL5LIB

$ export PERL5LIB=/path/to/my/dir
$ perl program.pl

флаг командной строки perl-Idir

$ perl -I/path/to/my/dir program.pl

использование lib pragma:

use lib "$ENV{HOME}/myown_perllib";

последнее особенно полезно, потому что оно знает о зависимых от машины архитектурах. Либ.прагматический модуль pm был впервые включен в выпуск 5.002 Perl.


посмотри Par:: Packer. Он создает исполняемый файл со всеми включенными зависимостями скрипта. Это облегчает распространение. Вы также можете предоставить пользователям версию своего модуля, которая может быть установлена в их системах. См.Модуль::Стартер для простого способа создания всех файлов, необходимых для создания стандартного дистрибутива в стиле CPAN.


вы можете заставить perl искать в любом каталоге, используя -I флаг. Вот,-I расшифровывается как @INC который является массивом путей, в которых perl ищет модули. Используя -I добавляет заданный путь к @INC массив для этого выполнения.

например:

perl -I lib bin/script.pl

где lib содержит модули, которые я хочу использовать.

Я знаю, что это работает для в Perl 5. Я не уверен в других версиях.


чтобы преобразовать относительные ссылки в абсолютные и добавить в @INC, я обычно использую ex:: lib. Конечно, это полезно, только если вы планируете сохранить относительные местоположения скрипта и модуля одинаковыми на всех машинах, где вы планируете запустить скрипт.


FindBin:: libs найдет все ваши библиотеки, размещенные в разумных местах относительно пути, по которому выполняется ваш скрипт.


просто держите его простым. Нет необходимости импортировать какие-либо библиотеки; просто узнайте свой текущий рабочий каталог:

use lib "$ENV{PWD}/relativ_path_own_perllib";

для подобных проблем вы можете прочитать переменную среды, которая дает вашу информацию о том, где вы находитесь, ваш домашний каталог, материал операционной системы и так далее, с помощью всего одной строки программного кода в оболочке терминала, например:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV '

нет необходимости связывать некоторые библиотеки; просто используйте %ENV-Hash.