how perl set envirment variable

J

Joe Smith

Ting said:
I want set envirment variable, e.g PATH
with perl, how can I co it?

That's a FAQ.
perldoc -q environment

Note: Win32 acts different than Unix/Linux in regards to this.
-Joe
 
J

Jürgen Exner

Ting said:
I want set envirment variable, e.g PATH
with perl, how can I co it?

Depends on what you want to achive. Please check
- "perldoc perlvar", section about %ENV
- "perldoc -q env"

jue
 
J

J. Romano

Ting Wang said:
I want set envirment variable, e.g PATH
with perl, how can I co it?


Dear Ting Wang,

"perldoc -q environment" says that it's almost impossible, but that
there are a few work-arounds, if you are using Unix.

Here's one work-around (for Unix/Linux) that sets your PATH to
"/usr/bin":


#!/usr/bin/perl -w
use strict;
$ENV{PATH} = "/usr/bin";
exec $ENV{SHELL};
__END__


All I did was set the PATH by setting $ENV{PATH}, and then adding
"exec $ENV{SHELL}" as the last line of the Perl script. That way,
your environment changes will "stick" when the Perl script ends.

What is really happening is that a child process was made (that's
why the environment changes stick) so, for every time you run this
Perl script, you have to type an extra "exit" at the prompt when you
want to leave, unless you run the script with the UNIX "exec" command,
like this:

exec script.pl

Keep in mind that these environment changes aren't permanent. Once
you logout or exit your shell you will have to run your script again
to get your changes back.

I hope this helps,

Jean-Luc
 
J

Jürgen Exner

J. Romano said:
"perldoc -q environment" says that it's almost impossible, but that
there are a few work-arounds, if you are using Unix.

Here's one work-around (for Unix/Linux) that sets your PATH to
"/usr/bin":
#!/usr/bin/perl -w
use strict;
$ENV{PATH} = "/usr/bin";
exec $ENV{SHELL};
__END__

I guess "It works" by some definition of works.
However your approach provides a workaround for only one user scenario, and
a rare scenario for that matter. How often do you really want to open a new
shell? Typically people would rather continue in the given shell.
Not to mention that your approach is utterly useless in batch programming
which is one of the main application areas of Perl.

jue
 
D

Derek Ludwig

Jürgen Exner wrote:
I guess "It works" by some definition of works.

Actually, this shows that you can you can set $ENV{PATH},
and effect subsequent calls to exec, system, etc. If have
had path problems in a batch environment, so I ended up
with the (somewhat cheesy):

use local::Batch::Env;

to set my local environment, including $ENV{PATH}, so
that system does work they way I want. I have to deal
with too many "helpful" people who correct the value
of ${PATH} :-/.
 
A

A. Sinan Unur

(e-mail address removed) (J. Romano) wrote in

....
#!/usr/bin/perl -w
use strict;
$ENV{PATH} = "/usr/bin";
exec $ENV{SHELL};
__END__


All I did was set the PATH by setting $ENV{PATH}, and then adding
"exec $ENV{SHELL}" as the last line of the Perl script. That way,
your environment changes will "stick" when the Perl script ends.

....

Changes will not stick. You have just invoked a new copy of your shell
with a new environment.

Each time you run this script, a new copy of your shell will run.

Why would you want to do that for something that can be handled much for
easily using your shell's facilities?
 
A

Anno Siegel

A. Sinan Unur said:
(e-mail address removed) (J. Romano) wrote in

...


...

Changes will not stick. You have just invoked a new copy of your shell
with a new environment.

Each time you run this script, a new copy of your shell will run.

Why would you want to do that for something that can be handled much for
easily using your shell's facilities?

One of those is the eval function that most shells have. You can say

eval `perl_script`

in your shell and pull in the power of Perl, if needed.

The perl_script must print a bit of shell code which "eval" will
execute, say "PATH = something; export PATH" for a bourne-like shell.
The eval command can also be conserved in an alias for interactive
use.

That is a much better approach than heavy-handedly starting another shell.

Anno
 
J

J. Romano

(e-mail address removed) (J. Romano) wrote in
A. Sinan Unur said:
Changes will not stick. You have just invoked a new copy of your shell
with a new environment.

You're right: Changes will not stick -- to the old shell. But the
old shell is not around anymore, and what's left to work with is a new
shell that's practically identical to the old shell but with the
environment changes you made in the Perl script.

It's kind of like a joke I heard once: A robber broke into a house
and stole all the furniture and appliances -- but he replaced them
with exact copies.

