Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

setting env vars from hash fails for me

by ccarden (Monk)
on Aug 06, 2003 at 22:18 UTC ( [id://281620]=perlquestion: print w/replies, xml ) Need Help??

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

I suspect it's actually working but that my use of system("printenv") to check my settings is incorrect. I've tried system("set") and system("env") with no luck. Suggestions?
my %hash; $hash{APP_DIR} = "/usr/vendor/app/version/"; $hash{TMP_DIR} = "/usr/tmp/"; $hash{PROJ_DIR} = "/usr/people/userid/app/"; $hash{APP_LOCATION} = "/usr/vendor/app/version/bin/"; ... use Env qw(keys %hash); foreach $key (keys %hash) { eval("$key=\"$hash{$key}\""); print " $key=$hash{$key}\n"; } system("printenv");

Replies are listed 'Best First'.
Re: setting env vars from hash fails for me
by chromatic (Archbishop) on Aug 06, 2003 at 22:31 UTC

    Since use happens at compile-time, %hash is empty. That's not really a problem here, since keys %hash is treated as a literal string by qw//. Since you're not importing what you think you're importing, your eval fails. Since you're not checking $@, you don't know this.

    I'd really rather write:

    %ENV{ keys %hash } = values %hash;

    but if you really want to get your way to work, here's a start. I'm not sure if Env returns lvalue subs, though:

    #!/usr/bin/perl -w use strict; my %hash; BEGIN { $hash{APP_DIR} = "/usr/vendor/app/version/"; $hash{TMP_DIR} = "/usr/tmp/"; $hash{PROJ_DIR} = "/usr/people/userid/app/"; $hash{APP_LOCATION} = "/usr/vendor/app/version/bin/"; } use Env (keys %hash); foreach my $key (keys %hash) { eval("$key=\"$hash{$key}\""); print "Eval error '$@'\n" if $@; print " $key=$hash{$key}\n"; } system("printenv");
Re: setting env vars from hash fails for me
by japhy (Canon) on Aug 06, 2003 at 22:32 UTC
    The problem is that use Env ... happens at compile-time, before you've stored anything in the %hash hash. Another problem is your use of qw() -- it literally sends the strings 'keys' and '%hash' to the Env module. But I think you're going about things the wrong way. Why not just place those values in the %ENV hash directly?
    BEGIN { $ENV{APP_DIR} = "/usr/vendor/app/version"; # etc. } system("printenv"); # should have the new keys in it
Re: setting env vars from hash fails for me
by Zaxo (Archbishop) on Aug 06, 2003 at 22:34 UTC

    I suspect you don't want 'keys' and '%hash' to be the two arguments in use Env ...;, but that's what qw() is giving you. Omit the qw and you will get a list of the keys.

    I don't see why you use Env.pm, though. If you do as you are to %hash with the special %ENV hash, all will be well.

    After Compline,
    Zaxo

Re: setting env vars from hash fails for me
by dws (Chancellor) on Aug 06, 2003 at 22:38 UTC
    It appears that you're trying to set environment variables from inside of a script, so that they're visible to some other (or later) process. What you're doing instead is setting script variables, which are invisible outside of the processes memory (i.e., "printenv", which is another process, won't see them).

    What you need to do is explained (very briefly) in perlvar, which explains that fork() will propagate changes to %ENV. So, instead of loading up %hash, change %ENV and then fork. Try forking to "printenv" as a quick test.

      Hmm, the following works for me on two Unix-like boxes (Mac OS X and GNU/Linux):

      use strict; %ENV = ( foo => 'bar '); system( 'printenv' );

      Looking in the code for system, it forks internally, which is what I'd expect. I wouldn't expect this to be very portable outside of Unix, though.

      dws,
      I thought this too and almost replied, but I got distracted. It would be good to point out that while you can change "set" the environment that you fork (child process), you can't export it back to the parent. I was guessing that the OP was trying to do the equivalent of:
      $ perl -e 'cd /tmp' $ pwd /home/user $ echo "WTF?"

      Cheers - L~R

      Update: I can neither confirm nor deny it (without research anyway), but I heard this actually works on VMS. And while you can set the parent to read information from the child and set the parameters itself in the OS's I was originally referring to, the child is not actually doing it.

Re: setting env vars from hash fails for me
by PodMaster (Abbot) on Aug 07, 2003 at 06:06 UTC
    You're abusing eval righ there, don't do it ;)
    use Env qw[ APP_DIR TMP_DIR PROJ_DIR APP_LOCATION ]; $PROJ_DIR = '/usr/people/userid/app/'; $APP_DIR = '/usr/vendor/app/version/'; $APP_LOCATION = '/usr/vendor/app/version/bin/'; $TMP_DIR = '/usr/tmp/'; system 'printenv'; __END__
    The way I see it, Env's only real usefulness is when you're dealing with multi-valued vars, like PATH (you get to treat them like an array). Ex:
    use Env qw[ $PATH @PATH]; print "$PATH\n"; print "$_\n" for @PATH; __END__

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: setting env vars from hash fails for me
by LazerRed (Pilgrim) on Aug 06, 2003 at 22:38 UTC
    Try changing your last "system("printenv")" to:

    foreach my $x ( sort keys %ENV ) { print "$x -- $ENV{$x}\n"; }
    Whip me, Beat me, Make me use Y-ModemG.
Re: setting env vars from hash fails for me
by ccarden (Monk) on Aug 07, 2003 at 15:35 UTC
    Okay, it was a combination of chromatic's and japhy's suggestions which got me working. But it wasn't until I read every response that I understood all of the things that I was doing wrong.

    First, though, chromatic suggested %ENV{ keys %hash } = values %hash; which I tried right away, only to get a syntax error. Not certain what was failing, I went to japhy's suggestion and came up with:

    foreach $key (keys %hash) { $ENV{$key} = $hash{$key}; }
    This works perfectly. But why doesn't chromatic's example work?

    As for all of the other suggestions, they mostly had to do with my clumsy creation of the hash. My example code was significantly simpler than what I'm really doing, and I was trying provide you with a simple hash for testing. It was the use Env qw(keys %hash); that was really the hack, and it turns out that I misread an example somewhere on this site that was meant for multi-valued vars (thanks for the heads-up, PodMaster).

    My real code takes in the hash as a parm using Getopt and then passes it to a sub intended to set the environment vars to their corresponding values in the hash:

    #!/usr/bin/perl use strict; use warnings; use Getopt::Long; my %engEnvVars; GetOptions ( "engEnvVar=s" => \%engEnvVars ) sub setEnvVars { my %engEnvVars = @_; my $key; foreach $key (keys %hash) { $ENV{$key} = $hash{$key}; } system("printenv") if $DEBUG; } setEnvVars(%engEnvVars);
    and then call the script with parms:
    ./testScript.pl -engEnvVar APP_DIR=/usr/vendor/app/version/ -engEnvVar + TMP_DIR=/usr/tmp/
    ... etc.

    Yes, dws was correct in that I am setting these environment variables so that I can call another application.

    I tested chromatic's second example:

    use strict; %ENV = ( foo => 'bar '); system ( 'printenv' );
    ... and found that in that case printenv only prints out the one environment variable and its value. In my main script, printenv prints out not only the vars that I set in my script, but all other environment vars. Curious.

    What a long, arduous path for me. Finding this site and sharing my questions shows me how little I really know about Perl. I appreciate all of your input. Thank you.

    -- ccarden

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://281620]
Approved by Thelonius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (6)
As of 2024-04-25 10:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found