10

我不能%ENV在我的 Perl 脚本上使用 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哈希。

导出ORACLE_HOMELD_LIBRARY_PATH通过 unix shell ( export LD_LIBRARY_PATH=...) 它可以正常工作。有什么建议吗?

4

5 回答 5

11

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:\n\n$@\n";
     exec { $0 } $0 => @ARGV;
  }
于 2011-12-28T15:46:52.457 回答
1

我编写了一些测试脚本来验证更改时是否正在设置环境%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 不仅设置了环境变量,而且还导出了这些变量,所谓的 shell 脚本可以访问它们。

您可以尝试类似的技术来验证两者LD_LIBRARY_PATHORACLE_HOME在使用它们之前都已设置。我怀疑你会发现这确实发生了,但是当你设置%ENV.

这指向一个结论:为 Perl 脚本启动时设置环境LD_LIBRARY_PATH可能ORACLE_HOME为时已晚。我相信操作系统会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似乎有效。

于 2011-12-28T16:30:34.820 回答
1

一种解决方案是修改 /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
于 2013-09-24T22:01:14.490 回答
0

您可以将export命令放入您应该有权编辑的 unix shell 的启动脚本中。这样,每当您启动一个新的 shell 时,都会设置环境变量,并且所有使用 Oracle 的脚本和程序都会选择它们。

于 2017-10-04T16:05:12.427 回答
-1

我刚刚经历了类似的事情。我必须确保在其他任何调用之前都设置了 Oracle 环境。确保该BEGIN块位于任何其他“使用”语句之前。就我而言,在 Apache 的 httpd.conf 文件中调用了一些东西,所以我不得不在那里而不是在我的包中设置我的环境。

于 2011-12-28T14:23:44.293 回答