Setting environment variables from a Perl script

Discussion in 'Perl Misc' started by J. Romano, Jun 29, 2004.

  1. J. Romano

    J. Romano Guest

    Dear Perl community,

    In the past I have tried to find an answer to the question of how
    to set environment variables in Perl scripts and make them last even
    after the Perl script has finished. I eventually found the response
    mentioned in "perldoc -q environment", which basically says that it
    can't be done (although there are work-arounds if you're willing to
    use a few Unix tricks).

    However, I just recently discovered an easy way to do it. It works
    like a charm in Unix. (But unfortunately, it doesn't work so great on
    Win32.)

    Basically, you write your script as normal, setting environment
    variables, changing them, deleting them, and even changing
    directories:

    $ENV{EDITOR} = "/usr/bin/vi"; # make vi default editor
    $ENV{PATH} .= ":/usr/bin/games"; # add games dir to path
    delete $ENV{PAGER}; # remove the pager environment variable
    chdir($ENV{HOME} . "/bin") or warn $!; # change to my bin dir

    But at the end of the script, add this line:

    exec $ENV{SHELL};

    Run your script, and voila'! The environment variable changes stick!

    I've found it's best to run your script with "exec" in front of it,
    like so:

    exec perl script.pl

    otherwise, you'll have to type an extra "exit" for every time you run
    the script in order to fully exit the shell.

    Of course, this script assumes that your SHELL environment variable
    exists and that it's set to your current shell.

    In DOS using ActiveState Perl, I've found that changing:

    exec $ENV{SHELL};

    to:

    system 'cmd';

    works better than changing it to:

    exec 'cmd';

    (I have a hunch that ActivePerl implements the exec() call by
    replacing it with system() and exit(), but I don't know for sure...)

    As far as I know, in DOS you can't run the exec command, so you'll
    have to type an extra "exit" to close down the DOS terminal window.
    And deleting an evironment variable doesn't seem to work, either (at
    least, not when I tried it). No error is generated; it just doesn't
    appear to work.

    So this approach doesn't fare so well in Win32 DOS, but it looks to
    me that it works great in Unix. This goes against what the perldoc
    says, so if anybody knows a caveat about using this technique (on
    Unix) that I don't see, please speak up. But if there are no
    problems, then I would think that this popular dilemma has been
    solved.

    Happy Perling!

    -- Jean-Luc
     
    J. Romano, Jun 29, 2004
    #1
    1. Advertising

  2. (J. Romano) wrote in
    news::

    > Dear Perl community,
    >
    > In the past I have tried to find an answer to the question of how
    > to set environment variables in Perl scripts and make them last even
    > after the Perl script has finished. I eventually found the response
    > mentioned in "perldoc -q environment", which basically says that it
    > can't be done (although there are work-arounds if you're willing to
    > use a few Unix tricks).


    ....

    > But at the end of the script, add this line:
    >
    > exec $ENV{SHELL};
    >
    > Run your script, and voila'! The environment variable changes stick!


    ....

    > This goes against what the perldoc says, so if anybody knows a
    > caveat about using this technique (on Unix) that I don't see,
    > please speak up. But if there are no problems, then I would
    > think that this popular dilemma has been solved.
    >
    > Happy Perling!
    >
    > -- Jean-Luc


    Jean-Luc:

    This complete and utter nonsense: You have not changed the environment
    variables in the shell from which you started your program. Instead, you
    started a new shell with a new environment. That may be what you want but
    then it very well may not be. The answer to the FAQ stands.


    --
    A. Sinan Unur
    (reverse each component for email address)
     
    A. Sinan Unur, Jun 29, 2004
    #2
    1. Advertising

  3. J. Romano

    J. Romano Guest

    > (J. Romano) wrote in
    > news::
    >
    > > Dear Perl community,
    > >
    > > In the past I have tried to find an answer to the question of how
    > > to set environment variables in Perl scripts and make them last even
    > > after the Perl script has finished. I eventually found the response
    > > mentioned in "perldoc -q environment", which basically says that it
    > > can't be done (although there are work-arounds if you're willing to
    > > use a few Unix tricks).

    >
    > ...
    >
    > > But at the end of the script, add this line:
    > >
    > > exec $ENV{SHELL};
    > >
    > > Run your script, and voila'! The environment variable changes stick!


    "A. Sinan Unur" <> replied in message
    news:<Xns9516EC0B3A600asu1cornelledu@132.236.56.8>...
    >
    > This complete and utter nonsense: You have not changed the environment
    > variables in the shell from which you started your program. Instead, you
    > started a new shell with a new environment. That may be what you want but
    > then it very well may not be. The answer to the FAQ stands.



    Be careful what you call "complete and utter nonsense": The
    perldoc explicitly says that "there is shell magic that may allow you
    to fake it by eval()ing the script's output in your shell." That
    solution probably suffers the same faults my solution has.
    Nevertheless, it made it into the perldocs. (And if it doesn't happen
    to have the same faults that render my own findings "complete and
    utter nonsense", I'd be happy to see that solution.)

    Of course, the changes made by my solution aren't permanent (in
    that, once you exit your shell and restart it, the changes made by the
    Perl script are no longer there), but there are times when a user
    needs to set up the ideal environment in which to begin work on a
    specific task (I've done it several times myself), but doesn't want
    those environment changes to be permanent.

    That scenario is what leads many Perl users to ask the question, "I
    know how to change environment variables in Perl, but how do I made
    them outlast my Perl program?" Mine is one such solution that doesn't
    require "...shell magic that may allow you to fake it by eval()ing the
    script's output in your shell." Not that there's anything wrong with
    that; I just offer a different solution.

    -- Jean-Luc
     
    J. Romano, Jun 29, 2004
    #3
  4. J. Romano

    Keith Keller Guest

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    On 2004-06-29, J. Romano <> wrote:

    > Of course, the changes made by my solution aren't permanent (in
    > that, once you exit your shell and restart it, the changes made by the
    > Perl script are no longer there), but there are times when a user
    > needs to set up the ideal environment in which to begin work on a
    > specific task (I've done it several times myself), but doesn't want
    > those environment changes to be permanent.


    Don't you think it's a bit overkill to use a Perl script to set
    shell environment variables? Why not (for example) write a bash
    script that accomplishes the same task?

    - --keith

    - --
    -francisco.ca.us
    (try just my userid to email me)
    AOLSFAQ=http://wombat.san-francisco.ca.us/cgi-bin/fom

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.3 (GNU/Linux)

    iD8DBQFA4YZ5hVcNCxZ5ID8RAtubAKCVvzdTr2DBNYgkXI8ppGE5Cx+C3QCfXanq
    j/xx/NsHf+etsB8ltzdF9pI=
    =nqs1
    -----END PGP SIGNATURE-----
     
    Keith Keller, Jun 29, 2004
    #4
  5. J. Romano

    J. Romano Guest

    > On 2004-06-29, J. Romano <> wrote:
    >
    > > Of course, the changes made by my solution aren't permanent (in
    > > that, once you exit your shell and restart it, the changes made by the
    > > Perl script are no longer there), but there are times when a user
    > > needs to set up the ideal environment in which to begin work on a
    > > specific task (I've done it several times myself), but doesn't want
    > > those environment changes to be permanent.


    Keith Keller <-francisco.ca.us> responded in
    message news:<-francisco.ca.us>...
    >
    > Don't you think it's a bit overkill to use a Perl script to set
    > shell environment variables?


    That's a good question. I'll begin by saying that I used to write
    shell scripts to do just that before I took the time to learn Perl. I
    was able to write fairly elaborate scripts, but it was very
    frustrating at times: between bash, csh, and ksh, I couldn't always
    keep all the dialectual differences straight to the point that I had
    trouble remembering how to do a simple loop or even a simple
    assignment. In some cases, the shell language I started with lacked a
    feature that another shell had, so I had to re-write my script from
    scratch using the other shell language.

    That's one of the reasons I liked Perl so much when I started
    learning it. It had a superset of the shells' features in a syntax
    that made sense to a C programmer.

    > Why not (for example) write a bash script that accomplishes
    > the same task?


    Because the Perl script is much easier to write and understand.
    I'll give you an example:

    Back when I was a student in college, as part of our homework
    assignments, we had to run a specific program the Unix machines. Many
    times these programs required that certain environment variables were
    set and, as a result, the instructors very often provided us with a
    file for us to "source", like with the following command:

    source cs400

    That would set our environment variables (and maybe even change our
    working directories). One of the environment variables that always
    got modified was $PATH. As a result, my $PATH became super-huge, and
    many of its entries were duplicates, making it difficult to
    troubleshoot Unix problems as the $PATH was very convoluted.

    I did not know Perl at the time, so I used csh to write myself a
    script to simplify my $PATH. It worked, but it was not easy. Once I
    had written the script, I could run a line like:

    source simplifyPath

    and duplicates would automatically be removed from my $PATH.

    I don't remember how I wrote it, but I do remember that it was more
    than five lines of code. And here's where Perl comes in: With this
    Perl script that is effectively four lines long, I achieve the same
    effect:


    #!/usr/bin/perl -w
    # File: simplifyPath.pl
    use strict;
    my %seen; # store paths already seen

    my @pathList = split /:/, $ENV{PATH};
    @pathList = grep { ! $seen{$_}++ } @pathList;
    $ENV{PATH} = join ':', @pathList;

    exec $ENV{SHELL};
    __END__


    Now, instead of typing "source simplifyPath", I type:

    exec simplifyPath.pl

    and I get a new $PATH that has all the duplicate paths removed.

    Could I have done it with a bash script? Definitely. Like I said,
    I've done it before with csh, but setting my environment variables and
    my current directory with Perl gives me all the power of the Perl
    programming language.

    And this "Perl power" is why, periodically, we get users asking how
    to use Perl to set environment variables that outlast the Perl script.
    Unfortunately, most of them receive the answer that "it can't be
    done." And that's the reason behind my posts -- to show that it CAN
    be done.

    I hope this answers your questions, Keith.

    -- Jean-Luc
     
    J. Romano, Jun 30, 2004
    #5
  6. J. Romano <> wrote:
    > So this approach doesn't fare so well in Win32 DOS, but it looks to
    > me that it works great in Unix. This goes against what the perldoc
    > says, so if anybody knows a caveat about using this technique (on
    > Unix) that I don't see, please speak up. But if there are no
    > problems, then I would think that this popular dilemma has been
    > solved.


    This isn't the same shell, but a new one. As a result, any shell
    variables you may have set in the session will be lost.

    $ BAR="bar bar"
    $ echo "$FOO - $BAR"
    - bar bar
    $ exec /tmp/perl
    execing /usr/bin/bash
    $ echo "$FOO - $BAR"
    foo foo -
    $

    Depending on your shell, you may lose history (although many will use a
    ..history file which will maintain state). You'd certainly lose any
    connections to associated jobs.

    $ sleep 500 &
    [1] 2255
    $ jobs
    [1]+ Running sleep 500 &
    $ exec /tmp/perl
    execing /usr/bin/bash
    $ jobs
    $

    I wouldn't call the issue "solved" by this technique. It's another
    option.

    --
    Darren Dunham
    Senior Technical Consultant TAOS http://www.taos.com/
    Got some Dr Pepper? San Francisco, CA bay area
    < This line left intentionally blank to confuse you. >
     
    Darren Dunham, Jul 7, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dpackwood
    Replies:
    3
    Views:
    1,811
  2. Rick Kasten

    Setting Environment Variables

    Rick Kasten, Jul 7, 2004, in forum: Perl
    Replies:
    2
    Views:
    598
    Howard
    Jul 7, 2004
  3. =?Utf-8?B?YnNmbDQ0?=
    Replies:
    0
    Views:
    488
    =?Utf-8?B?YnNmbDQ0?=
    May 12, 2004
  4. Replies:
    5
    Views:
    660
  5. powah
    Replies:
    7
    Views:
    478
    kun niu
    Apr 23, 2009
Loading...

Share This Page