% ENV не работает, и я не могу использовать общую библиотеку - PullRequest
10 голосов
/ 28 декабря 2011

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

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/local/lib64/perl5/auto/DBD/Oracle/Oracle.so' для модуля DBD :: Oracle: libclntsh.so.10.1: не удается открыть общий объект file: Нет такого файла или каталога в /usr/lib64/perl5/DynaLoader.pm строка 200. на (eval 3) линии 3 Сбой компиляции в требовании в (eval 3) строке 3. Возможно, необходимая общая библиотека или DLL не установлены там, где ожидается на постоянстве. Perl 22 * ​​1010 *

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

Экспорт ORACLE_HOME и LD_LIBRARY_PATH через оболочку unix (export LD_LIBRARY_PATH=...) работает правильно. Любой совет?

Ответы [ 5 ]

10 голосов
/ 28 декабря 2011

Переменная окружения LD_LIBRARY_PATH должна быть установлена ​​ до запуска вашей программы - до самой загрузки perl.Изменение его в 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 { $0 } $0 => @ARGV;
  }
1 голос
/ 28 декабря 2011

Я написал несколько тестовых сценариев, чтобы убедиться, что среда изменяется при изменении %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-скрипте. Запуск test.pl Я получаю:

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.so) дополнительный набор каталогов, который нужно искать при поиске общих библиотек . Можно указать несколько каталогов, разделенных двоеточием (:). Этот список добавляется к существующему списку скомпилированных путей загрузчика для данного исполняемого файла и любых системных путей загрузчика по умолчанию.

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

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

0 голосов
/ 04 октября 2017

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

0 голосов
/ 25 сентября 2013

Одним из решений является изменение /etc/ld.so.conf

В CentOS / RHEL 6.4 вы можете создать etc / ld.so.conf.d / oracle с помощью этого:

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

Очевидно, измените в соответствии с вашими ORACLE_HOME.

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

ldconfig -v
0 голосов
/ 28 декабря 2011

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

...