In 2005, it was sufficient to setup %ENV in a BEGIN block *BEFORE* loading DBD::Oracle:

#!/usr/bin/perl -T
use strict;
use warnings;
BEGIN {
   $ENV{'ORACLE_HOME'}='/some/where/on/the/disk';
}
use DBI;
# ...
my $dbh=DBI->connect('dbi:Oracle:...',$user,$pass);
# ...

The trick was that DBI loads DBD/Oracle.pm, which loads DBD::Oracle.xs, which loads the Oracle client libraries, which need %ENV set up properly. Until the point where the Oracle client libraries are loaded, the %ENV did (and does) not matter.

Note that %ENV is set up in a BEGIN block before use DBI, just in case DBI would load DBD::Oracle (and thus the Oracle client libraries). If I was really paranoid, I would write

BEGIN {
   $ENV{'ORACLE_HOME'}='/some/where/on/the/disk';
   require DBI;
}

instead, just in case DBI would load DBD::Oracle before connect() was called.

And regarding Apache: Apache DOES NOT pass its environment to its child processes unmodified, instead, it removes most environment variables. To pass a variable from Apaches environment to a child process (CGI), you have to specify it in the Apache configuration in a "PassEnv" directive, i.e. "PassEnv ORACLE_HOME". It should also be possible to use "SetEnv ORACLE_HOME /some/where/on/the/disk".

See also <http://www.alexander-foken.de/Censored%20copy%20of%20Oracle%20Troubleshooter%20HOWTO.html>, which is written for a Windows-based DBI application accessing an Oracle database, but except for the backslashes and the DLL suffix, most of it is also true for DBI applications on Unix-like systems.

Alexander


On 10.01.2009 14:16, Alexander V Alekseev wrote:
        Hello!

On Fri, 9 Jan 2009, Koester, Chris wrote:

Scripts ran from cron give this error.

failed: ERROR OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc. at /app/XOstats/prod/bin/util/check_user.pl line 43 Can't call method "disconnect" on an undefined value at /app/XOstats/prod/bin/util/check_user.pl line 69.

Web log give this error.

[Fri Jan 09 12:08:57 2009] [error] [client 172.31.48.85] Premature end of script headers: Login.pl [Fri Jan 09 12:21:39 2009] [error] [client 172.31.48.85] install_driver(Oracle) failed: Can't load '/xst/xstlocal/bin/lib/perl5/site_perl/5.10.0/i86pc-solaris-thread-multi/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: ld.so.1: perl: fatal: libnnz10.so: open failed: No such file or directory at /xst/xstlocal/bin/lib/perl5/5.10.0/i86pc-solaris-thread-multi/DynaLoader.pm line 203.

For some reason its not recognizing the $ENV{…. } set with in the perl
scripts to identify ORACLE_HOME and other variables.
    Most ld.so implementations read environment only once. When your
application is loaded, ld.so is initialized first, therefore you usually
cannot change it's environment from your code.

$ENV{"ORACLE_HOME"}="/xst/xstlocal/bin/oracleInstantClient/instantclient_10_2"; $ENV{"TNS_ADMIN"}="/xst/xstlocal/bin/oracleInstantClient/instantclient_10_2"; $ENV{"LD_LIBRARY_PATH"}="/xst/xstlocal/bin/oracleInstantClient/instantclient_10_2:....

If I have the script from the command line with all the env variables
set correctly the script runs.   It basically does not recognize the
variables in the scripts.
    The best way to solve the problem is to set environment before
http server starts. (for example in its startup script).
    If you do not have access to httpd startup, and your script is
pure CGI (not FastCGI, not mod_perl, etc...), you can put something like
this to your script:
-------------------------------
#!/usr/bin/perl

BEGIN {
if (not $ENV{"MYLIBSET"} and (not $ENV{"LD_LIBRARY_PATH"} or $ENV{"LD_LIBRARY_PATH"} !~ m#/xst/xstlocal/bin/oracleInstantClient/instantclient_10_2#)) { $ENV{"LD_LIBRARY_PATH"}="/xst/xstlocal/bin/oracleInstantClient/instantclient_10_2:...."; $ENV{"MYLIBSET"} = 1; # Just in case someone mangles LD_LIBRARY_PATH in/after exec()
        exec($0,@ARGV);
    }
}
-------------------------------

    It's ugly, but works.

            Bye. Alex.


--
Alexander Foken
mailto:alexan...@foken.de  http://www.foken.de/alexander/

Reply via email to