The point of the joke is that if the robber replaced everything
with an exact copy, how is that any different (from the rightful
owner's point of view) from the thief not stealing anything at all to
begin with?

In the same way, you might be concerned that a new copy of your
shell was invoked (replacing the old shell), but if the new shell is
almost identical to the old shell, would that really matter?

As it turns out, it does matter in some matter in some cases.
Jürgen Exner pointed out that Perl is often used in batch programming,
in which case the commands after the call to the Perl script would run
in the parent shell and not have the environment changes. But then,
if the Perl script was invoked with the "exec" command, the commands
after the call to the Perl script wouldn't get run at all (not to
mention, the Perl script's line "exec $ENV{SHELL}" would open up a new
shell, which is not wanted in batch scripting).
Each time you run this script, a new copy of your shell will run.

Why would you want to do that for something that can be handled much for
easily using your shell's facilities?

(I assume you meant "... much *more* easily ...")

I'll give you an example:

Several times during working on Unix systems (both at the
university and at work) I've had to execute a specific shell script in
order to begin a certain task or run a certain program. This shell
script was provided by the professor or a system administrator, and it
would made changes to my environment ensuring me being able to run the
program needed for me to get my work done. (I would have to execute
this shell script once for each terminal window I had open.)

One problem with these scripts was that they would often add paths
to my $PATH environment variable. They would usually add the
"/usr/bin" path as well as a few X11 paths, even though I already had
them in my $PATH. And often these scripts would call other scripts
(which sometimes would call more scripts) that other professors or
system administrators wrote, and each one of these scripts would add
new entires to my $PATH. So after I ran the one script my professor
(or system administrator) required us to run, my $PATH would have
dozens of duplicate paths.

You can argue that you should check to see if a path already exists
before adding it to the $PATH. That's a valid point, but I didn't
write these scripts, nor did I have the permissions to change them.
As Derek Ludwig said:
I have to deal with too many "helpful" people who
correct the value of ${PATH}

This is where the following script comes in handy:

#!/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 I can run:

exec syimplifyPath.pl

and there will be no more duplicates in my path, leaving me free to
work on my task with all the environment changes I wanted (in this
case, the one made to my $PATH).

Could I write a program that does the same thing in another shell
script language? Yes, I could -- and I did. I wrote a "simplifyPath"
script (I think in csh) a few years ago before I knew Perl -- but let
me tell you: it was much more difficult to write it in csh.

But maybe there is an easier way to do this using a non-Perl shell
script. And if there is, I'd like to see it. But since I've had the
exact problem I just stated to you (several times in the past), I'm
inclined to think that posters like Ting Wang have the same problem,
while others are inclined to think that he (or she?) is running Perl
in as part of another script, and that opening an interactive child
shell is unacceptable.

