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

Hello fellow brothers !

I need to change in my script an environment variable, so I used:
$ENV{VAR} = $newValue;
the thing is that I need to execute a C program using system() and I need it to recognize the environment variable I defined above. as for now, it doesn't recognize it, probably because system() opens a new shell.
Is there a way to export the variable using perl (and not using system('export ..')) ?

Hotshot

Replies are listed 'Best First'.
Re: environment variable
by grinder (Bishop) on Dec 27, 2001 at 21:24 UTC
    I don't think you are having a problem with environment inheritance, you must be having a problem with something else. Consider

    #include <stdlib.h> #include <stdio.h> int main( int argc, char **argv ) { char *arg = *++argv; printf( "%s is %s\n", arg, getenv(arg) ); exit(0); }

    which is named env-echo.c, which you should compile with cc -o env-echo env-echo.c. You can then use this script:

    #! /usr/bin/perl -w use strict; my $var = shift || 'FOO'; my $value = shift || 'bar'; $ENV{$var} = $value; system "./env-echo $var";
    And if I run that as ./env-change HOME /tmp the child process prints out HOME is /tmp. What does this code do when you run it on your system?

    --
    g r i n d e r
    just another bofh

    print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u';
Re: environment variable
by dmmiller2k (Chaplain) on Dec 27, 2001 at 21:14 UTC

    Setting it in the current processes' environment should be enough, since any subprocesses inherit their parent's environment.

    Although system() does, in fact open a new shell, that shell should inherit your perl script's environment like any other child process (and pass it on to its children).

    Update: reasons why this may not be working:

    • What shell are you using? bash, for instance, executes .bashrc everytime it starts a subshell (same as .csh does with .cshrc, .tcsh does with .tcshrc, etc.). Are you inadvertantly overwriting your desired environment variable(s) in some startup script?
    • The SYBASE variable (and the like) is special, particularly when you are trying to use DBD::Sybase with DBI. You cannot set $ENV{SYBASE} (even in a BEGIN block) and expect DBD::Sybase/DBI to work. (on closer re-read, I realize this iss not your problem)
    • There is probably another one, but I cannot at the moment think of it.

    dmm

      The SYBASE env. variable is special...

      Actually, that's not the case. It's the LD_LIBRARY_PATH variable that needs to be set outside of the running process for it to have any effect.

      The SYBASE env. variable can be set normally when using DBI/DBD::Sybase - it needs to be set before DBD::Sybase gets loaded, but as that only happens on the first DBI->connect() there is no need to use a BEGIN block.

      Michael

        Right you are! I stand corrected. Thanks, mpeppler. Good catch.

        You would think with all of the times this particular thing has bitten me in the behind, I'd remember the difference between SYBASE and LD_LIBRARY_PATH. In my own defense, the environment where this was a problem bundled these two things together in one script for changing between production and development.

        dmm

        You can give a man a fish and feed him for a day ...
        Or, you can
        teach him to fish and feed him for a lifetime
Re: environment variable
by maverick (Curate) on Dec 27, 2001 at 21:22 UTC
    I fear this may be a OS dependant thing. That it may work as expected on some systems, and not others. What OS are you trying this on?

    /\/\averick
    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

Re: environment variable
by hotshot (Prior) on Dec 27, 2001 at 21:51 UTC
    thank guys for your answers. a few things to clarify:
    1. I'm running on Linux 7.1
    2. I'm trying to update the variable LD_LIBRARY_PATH.
    3. I'm using bash.
    4. and another thing, the C program doesn't even load if it doesn't have this var.

    I even tried eventually just for the test, to export LD_LIBRARY_PATH using backticks, like this:
    `export LD_LIBRARY_PATH=/usr/local/lib`
    And it still doesn't work. if I do that from the shell prompt, and execute the C program from there too, it works.
    Any Ideas?

    Hotshot
      7.1 as in RedHat 7.1? system() should inherit your %ENV variables as said before. But if your C program requires that you input something and get something out of it then it might be more appropriate to use IPC::Open3.
      use strict; use IPC::Open3; $ENV{'LD_LIBRARY_PATH'} = '/usr/local/lib'; $COMMAND = '/some/c/proggie -w -options'; my ($read,$write,$error); my $pid = open3($read,$write,$error,$COMMAND); if ($pid) { # do stuff } else { # croak, bitch and complain }


      BMaximus
Re (tilly) 1: environment variable
by tilly (Archbishop) on Jan 05, 2002 at 08:14 UTC
    An obvious guess that everyone seems to have missed.

    Are you by any chance calling the Perl program from within a shell script and then hoping to change the environment variable?

    If so then you are SoL. As Perl is a subprocess it cannot set its parent environment. You need to use export since export is a shell builtin and not a subprocess. The closest that you can come is something like this:

    export foo=`perl script.pl`
    In that case whatever the script prints will be inserted into the commandline and can therefore be used to set the environment of the shell.
Re: environment variable
by hotshot (Prior) on Dec 27, 2001 at 21:47 UTC
    thank guys for your answers. a few things to clarify:
    1. I'm running on Linux 7.1 2. I'm trying to update the variable LD_LIBRARY_PATH. 3. I'm using bash.
    I even tried eventually just for the test, to export LD_LIBRARY_PATH using backticks, like this:
    `export LD_LIBRARY_PATH=/usr/local/lib`
    And it still doesn't work. if I do that from the shell prompt, and execute the C program from there too, it works.
    Any Ideas?

    Hotshot
Re: environment variable
by vek (Prior) on Dec 27, 2001 at 21:20 UTC
    Ditto dmmiller2k - are you sure you're setting $newValue correctly?