Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

set env var at compile time

by SantaClaus (Initiate)
on Jun 26, 2008 at 20:46 UTC ( [id://694276]=perlquestion: print w/replies, xml ) Need Help??

SantaClaus has asked for the wisdom of the Perl Monks concerning the following question:

I have a script that uses DBI and DBD::Oracle. My sysadmin had some trouble getting DBD::Oracle to work, and in the end used a LD_LIBRARY_PATH=$ORACLE_HOME hack over which I have no control. The trouble is that DBD::Oracle is now compiled with this, and I can not run my script without setting that env var.

I plan to run the script in cron, and I know I can just do "env LD_LIBRARY_PATH=<path_to_oracle> my_script.pl." It works, I've tested it. We have other scripts that run that way now. But that just seems ugly to me. The script already has many configuration options set in a conf file, and it seems more elegant and consistent to set LD_LIBRARY_PATH in there. My shop also has standard modules for Oracle connections and config files that I'd like to use.

I've tried:

my $config; # scoped to script so I can continue to use it BEGIN { require Our::Config::Module; import Our::Config::Module; $config = new Our::Config::Module('filename') or die "Can't read config file\n"; $ENV{LD_LIBRARY_PATH} = $config->get('lib_path'); } use Our::Oracle::Module;

But this dies at compile time with the usual

"can't load '/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/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/lib/perl5/5.8.5/i386-linux-thread-multi/DynaLoader.pm line 230. at /usr/lib/perl5/site_perl/5.8.5/Our/Oracle/Module.pm line 27 Compilation failed in require at /usr/lib/perl5/site_perl/5.8.5/Our/Oracle/Module.pm line 27."

that I always see when LD_LIBRARY_PATH is not set. So I'm assuming that's not an acceptable way to set env vars before use-ing modules that rely on them.

I strongly prefer to maintain portability by keeping machine specific stuff in a config file that I can modify without making code changes. Remember too that I have actual sysadmins, so I have no control over the Perl installation and don't want to maintain a separate one. With these restrictions, can anyone propose a clean way to set the env var that does not involve hard coding the path, either in the script or in the cron job? Or am I just letting an unaccountable fastidiousness lure me away from a perfectly good solution that I know works?

Replies are listed 'Best First'.
Re: set env var at compile time
by moritz (Cardinal) on Jun 26, 2008 at 21:23 UTC
    I have no idea if this actually works, but you could try this:
    BEGIN { unless($ENV{LD_LIBRARY_PATH}){ $ENV{LD_LIBRARY_PATH} = "whatever"; exec $^X, $0, @ARGV; } }

    This re-executes the current script after setting the environment variable, in the hope that it works then in the same way as it does when you provide it through external environment variables.

    (No idea if this makes a difference at. But there's no harm in trying).

Re: set env var at compile time
by songmaster (Beadle) on Jun 26, 2008 at 21:32 UTC

    I had a similar problem with a shared library in a non-standard location, and found that DynaLoader has its own search path to which I could add the location containing my shared library. You might be able to do something like this (which I don't claim is a complete solution to your question but might be a good starting point):

    require DynaLoader; # Add our lib directory to the library search path push @DynaLoader::dl_library_path, $libdir;

    You should be able to calculate $libdir using your config module as you wanted to.

Re: set env var at compile time
by diotalevi (Canon) on Jun 26, 2008 at 20:55 UTC

    I'm guessing here but I think you have to satisfy ld.so and it reads from the process's C environment which is not updated by updating the perl variable %ENV. I see no problem with having a configuration file somewhere on disk but you'll need to write it in bash (or similar) and just make sure that invoking it is a part of your /etc/profile or how you invoke perl.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      Satisying ld.so makes sense, as does the failure of %ENV to update its environment. I wished for a Perl solution, but I suppose a shell script is better than hard coding the path. It's not really any better than just adding the 'env' to the crontab line, though, so I'll probably just hold my nose and go with that. Thanks for taking the time to respond.

Re: set env var at compile time
by kyle (Abbot) on Jun 26, 2008 at 20:59 UTC

    No offense to Our::Config::Module, but I wonder if LD_LIBRARY_PATH is what you think it is. Have you tried printing it once you set it?

    I wonder also if Our::Config::Module somehow pulls in Our::Oracle::Module (perhaps indirectly) so that you're not really getting the environment set in time for it.

    Are you on Solaris? If so, see Re: %ENV and DBI (setting LD_LIBRARY_PATH inside the process doesn't work).

      Fair calls - I'll check on them. I also wonder if the failure of setting LD_LIBRARY_PATH isn't because of what diotalevi said, which would make it true for any *nix, yes? Meaning that the truth I'm slowly reconciling myself to is that I just can't do this within Perl only. Ah well, I'll live. Thanks.

        I think what diotalevi says is true, but I think there is still a Perl solution. I think the solution moritz gives below would work (using exec). It's very similar to what's in the link in my note above. I say all this without having tried it, of course.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://694276]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-23 06:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found