% ENV не работает, и я не могу использовать общую библиотеку
Я не могу использовать %ENV
var на моем Perl script для использования 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'}
, все выглядит нормально, но когда я запускаю свой script, у меня есть ошибка:
install_driver (Oracle) не удалось: невозможно загрузить '/usr/local/lib64/perl5/auto/DBD/Oracle/Oracle.so' для модуля DBD:: Oracle: libclntsh.so.10.1: не удается открыть общий объект file: Нет файла или каталога на /usr/lib 64/perl5/DynaLoader.pm строке 200. на (eval 3) линии 3 Не удалось выполнить компиляцию в строке (eval 3) 3. Возможно, требуемая общая библиотека или dll не установлены там, где это ожидалось на persistence.perl строка 22
Поиск в Интернете Я видел, что правильный способ установки env vars на Perl - использовать хеш %ENV
.
Экспорт ORACLE_HOME
и LD_LIBRARY_PATH
через оболочку unix (export LD_LIBRARY_PATH=...
) работает корректно. Любые советы?
Ответы
Ответ 1
Переменная среды LD_LIBRARY_PATH
должна быть установлена до запуска вашей программы - перед загрузкой perl
. Изменение его в BEGIN{}
повлияет на запуск новых программ, но это не повлияет на загрузку разделяемых библиотек - в этом случае (хотя я никогда не использовал DBD:: Oracle) вы загружаете Oracle .so
в уже запущенную программу, поэтому "слишком поздно" изменить LD_LIBRARY_PATH
. Динамический компоновщик /lib/ld.so
(или так) запускается до perl
, поэтому к моменту скомпилирования script и BEGIN{}
он уже настроен.
Вы можете попытаться повторно выполнить свой script как свой собственный преемник или что-то еще, но короткая оболочка script почти наверняка станет самым простым решением:
#!/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 "[email protected]"
* - это было бы сумасшедшим, но TIMTOWTDI:
eval {
use DBD::Oracle foo bar baz; …
};
if ([email protected] =~ /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\[email protected]\n";
exec { $0 } $0 => @ARGV;
}
Ответ 2
Я написал несколько тестовых скриптов, чтобы убедиться, что среда задается при изменении %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 script работает test.sh
, который выводит значение переменной среды $FOO
, которая была установлена в моем Perl script. Запуск test.pl
Я получаю:
This is what I got bar-bar
Это показывает, что не только Perl задает переменные среды, но и экспортирует эти переменные, так называемые shell-скрипты имеют к ним доступ.
Вы можете попробовать аналогичную технику, чтобы убедиться, что оба параметра LD_LIBRARY_PATH
и ORACLE_HOME
устанавливаются до их использования. Я подозреваю, что вы обнаружите, что это действительно происходит, но ваша программа все еще не работает, когда вы устанавливаете %ENV
.
Это указывает на один вывод: установка среды для LD_LIBRARY_PATH
и ORACLE_HOME
может произойти слишком поздно к моменту запуска вашего Perl script. Я считаю, что операционная система проверяет LD_LIBRARY_PATH
до начала Perl. Я нашел это, выполнив поиск по LD_LIBRARY_PATH
:
LD_LIBRARY_PATH - это переменная среды, для которой вы устанавливаете значение , чтобы предоставить загрузчику разделяемой библиотеки времени выполнения (ld.so) дополнительный набор каталогов для поиска при поиске разделяемых библиотек. Можно указать несколько каталогов, разделенных двоеточием (:). Этот список добавляется к существующему списку скомпилированных путей загрузчика для данного исполняемого файла и к любым путям загрузчика по умолчанию.
Итак, LD_LIBRARY_PATH
предназначен для загрузчика разделяемой библиотеки ld.so
, если ld.so
уже загружен, изменение LD_LIBRARY_PATH
ничего не сделает.
Я нашел аналогичное обсуждение Perl Monks. Я заметил, что кто-то нашел reerunning env
, похоже, работал.
Ответ 3
Одним из решений является изменение /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
Ответ 4
Вы можете поместить команды export
в начало script для вашей оболочки unix, которая должна иметь разрешение на редактирование. Таким образом, переменные среды будут устанавливаться всякий раз, когда вы запускаете новую оболочку, и все сценарии и программы, использующие Oracle, будут их подбирать.
Ответ 5
Я просто прошел через нечто подобное. Я должен был убедиться, что среда Oracle была настроена до того, как ее еще называют. Убедитесь, что блок BEGIN
находится перед любыми другими операциями использования. В моем случае что-то вызывалось в файле Apache httpd.conf, поэтому мне пришлось настраивать свою среду там, а не в моем пакете.