Unfortunately, our friend Ting Wang was rather vague about the
situation (he/she didn't even specify what platform he/she was using),
making it hard to suggest a suitable solution for him/her.

But to say that the solution I proposed is worthless because of
some side effect (that may or may not be an issue to the poster) is to
neglect any Perl programmer looking for a working solution to the same
dilemma I had. Not everyone has a problem with those side-effects, so
it's unreasonable to think that just because some people do, then
everyone does.

I hope this explains things.

-- Jean-Luc
 
J

Jürgen Exner

J. Romano said:
You're right: Changes will not stick -- to the old shell. But the
old shell is not around anymore,

Oh, no. It is still very much around. Check the process table.
and what's left to work with is a new
shell that's practically identical to the old shell but with the
environment changes you made in the Perl script.

Not at all. The new shell has a different process ID (which might screw up
processed, that rely on the process ID to e.g. identify temporary files), it
has a different command history, it may be executing a different shell
script (if any!), if doesn't continue where the old shell script called the
Perl script.
It's kind of like a joke I heard once: A robber broke into a house
and stole all the furniture and appliances -- but he replaced them
with exact copies.

The point of the joke is that if the robber replaced everything
with an exact copy, how is that any different (from the rightful
owner's point of view) from the thief not stealing anything at all to
begin with?

If the robber stole your antic furnitures and replaced them with new copies,
then I guess you would notice the difference, wouldn't you?
In the same way, you might be concerned that a new copy of your
shell was invoked (replacing the old shell), but if the new shell is
almost identical to the old shell, would that really matter?

It does. Very much so.
As it turns out, it does matter in some matter in some cases.
Jürgen Exner pointed out that Perl is often used in batch programming,
in which case the commands after the call to the Perl script would run
in the parent shell and not have the environment changes.

Ok, glad to see that you do understand the shortcomings of your approach.
But then,
if the Perl script was invoked with the "exec" command,

Why would anyone do that? Typically you want a process to call the Perl
script to do some task and then call the next script or program to do the
next task and so on. If you call the sub-scripts using exec() then I
certainly don't want to manage the control flow of that system.
the commands
after the call to the Perl script wouldn't get run at all (not to
mention, the Perl script's line "exec $ENV{SHELL}" would open up a new
shell, which is not wanted in batch scripting).
Several times during working on Unix systems (both at the
university and at work) I've had to execute a specific shell script in
order to begin a certain task or run a certain program. This shell
script was provided by the professor or a system administrator, and it
would made changes to my environment ensuring me being able to run the
program needed for me to get my work done. (I would have to execute
this shell script once for each terminal window I had open.)

One problem with these scripts was that they would often add paths
to my $PATH environment variable. They would usually add the
"/usr/bin" path as well as a few X11 paths, even though I already had
them in my $PATH. And often these scripts would call other scripts
(which sometimes would call more scripts) that other professors or
system administrators wrote, and each one of these scripts would add
new entires to my $PATH. So after I ran the one script my professor
(or system administrator) required us to run, my $PATH would have
dozens of duplicate paths.

So what? What is the problem with that?

[...]
This is where the following script comes in handy:
[Perl script to remove duplicate entries in PATH]
$ENV{PATH} = join ':', @pathList;
exec $ENV{SHELL};

Now I can run:

exec syimplifyPath.pl

If instead of the exec() you would have done a
print 'set path="' . join (':', @pathList) . '"';
and then eval'ed the output of the Perl script in your original shell, then
you would not have needed a new shell with all the nasty side effects.

jue
 
A

A. Sinan Unur

(e-mail address removed) (J. Romano) wrote in
You're right: Changes will not stick -- to the old shell. But the
old shell is not around anymore, and what's left to work with is a new
shell that's practically identical to the old shell but with the
environment changes you made in the Perl script.

It's kind of like a joke I heard once: A robber broke into a house
and stole all the furniture and appliances -- but he replaced them
with exact copies.

The point of the joke is that if the robber replaced everything
with an exact copy, how is that any different (from the rightful
owner's point of view) from the thief not stealing anything at all to
begin with?

The fact that the owner has the right to shoot the robber while he is in
the process.
In the same way, you might be concerned that a new copy of your
shell was invoked (replacing the old shell), but if the new shell is
almost identical to the old shell, would that really matter?

It does not replace the old shell. The old shell is still taking memory
(however virtual it is).
(I assume you meant "... much *more* easily ...")

Yes :)
I'll give you an example:

Several times during working on Unix systems (both at the
university and at work) I've had to execute a specific shell script in
order to begin a certain task or run a certain program.
....

One problem with these scripts was that they would often add paths
to my $PATH environment variable. ....

So after I ran the one script my professor (or system administrator)
required us to run, my $PATH would have dozens of duplicate paths.

The solution to that is to start a new shell, run the scripts and do
whatever your professor asks of you etc, then exit that shell.

Or, screen (http://www.gnu.org/software/screen/) might be useful.

Anyway, this is where we stand and I am going to stop before carrying
this thread any more off-topic than I have done with some others :)
 
J

J. Romano

(e-mail address removed) (J. Romano) wrote in
A. Sinan Unur said:
The solution to that is to start a new shell, run the scripts and do
whatever your professor asks of you etc, then exit that shell.

Ideally, yes, you are correct there. But homework assignments are
sometimes less than ideal, where even running the professor's script
does not perfectly set up the environment required for the student to
complete the assignment. As a result, a lot of perusing through
enviornment variables is needed, and it certainly doesn't help that
the $PATH (and possibly other environment variables) are full of
duplicate entries.

In this case, Perl excels as a debugging tool (even if used
temporarily) in the ability to set and modify environment variables.
Perl might be used to set environment variables only in a few rare
cases, but that certainly beats the frustration caused by not turning
in your homework assignment just because you (or your professor)
couldn't get the program to work on your account.

And the problem might not even ultimately lie with the environment
settings, but any help that Perl can afford me is sure welcome.

I know that what I just said might sound silly to some people, but
until you've been in that situation yourself, it's hard to gain an
appreciation for it.

-- Jean-Luc
 
J

J. Romano

Jürgen Exner said:
Ok, glad to see that you do understand the shortcomings of your approach.


Why would anyone do that? Typically you want a process to call the Perl
script to do some task and then call the next script or program to do the
next task and so on. If you call the sub-scripts using exec() then I
certainly don't want to manage the control flow of that system.

Why would anyone do that? Here's why: Although it may be
"typical" (as you claim) for a Perl script to be called from a process
to do some task and then have the process call the next script or
program to do the next task and so on, sometimes a user wants to use a
Perl script straight from a Unix shell prompt, as "atypical" as that
may sound.

To be honest, it's typical for me to run a Perl script straight
from the command line. That many not be typical for you, but it is
for me, and possibly for many other Perl programmers as well.

There's nothing wrong with a Perl script being called from a batch
script; there's also nothing wrong with a Perl script not being called
from a batch script. It might be a rare case, but it does happen, and
that's why someone might want to invoke a Perl script with the "exec"
command.

I hope this answers your question.

-- J.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top