in reply to DBI, DBD::Oracle and LD_LIBRARY_PATH
If you are running on Solaris (it looks to
me like you are)
LD_LIBRARY_PATH is cached by the linker
when your script is first started. The effect of this
is that any changes made to
LD_LIBRARY_PATH inside your program (even in
a BEGIN block) will not be reflected in how the linker
searches for libraries that need to be dynamically linked.
The only decent solution I ever came up with
was to ensure that LD_LIBRARY_PATH was set before my
perl program was ever started. Not
very elegant; but the problem isn't perl's fault.
RE: Re: DBI, DBD::Oracle and LD_LIBRARY_PATH
by Shendal (Hermit) on Aug 18, 2000 at 22:22 UTC
|
After much work (and tye and lhoward's assistance), here's what I've got to work:
BEGIN {
unless ($ENV{BEGIN_BLOCK}) {
$ENV{ORACLE_HOME} = '/common/oracle/product/v8.1.6';
$ENV{LD_LIBRARY_PATH} = "$ENV{ORACLE_HOME}/lib";
$ENV{TNS_ADMIN} = '/common/oracle/env';
$ENV{BEGIN_BLOCK} = 1;
exec 'env',$0,@ARGV;
}
}
use DBI;
$dbh = DBI->connect('','scmuser/scmuser@itopstst','','Oracle');
die $DBI::errstr unless defined $dbh;
lhoward says this is a problem with the way Solaris handles locating dynamically loaded libraries. ld.so.1(1) caches the LD_LIBRARY_PATH, so any changes we make don't matter. env(1) forces this to update.
*phew*
| [reply] [d/l] |
|
I ran into this problem recently on Linux. (I think it was triggered by an update of the Oracle InstantClient package; it used to run okay with caring about LD_LIBRARY_PATH. I'm not certain of that, though.)
I ended up using the solution above, but changing the first condition from
unless ($ENV{BEGIN_BLOCK}) {
to
unless (($ENV{BEGIN_BLOCK}) or $^C) {
so that my habitual "perl -c script.pl" reflexes would work. Without that change, the BEGIN block will re-execute the script in fully-operational mode, which is almost certainly not what you want.
(Of course, in versions of Perl that have it - certainly 5.6.0 onward, maybe later revisions of 5.005 - you should just use an INIT block instead. But that wasn't an option when the question was originally asked.)
| [reply] [d/l] [select] |
|
or simply give perl the library in the location where it looks for it. Silly but easy (if you are root).
ln -s $ORACLE_HOME/libnnz10.so /usr/lib/libnnz10.so
| [reply] |
|
|
I added the same lines in my perl program .
BEGIN {
unless ($ENV{BEGIN_BLOCK}) {
$ENV{ORACLE_HOME} = '/usr/local/lib/instantclient_10_2';
$ENV{LD_LIBRARY_PATH} = '/usr/local/lib/instantclient_10_2';
#$ENV{TNS_ADMIN} = '/common/oracle/env';
$ENV{BEGIN_BLOCK} = 1;
exec 'env',$0,@ARGV;
}
}
I am getting the below error message
env: this is not a file and directory
Please help
Thanks
Sri | [reply] [d/l] |
|
Thanks, this sparked a recollection and I got a solution working that didn't require exec() or messy wrappers. In fact, it is desirable in context of this code to put the "use DBD::Oracle;" in a module, so the exec was questionable for me anyway...
Use a .conf file and ldconfig. RedHat and others support this nowadays. (Google knows more about this than I do, so I leave the research to the reader.) Now on my "standard platforms" I have a .conf file listing the various LD_LIBRARY_PATHs I use, including the standardized path to Oracle client, and did ldconfig to reload that cache, and all is right with the world. No fussing with wrappers or messy execs.
Now if only we could prod Perl to force a reload of that cache (and subsequently its own), we wouldn't have an OS dependency...
| [reply] |
|
Now if only we could prod Perl to force a reload of that cache (and subsequently its own), we wouldn't have an OS dependency... Seeing how the entire concept of LD_LIBRARY_PATH is already OS dependent and flawed, perl should stay far away from it, and let the OS manage its business
| [reply] |
RE: Re: DBI, DBD::Oracle and LD_LIBRARY_PATH
by Shendal (Hermit) on Aug 18, 2000 at 21:50 UTC
|
Yes, I am indeed running Solaris. Is it possible to do something like this then, in order for the script to retain control?
#!/app/eol/perl/bin/perl -- # -*-Perl-*-
BEGIN {
unless ($ENV{BEGIN_BLOCK_DONE}) {
$ENV{ORACLE_HOME} = '/common/oracle/product/v8.1.6';
$ENV{LD_LIBRARY_PATH} = "$ENV{ORACLE_HOME}/lib";
$ENV{TNS_ADMIN} = '/common/oracle/env';
$ENV{BEGIN_BLOCK_DONE} = 1;
exec $0 @ARGV;
}
}
use DBI;
$dbh = DBI->connect('','scmuser/scmuser@itopstst','','Oracle');
die $DBI::errstr unless defined $dbh;
I've never run an exec in a BEGIN block... I don't know what possible caveats there may be.
Thanks,
Shendal
Update: Well, I tried it and it still doesn't work. ARGH!
| [reply] [d/l] |
|
The problem is even if you do it that way the linker already
has LD_LIBRARY_PATH cached and you can't change it.
The linker is started (and caches LD_LIBRARY_PATH) as
soon as perl is started. You really need to set LD_LIBRARY_PATH
before perl even starts.
Other that just setting LD_LIBRARY_PATH in the environment
the only solution
I came up with
was to set the environment, fork, and
have the new process do the
DB work. But that was kind of hokey and I didn't like
spawning the second process to do the work. I tried to look
for ways of chainging solaris's linker to not cache
LD_LIBRARY_PATH but never got very far.
BTW, LD_LIBRARY_PATH (and any other environmental vars used
by the linker) are the only ones you need to worry about.
You're OK setting other environmental vars
(ORACLE_HOME, TNS_ADMIN, etc...) in your
perl script. The problem is strictly related to the
behavior of solaris's linker.
| [reply] |
Re^2: DBI, DBD::Oracle and LD_LIBRARY_PATH
by ryber (Acolyte) on Jan 23, 2013 at 19:47 UTC
|
I know this is an old post, but it seems to still be relevant. On both Solaris and Linux, I have always used a wrapper shell script to set LD_LIBRARY_PATH etc.
When I recently had to run a PERL script using Oracle as a CGI via an Apache web server, I found that I could use Apache's SetEnv directive to set these environmental vars in my httpd.conf file, like so:
SetEnv LD_LIBRARY_PATH /lib64:/lib:/opt/oraClient/11.2.0.2/lib
SetEnv ORACLE_HOME /opt/oraClient/11.2.0.2
| [reply] [d/l] |
|
|