%ENV 不起作用,我无法使用共享库
我无法在 Perl 脚本中使用 %ENV
var 来使用 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) 失败:无法加载模块 DBD::Oracle 的“/usr/local/lib64/perl5/auto/DBD/Oracle/Oracle.so”:libclntsh.so.10.1:无法打开共享对象文件:/usr/lib64/perl5/DynaLoader.pm 第 200 行没有这样的文件或目录。 在 (eval 3) 第 3 行 (eval 3) 第 3 行的 require 编译失败。 也许所需的共享库或 dll 没有安装在预期的位置 在 persistence.perl 第 22 行
在网络上搜索我发现在 Perl 上设置环境变量的正确方法是使用 %ENV
哈希。
通过unix shell导出ORACLE_HOME
和LD_LIBRARY_PATH
(export LD_LIBRARY_PATH=...
)它可以正常工作。有什么建议吗?
I cannot use %ENV
var on my Perl script to use 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;
};
If I print $ENV{'ORACLE_HOME'}
and $ENV{'LD_LIBRARY_PATH'}
all seems ok but, when I run my script I have the error:
install_driver(Oracle) failed: Can't load '/usr/local/lib64/perl5/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: libclntsh.so.10.1: cannot open shared object file: No such file or directory at /usr/lib64/perl5/DynaLoader.pm line 200.
at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a required shared library or dll isn't installed where expected
at persistence.perl line 22
Searching on web I saw that the correct way to set env vars on Perl is to use %ENV
hash.
Exporting ORACLE_HOME
and LD_LIBRARY_PATH
through unix shell (export LD_LIBRARY_PATH=...
) it works correctly. Any advice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
LD_LIBRARY_PATH
环境变量必须在程序启动之前设置 - 在perl
本身加载之前。在BEGIN{}
中更改它会影响您启动的新程序,但不会影响共享库的加载 - 在本例中(虽然我从未使用过 DBD::Oracle)您正在将 Oracle.so
加载到已经运行的程序中,因此更改LD_LIBRARY_PATH
已经“太晚了”代码>.动态链接器/lib/ld.so
(或 so)在perl
之前启动,因此在编译脚本并BEGIN{}
时> 运行,它已经设置好了。你可以尝试重新执行你的脚本作为它自己的后继者或其他东西*,但是一个简短的shell脚本几乎肯定是最简单的解决方案:
* - 这有点疯狂,但是TIMTOWTDI:
The
LD_LIBRARY_PATH
environment variable has to be set before your program starts — beforeperl
itself is loaded. Changing it inBEGIN{}
will affect new programs that you start, but it won't affect the loading of shared libraries — in this case (although I've never used the DBD::Oracle) you're loading an Oracle.so
into the already-running program, so it's “too late” to change theLD_LIBRARY_PATH
. The dynamic linker/lib/ld.so
(or so) is started beforeperl
, so by the time your script is compiled andBEGIN{}
runs, it's already set up.You could try to re-exec your script as its own successor or something*, but a short shell script is almost certainly going to be the simplest solution:
*- this would be kinda crazy, but TIMTOWTDI:
我编写了一些测试脚本来验证当您更改
%ENV
时是否已设置环境:这会打印出:
这是我所期望的。
然后我尝试了这个:
并创建了一个
test.sh
程序,如下所示:在这种情况下,我的 Perl 脚本正在运行
test.sh
,它打印出在我的 Perl 脚本中设置的$FOO
环境变量。运行 test.pl 我得到:这表明 Perl 不仅设置环境变量,而且还导出这些变量,因此所谓的 shell 脚本可以访问它们。
您可以尝试类似的技术来验证
LD_LIBRARY_PATH
和ORACLE_HOME
在使用之前是否已设置。我怀疑您会发现这确实发生了,但是当您设置%ENV
时,您的程序仍然无法运行。这表明了一个结论:在 Perl 脚本启动时,为
LD_LIBRARY_PATH
和ORACLE_HOME
设置环境可能已经太晚了。我相信操作系统在 Perl 启动之前会检查 LD_LIBRARY_PATH 。我在 LD_LIBRARY_PATH 上进行搜索时发现:因此,
LD_LIBRARY_PATH
用于ld.so
运行时共享库加载器,如果ld.so
已经加载,则更改LD_LIBRARY_PATH< /code> 不会做任何事情。
我在 Perl Monks 上发现了类似的讨论。我注意到有人发现 重新运行
env
似乎有效。I wrote a few test scripts to verify that the environment is being set when you change
%ENV
:This prints out:
which is what I expected.
I then tried this:
and created a
test.sh
program that looks like this:In this case, my Perl script is running
test.sh
which prints out the value of the$FOO
environment variable that was set in my Perl script. Runningtest.pl
I get:This shows that not only is Perl setting the environment variables, but that it is also exporting those variables, so called shell scripts have access to them.
You can try a similar technique to verify that both
LD_LIBRARY_PATH
andORACLE_HOME
are being set before they're used. I suspect you'll find that this is indeed happening, but that your program still isn't working when you set%ENV
.This points to one conclusion: Setting the environment for
LD_LIBRARY_PATH
andORACLE_HOME
might be occurring too late by the time your Perl script starts. I believe the operating system examinesLD_LIBRARY_PATH
before Perl starts. I found this doing a search onLD_LIBRARY_PATH
:So,
LD_LIBRARY_PATH
is for theld.so
runtime shared library loader, Ifld.so
has already been loaded, changingLD_LIBRARY_PATH
won't do anything.I found a similar discussion on Perl Monks. I noticed someone found rerunning
env
seemed to work.一种解决方案是修改 /etc/ld.so.conf
在 CentOS/RHEL 6.4 上,您可以使用以下命令创建 etc/ld.so.conf.d/oracle:
显然,根据您的 ORACLE_HOME 进行修改。
然后运行
One solution is to modify /etc/ld.so.conf
On CentOS/RHEL 6.4, you could create etc/ld.so.conf.d/oracle with this:
Obviously, modify as suits your ORACLE_HOME.
Then run
您可以将
export
命令放入您的 UNIX shell 的启动脚本中,您应该有权编辑该脚本。这样,每当您启动新 shell 时都会设置环境变量,并且所有使用 Oracle 的脚本和程序都会选择它们。You could put the
export
commands into the start up script for your unix shell which you should have permission to edit. That way, the environment variables will be set whenever you start a new shell and all scripts and programs that use Oracle will pick them up.我刚刚经历过类似的事情。我必须确保 Oracle 环境在其他任何调用之前已设置完毕。确保
BEGIN
块位于任何其他“use”语句之前。就我而言,Apache 的 httpd.conf 文件中正在调用某些内容,因此我必须在那里设置我的环境,而不是在我的包中。I just went through something similar. I had to make sure that the Oracle environment was setup before anything else called it. Make sure the
BEGIN
block is before any other "use" statements. In my case, something was being called in Apache's httpd.conf file, so I had to setup my environment there instead of in my package.