%ENV doesn't work and I cannot use shared library
Asked Answered
B

5

10

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?

Bicameral answered 28/12, 2011 at 14:15 Comment(3)
It has been a long time since I have had to work with Oracle and Perl and I remember that one of the libraries that the Perl module needs doesn't install with the developer install. I would have to extract the files and pull the library out of the database package.Spindly
But is strange, because if I export those paths through shell, it works correctly. Seems not a problem related to missing librariesBicameral
Shell script wrapper is how we always did it.Lindholm
D
11

The LD_LIBRARY_PATH environment variable has to be set before your program starts — before perl itself is loaded. Changing it in BEGIN{} 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 the LD_LIBRARY_PATH. The dynamic linker /lib/ld.so (or so) is started before perl, so by the time your script is compiled and BEGIN{} 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:

  #!/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 "$@"

*- this would be kinda crazy, but 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;
  }
Dwan answered 28/12, 2011 at 15:46 Comment(0)
D
1

I wrote a few test scripts to verify that the environment is being set when you change %ENV:

use strict;
use warnings;
use feature qw(say);

BEGIN {
    my $foo = "bar-bar";
    $ENV{FOO} = "$foo";
}

system qq(/bin/echo printing out \$FOO);

This prints out:

printing out bar-bar

which is what I expected.

I then tried this:

use strict;
use warnings;
use feature qw(say);

BEGIN {
    my $foo = "bar-bar";
    $ENV{FOO} = "$foo";
}


system qq(./test.sh);

and created a test.sh program that looks like this:

#! /bin/sh

echo This is what I got: $FOO;

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. Running test.pl I get:

This is what I got bar-bar

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 and ORACLE_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 and ORACLE_HOME might be occurring too late by the time your Perl script starts. I believe the operating system examines LD_LIBRARY_PATH before Perl starts. I found this doing a search on LD_LIBRARY_PATH:

LD_LIBRARY_PATH is an environment variable you set to give the run-time shared library loader (ld.so) an extra set of directories to look for when searching for shared libraries. Multiple directories can be listed, separated with a colon (:). This list is prepended to the existing list of compiled-in loader paths for a given executable, and any system default loader paths.

So, LD_LIBRARY_PATH is for the ld.so runtime shared library loader, If ld.so has already been loaded, changing LD_LIBRARY_PATH won't do anything.

I found a similar discussion on Perl Monks. I noticed someone found rerunning env seemed to work.

Degraw answered 28/12, 2011 at 16:30 Comment(0)
A
1

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:

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

Obviously, modify as suits your ORACLE_HOME.

Then run

ldconfig -v
Arapaima answered 24/9, 2013 at 22:1 Comment(0)
C
0

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.

Citric answered 4/10, 2017 at 16:5 Comment(0)
A
-1

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.

Ashaashamed answered 28/12, 2011 at 14:23 Comment(3)
Yes, my BEGIN block is before everythingBicameral
Is this in a web environment? If so, it is possible that something loading DBD::Oracle before it makes it to your script.Ashaashamed
No, it is not in a web enviroment. It's just a script that I run from shellBicameral

© 2022 - 2024 — McMap. All rights reserved.