我不能在我的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) failed: Can't load '/usr/local/lib64/perl5/auto/DBD/Oracle/Oracle。Oracle: libclntsh.so.10.1:无法打开共享对象文件:/usr/lib64/perl5/DynaLoader中没有这样的文件或目录。PM线200。At (eval 3)第3行require at (eval 3)第3行编译失败。可能所需的共享库或dll没有安装在预期的位置在持久性。Perl第22行
在网上搜索,我看到在Perl上设置环境变量的正确方法是使用%ENV
哈希。
通过unix shell (export LD_LIBRARY_PATH=...
)导出ORACLE_HOME
和LD_LIBRARY_PATH
可以正常工作。任何建议吗?
必须在程序启动之前设置LD_LIBRARY_PATH
环境变量 -在perl
本身加载之前。在BEGIN{}
中更改它将影响您启动的新程序,但它不会影响共享库的加载 -在这种情况下(尽管我从未使用过DBD::Oracle),您正在将Oracle .so
加载到已经运行的程序中,因此更改LD_LIBRARY_PATH
"为时已晚"。动态链接器/lib/ld.so
(或左右)在perl
之前启动,所以当脚本编译和BEGIN{}
运行时,它已经设置好了。
你可以尝试重新执行你的脚本作为它自己的继承者或什么*,但一个简短的shell脚本几乎肯定是最简单的解决方案:
#!/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:nn$@n";
exec { $0 } $0 => @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
,它打印出在我的Perl脚本中设置的$FOO
环境变量的值。运行test.pl
我得到:
This is what I got bar-bar
这表明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_LIBRARY_PATH
是ld.so
运行时共享库加载器,如果ld.so
已经加载,更改LD_LIBRARY_PATH
不会做任何事情。
我在Perl Monks上发现了类似的讨论。我注意到有人发现重新运行env
似乎工作。
一个解决方案是修改/etc/ld.so.conf
在CentOS/RHEL 6.4中,您可以创建etc/ld.so.conf。D/oracle with this
/oracle/sw/product/11.2.0/dbhome_1/lib
显然,修改为适合您的ORACLE_HOME。
然后运行
ldconfig -v
您可以将export
命令放入您应该具有编辑权限的unix shell的启动脚本中。这样,无论何时启动一个新shell,环境变量都将被设置,并且所有使用Oracle的脚本和程序都会拾取它们。
我刚刚经历了类似的事情。我必须确保在调用Oracle环境之前设置好它。确保BEGIN
块位于任何其他"use"语句之前。在我的例子中,Apache的httpd.conf文件中调用了一些东西,所以我必须在那里而不是在包中设置环境。