http://www.perlmonks.org?node_id=1013046

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

I have this multi-platform application. it launches children that run for a short period of time.

I need to communicate from parent to child.

so just before launching the child, I do
$ENV{'varname'}='value';

and in the child, I get the environment variable and all is well.

this works on Windows without problem, but the variable does not show up for the linux child. in both cases I am actually starting a command shell script. xxx.cmd on Windows and xxx.sh on linux. the set command dumps the environment, and on linux the variable is not set when xxx.sh is started.

I do not need the value to be persistent, and I understand the reasons and issues there.

one piece of info, the child is started with OPEN so that the parent can monitor the childs console output
if($environmentDetails->GetValue() eq "Yes"){ $ENV{'SKIP_SYSTEM'}='0'; } else{ $ENV{'SKIP_SYSTEM'}='1'; } # have to execute the shell script from the current folder.. # *ix is picky, you must be explicit open(CMD, ( ($^O eq 'MSWin32' ) ? "":"./")."$command 2>&1 |"); while(<CMD>){ $detailsInfo->AppendText($_); }
on perl 5.10, linux fedora 10, 32 bit (can't update for other reasons)

Replies are listed 'Best First'.
Re: passing env{} variable to child fails on linux,works on windows
by RichardK (Parson) on Jan 12, 2013 at 16:11 UTC

    I've just tried this on Fedora 17, 64 bit with perl v5.14 and it works for me, if that helps :)

    Here's the test code I ran.

    use v5.14; $ENV{TEST_FLAG}=1; my $test = `env`; say $test; say 'OK' if $test =~ /TEST_FLAG=/;
Re: passing env{} variable to child fails on linux,works on windows
by flexvault (Monsignor) on Jan 12, 2013 at 16:48 UTC

    Hello sdetweil,

    Since you are testing for MS and treating the problem different for *nix and MS, you may not know about '/dev/shm' which most modern *nix have. If you do a 'df' you'll see if it's there. What this does is allow you to share information between different processes in *nix. It treats memory as a separate filesystem for you to 'open/read/write/close' in memory files without going to disk.

    In my testing, I've found it to be 2 or more times faster than using disk, and it's 'cleaned-up' on re-boot.

    I don't think the method you're using in *nix will work, since there is no relationship between the process created with 'open' and your process. Why it works in MS, someone else will have to explain. If you use 'fork', all variables are copied to the new process, so you can say:

    our $test_switch = 1; ## I recommend using 'our' over 'my' i +n this case ## It signals that it's something to b +e shared
    and it will be available in the new 'fork'ed process.

    Good Luck!

    "Well done is better than well said." - Benjamin Franklin

      >since there is no relationship between the process created with 'open' and your process

      well, there it is then.. its not a 'child' its a peer..

      never a dull moment..

      thanks..

      we have to think on the best way to do this..
        well, there it is then.. its not a 'child' its a peer..
        Flexvault is mistaken. It's a child, and it does inherit environment variables. Here are a couple of linux scripts that demonstrate this. First, /tmp/myenv just prints any environment variables that have 'MY' in the name:
        #!/usr/bin/perl print "$_=>$ENV{$_}\n" for grep /MY/, sort keys %ENV;
        Then the main script, which 'opens' myenv:
        #!/usr/bin/perl $ENV{MYA} = 'a'; $ENV{MYB} = 'b'; $ENV{C} = 'c'; open(CMD, "/tmp/myenv 2>&1 |") or die "open: $!\n"; while (<CMD>) { chomp; print "got: <$_>\n"; }
        Running this gives:
        got: <MYA=>a> got: <MYB=>b>

        Dave.

        sdetweil,

        How about:

        my @results = qx/script.plx -$envparm/;

        You get the results of the script in '@results' and you pass your script the required parameter that it needs.

        Maybe?

        Regards...Ed

        "Well done is better than well said." - Benjamin Franklin