%ENV не работает, и я не могу использовать общую библиотеку

Я не могу использовать %ENV var в моем скрипте Perl для использования Oracle libs.

BEGIN {
    $ORACLE_HOME = "/usr/lib/oracle/10.2.0.3/client64";
    $LD_LIBRARY_PATH = "$ORACLE_HOME/lib";
    $ORACLE_SID="prod";
    $ENV{ORACLE_SID}=$ORACLE_SID;
    $ENV{ORACLE_HOME}= $ORACLE_HOME;
    $ENV{LD_LIBRARY_PATH}= $LD_LIBRARY_PATH;
};

если я распечатаю $ENV{'ORACLE_HOME'} и $ENV{'LD_LIBRARY_PATH'} все кажется ок, но, когда я запускаю свой скрипт, у меня есть ошибка:

install_driver(для Oracle) ошибка: не удается загрузить '/usr/местные/lib64/perl5/авто/ДБР/Оракул/Оракул.поэтому для модуля ДБР::Оракул: libclntsh.так.10.1: невозможно открыть разделяемый объектный файл: нет такого файла или каталога в /usr/lib64/perl5/DynaLoader.линия часов 200. at (eval 3) строка 3 Сборник ошибка в require at (eval 3) строка 3. Возможно, требуемая общая библиотека или dll не установлена там, где ожидалось при настойчивости.строки в Perl 22

поиск в Интернете я видел, что правильный способ установить env vars на Perl-использовать %ENV хэш.

экспорт ORACLE_HOME и LD_LIBRARY_PATH через оболочку unix (export LD_LIBRARY_PATH=...) он работает правильно. Есть советы?

5 ответов


на LD_LIBRARY_PATH переменная окружения должна быть установлена до ваша программа начинается - перед загружается. Изменение его в BEGIN{} повлияет новый - программы что вы начинаете, но это не повлияет на загрузку общие библиотеки - в этом случае (хотя я никогда не использовал DBD::Oracle) вы загружаете Oracle .so в уже запущенную программу, поэтому" слишком поздно " менять LD_LIBRARY_PATH. Динамический компоновщик /lib/ld.so (или так) запускается до perl, поэтому к моменту компиляции вашего скрипта и BEGIN{} работает, он уже настроен.

вы мог бы попробуйте повторно выполнить свой скрипт как собственный преемник или что-то*, но короткий сценарий оболочки почти наверняка будет самым простым решением:

  #!/bin/sh
  export LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client64/lib
  export ORACLE_SID=prod
  exec /usr/local/bin/your-db-program "$@"

* - это было бы немного сумасшедшим, но TIMTOWTDI:

  eval { 
     use DBD::Oracle foo bar baz; …
  };
  if ($@ =~ /install_driver\(Oracle\) failed/) {
     $ENV{LD_LIBRARY_PATH} .= ':/usr/lib/oracle/10.2.0.3/client64/lib';
     $ENV{ORACLE_SID} = 'prod';
     warn "Restarting with LD_LIBRARY_PATH reset:\n\n$@\n";
     exec {  }  => @ARGV;
  }

я написал несколько тестовых сценариев, чтобы проверить, что среда устанавливается при изменении %ENV:

use strict;
use warnings;
use feature qw(say);

BEGIN {
    my $foo = "bar-bar";
    $ENV{FOO} = "$foo";
}

system qq(/bin/echo printing out $FOO);

это распечатывает:

printing out bar-bar

чего я и ожидал.

я тогда попробовал это:

use strict;
use warnings;
use feature qw(say);

BEGIN {
    my $foo = "bar-bar";
    $ENV{FOO} = "$foo";
}


system qq(./test.sh);

и создал test.sh программа, которая выглядит так:

#! /bin/sh

echo This is what I got: $FOO;

в этом случае мой скрипт Perl работает test.sh который печатает значение $FOO переменная среды, которая была установлена в моем Perl скрипт. Бег!--9--> Я:

This is what I got bar-bar

это показывает, что Perl не только устанавливает переменные среды, но и экспортирует эти переменные, так называемые сценарии оболочки имеют к ним доступ.

вы можете попробовать аналогичную технику, чтобы проверить, что оба LD_LIBRARY_PATH и ORACLE_HOME устанавливаются до их использования. Я подозреваю, что вы обнаружите, что это действительно происходит, но ваша программа все еще не работает, когда вы установите %ENV.

этот указывает на один вывод: установка среды для LD_LIBRARY_PATH и ORACLE_HOME может произойти слишком поздно к моменту запуска сценария Perl. Я считаю, что операционная система проверяет LD_LIBRARY_PATH перед началом Perl. Я нашел это, делая поиск на LD_LIBRARY_PATH:

LD_LIBRARY_PATH-это переменная среды, которую вы установили в дайте загрузчику общей библиотеки времени выполнения (ld.Итак) дополнительный набор каталогов для поиска при поиске общих библиотек. Множественный каталоги могут быть перечислены, разделены двоеточием (:). Этот список добавляется к существующему списку скомпилированных путей загрузчика для данного исполняемого файла и к любым системным путям загрузчика по умолчанию.

и LD_LIBRARY_PATH на ld.so загрузчик общей библиотеки времени выполнения, если ld.so уже загружен, изменение LD_LIBRARY_PATH ничего не сделает.

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


выход один-изменить файл /etc/ЛД.так.конф

на CentOS / RHEL 6.4 вы можете создать etc / ld.Итак.conf.d / oracle с этим:

/oracle/sw/product/11.2.0/dbhome_1/lib

очевидно, измените, как подходит вашему ORACLE_HOME.

затем запустите

ldconfig -v

вы могли бы поставить export команды в сценарий запуска для вашей оболочки unix, который вы должны иметь разрешение на редактирование. Таким образом, переменные среды будут устанавливаться при запуске новой оболочки, и все сценарии и программы, использующие Oracle, будут получать их.


Я только что прошел через что-то подобное. Я должен был убедиться, что среда Oracle была настроена, прежде чем что-либо еще называлось это. Убедитесь, что BEGIN блок находится перед любыми другими операторами "use". В моем случае что-то вызывалось в httpd Apache.conf-файл, поэтому мне пришлось настроить мою среду там, а не в моем пакете.