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

PerlIsFun

For some reason, we have to use perl script to setup unix enviroment variables, for example: JAVA_HOME=/path/here or run certain setEnv.sh script on current shell. We did try following methods. They all failed.

1. $rv = `export JAVA_HOME=/path/here`;

2. system(". setEnv.sh");

Syntax is right. But when script is done, environment variables did not set. I think both methods above fork another shell to finish the job. Actually i want it to run on current shell. Is that possible? thanks,

Replies are listed 'Best First'.
Re: UNIX environment setup via perl
by mojotoad (Monsignor) on May 07, 2004 at 15:07 UTC
    You're not going to be able do this merely by running the script.

    In order to efffect changes in your current shell environment, you will have to eval the output of your perl script, which should be valid shell syntax.

    So, for example, with a script like this (called bubba.pl):

    #!/usr/bin/perl print "export BUBBA=gump\n";

    You could set the environment in your bash-like shell like this:

    $ echo $BUBBA $ eval `bubba.pl` $ echo $BUBBA gump

    The other option is to write the shell commands into a temporary file, then '.' execute that temporary file in your current script/environment.

    Hope that helps,
    Matt

Re: UNIX environment setup via perl
by haoess (Curate) on May 07, 2004 at 14:39 UTC

    Yes, your child processes can't put their environment to their parents. What about

    $ENV{JAVA_HOME} = '/your/path';

    -- Frank

      PerlIsFun

      This is not what we want. We actually want that environment variable is set after perl script is done/finished.
        This is not possible. Child processes cannot change the environment of its parents. In this case, the perl script cannot alter the environment in the calling shell. You have to use "source" or "." with a shell script instead. Another way is to use the shell-builtin "eval" to evaluate the output of the script. Look at /usr/X11R6/bin/resize for an idea how to use this.

        You can't manipulate environment variables for your parent processes. Why? It's a security concern.

        But: Your shell can use the output of your perl programm to set it's own environment:

        # perl -lw print "export FOO=bar"; # assuming bourne-compatible shell

        Later in your (parent) shell:

        $ eval `your_perl_script.pl` $ echo $FOO bar $

        -- Frank

Re: UNIX environment setup via perl
by Fletch (Bishop) on May 07, 2004 at 15:18 UTC

    See also the canonical answer in perldoc -q "my environment'.

Re: UNIX environment setup via perl
by herveus (Prior) on May 07, 2004 at 15:18 UTC
    Howdy!

    #!/usr/bin/perl $ENV{JAVA_HOME}='/path/here'; # set other items in %ENV as appropriate exec '/usr/bin/ksh';

    %ENV is your environment. Changes you make in it will be propagated to child processes. When you then exec the new shell, the changed environment carries over.

    If you need to process a shell script to set variables, don't try to parse the script. Do something like:

    foreach (`. $profile; env`) { chomp; next unless /=/; my ($var, $value) = split(/=/, $_, 2); $ENV{$var} = $value; }

    This will execute the script and dump the environment in a straightforward format that you can parse.

    yours,
    Michael
      Thank you very much for your support. Really apprecaite all of you. I just could not believe perl could not do this easily.
      PerlIsFun

        It isn't a question of Perl being capable or not capable of altering the shell in which it runs. Rather, all shells prevent the scripts and programs they run from altering their environment, to prevent security risks.

        --
        TTTATCGGTCGTTATATAGATGTTTGCA

Re: UNIX environment setup via perl
by eserte (Deacon) on May 07, 2004 at 15:45 UTC
    To all monks who proposed the "export ..." and "eval ..." way: do not forget the csh and tcsh users! You should check for $ENV{SHELL} and emit "setenv VAR VALUE" lines if appropriate.
      > You should check for $ENV{SHELL} and emit "setenv VAR VALUE"
      > lines if appropriate.

      $ENV{SHELL} is not a way to determine your current shell. $ENV{SHELL} is your »preferred shell« (aka login shell in /etc/passwd), see The Single UNIX Specification, Version 3.

      Example:

      # we are in bash, all is fine $ eval `perl -le 'print $ENV{SHELL} =~ /csh/ ? "setenv FOO bar" : "exp +ort FOO=bar"'` # now we switch to tcsh $ tcsh $ eval `perl -le 'print $ENV{SHELL} =~ /csh/ ? "setenv FOO bar" : "exp +ort FOO=bar"'` $ export: Command not found. $ echo $SHELL /bin/bash

      It seems that there is no portable way to find out the name of your current shell. We discussed that some time ago at de.comp.os.unix.shell.

        Looking at $ENV{SHELL} is probably the best we can do --- other programs seem to do it the same way (and therefore do it wrong):
        $ env SHELL=/bin/sh ssh-agent SSH_AUTH_SOCK=/tmp/ssh-XXN54U4g/agent.3950; export SSH_AUTH_SOCK; SSH_AGENT_PID=3951; export SSH_AGENT_PID; echo Agent pid 3951;
        $ env SHELL=/bin/tcsh ssh-agent setenv SSH_AUTH_SOCK /tmp/ssh-XXPC7hgb/agent.3948; setenv SSH_AGENT_PID 3949; echo Agent pid 3949;
        Similar output for /usr/X11/bin/resize