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

Hi all,

I'm trying to set the LD_LIBRARY_PATH within my script, because the account that will run the script won't have the environment setup correctly.

#!/sw/perl5.6/bin/perl -I. -w use strict; use Env qw(@LD_LIBRARY_PATH); BEGIN { push @LD_LIBRARY_PATH, "/usr/local/sybase/lib"; } use Sybase::DBlib;
This does not work and I receive an error that perl cannot load the library. It's the right path - if I set my environment's LD_LIBRARY_PATH to that, the script doesnt complain. Running on SunOS 5.7...

Thanks folks

Replies are listed 'Best First'.
(tye)Re: programatically setting the LD_LIBRARY_PATH
by tye (Sage) on Nov 20, 2001 at 23:13 UTC

    Note that doing a Super Search for articles that mention LD_LIBRARY_PATH might have gotten you enough information to get past this problem. I didn't find the answer neatly wrapped up (but I only looked at a couple of the hits), though, so here is one...

    You likely can't set LD_LIBRARY_PATH from within the running process no matter how early you do it as the linker/loader has already started loading the process and has cached the value of LD_LIBRARY_PATH. Previously I've work around this by execing the perl executable so that it must reload and will see the new LD_LIBRARY_PATH that I have set. On some operating systems, even that isn't enough as the linker/loader notices that we are execing the same executable and doesn't bother to reinitialize. For such cases, you have to exec a different executable and ask it to exec perl for you.

    Something close to the following should work:

    BEGIN { my $need= '/usr/local/sybase/lib'; my $ld= $ENV{LD_LIBRARY_PATH}; if( ! $ld ) { $ENV{LD_LIBRARY_PATH}= $need; } elsif( $ld !~ m#(^|:)\Q$need\E(:|$)# ) { $ENV{LD_LIBRARY_PATH} .= ':' . $need; } else { $need= ""; } if( $need ) { exec 'env', $^X, $0, @ARGV; } }

            - tye (but my friends call me "Tye")

      This is an old thread, but I've often had reason to refer back to it. Hopefully someone will also find the following useful.

      Tye's solution works perfectly. It seems to be the best solution for cron jobs on a server with a diverse environment. The only problem is the the BEGIN block sort of breaks the use of perl -c and perl -d. If I understand correctly, it's because those options sort of wrap the existing code in code that will just compile or debug the existing code.

      The following works, but only if the environment variables don't need to be set before the modules are loaded. Naturally, on a Windows system you will need to find an alternative method of determining an interactive shell...

      my $interactive = TRUE if ( ! system( 'tty -s' ) / 256 ); unless ($interactive) { unless ( $ENV{BEGIN_BLOCK} ) { $ENV{"ORACLE_HOME"} = '/opt/oracle/product/9.2.0'; $ENV{"LD_LIBRARY_PATH"} = '/opt/oracle/product/9.2.0/lib'; $ENV{BEGIN_BLOCK} = 1; exec 'env',$0,@ARGV; } }

      Credit for this goes to one of my (non-perlmonk) co-workers. I'm just taking the credit :D I've been using a variation of Tye's code until now.

      -- GhodMode
        If you're doing this because a Perl module has a dependency on a native library (e.g. XML::LibXML), and you need to load the library from a non-default path (e.g. you have a version of libxml2 not in /lib or /usr/lib) and you want to avoid modifying LD_LIBRARY_PATH in a wrapper script or some kind of pseudo-wrapper like that shown above, there is another alternative. In the .bs file for the module, place a call to dl_load_file passing the absolute name of the native library. I used an environment variable to store my custom library path:
        # Need to find libxml2. Cannot set LD_LIBRARY_PATH as it is already # cached by the linker. So we load libxml2 BEFORE loading # XML::LibXML's library. dl_load_file($ENV{FOO_PATH} . '/lib/os/');

      Here's a "something close" for cases where you need multiple elements in your path.

      BEGIN { my $dir; my $needed_path = 0; my @need = ( "/usr/local/lib", "/usr/platform/SUNW,Ultra-80/lib", "/usr/lib" ); my $ld_path = $ENV{LD_LIBRARY_PATH}; if( ! $ld_path ) { $ENV{LD_LIBRARY_PATH} = join ":", @need; exec 'env', $^X, $0, @ARGV; } foreach $dir (@need) { if ( $ld_path !~ m/(^|:)\Q$dir\E(:|$)/ ) { $ENV{LD_LIBRARY_PATH} .= ':' . $dir; $needed_path = 1; } } if($needed_path) { exec 'env', $^X, $0, @ARGV; } }
      Be Appropriate && Follow Your Curiosity
      Thanks for explaining that one.
      I was going nuts.

      The super seach came back with a bunch of different ways to handle the prob too. I'm hooked.
      What if your Perl program uses system to call an executable program, which is the one that needs the library? Will setting LD_LIBRARY_PATH in the Perl code work then?
        Did you try it? Anyway, the answer should be yes. I have a few functions that go something like:
        sub exec_something { local $ENV{LD_LIBARY_PATH} = "...."; system some_command => @args; }
Re: programatically setting the LD_LIBRARY_PATH
by VSarkiss (Monsignor) on Nov 20, 2001 at 22:51 UTC

    Well, Env ties scalars, not arrays. Your code should look like:

    use Env qw(LD_LIBRARY_PATH); # no sigil here BEGIN { $LD_LIBRARY_PATH .= ":/usr/local/sybase/lib"; }
    I'm not sure a BEGIN block is necessary here, but if it works for you....


Re: programatically setting the LD_LIBRARY_PATH
by mpeppler (Vicar) on Nov 21, 2001 at 00:23 UTC
    tye gives a good writeup on LD_LIBRARY_PATH issues.
    Me I'd suggest that you try to set the environment correctly for this user before this (and other) scripts run. This can be done for cron jobs and other automated situations.


Re: programatically setting the LD_LIBRARY_PATH
by aveckey (Novice) on Aug 30, 2019 at 20:49 UTC
    You can use the shebang to set the environment variables you want:
    #! /bin/sh -- #! -*- perl -*- eval 'exec env LD_LIBRARY_PATH="/path/to/lib:$LD_LIBRARY_PATH" \ XML_SIMPLE_PREFERRED_PARSER=XML::Parser \ PATH="/path1:/path2:/path3:$PATH" \ perl -x $0 ${1+"$@"}' if (0);