1

Perl Code

`. /home/chronicles/logon.sh `; 

print "DATA  : $ENV{ID}\n";

In logon.sh , we are exporting the variable "ID" (sourcing of shell script).

Manual run

$> . /home/chronicles/logon.sh
$> echo $LOG

While I am running in terminal manually (not from script). I am getting the output. (But not working from the script)

I followed this post :

How to export a shell variable within a Perl script?

But didnt solve the problem.

Note

I am not allowed to change "logon.sh" script.

Community
  • 1
  • 1
Debaditya
  • 2,419
  • 1
  • 27
  • 46

6 Answers6

2

The script inside the backticks is executed in a child process. While environment variables are inherited from parent processes, the parent can't access the environment of child processes.

However, you could return the contents of the child environment variable and put it into a Perl variable like

use strict; use warnings; use feature 'say';
my $var = `ID=42; echo \$ID`;
chomp $var;
say "DATA: $var";

output:

DATA: 42

Here an example shell session:

$ cat test_script
echo foo
export test_var=42
$ perl -E'my $cmd = q(test_var=0; . test_script >/dev/null; echo $test_var); my $var = qx($cmd); chomp $var; say "DATA: $var"'
DATA: 42

The normal output is redirected into /dev/null, so only the echo $test_var shows.

amon
  • 57,091
  • 2
  • 89
  • 149
  • This is printing the output of the script. (Not printing the exported data). I am not allowed to change the logon.sh script. – Debaditya Dec 28 '12 at 14:42
  • @Chronicles Then just silence the script — you aren't using the output anyway. See my update for that. If you do need the output, redirect it to a file instead and read from there. – amon Dec 28 '12 at 15:04
  • This is a nice approach, but I would change the example to: `my $id = qx( . logon.sh; echo \$ID )` – William Pursell Dec 28 '12 at 16:25
1

It won't work.

An environment variable can't be inherited from a child process.

The environment variable can be updated in your "manual run" is because it's in the same "bash" process.

Source command is just to run every command in login.sh under current shell.

More info you can refer to: can we source a shell script in perl script

Community
  • 1
  • 1
melvinto
  • 369
  • 2
  • 4
1

Well, I've find a solution, that sound nice for me: This seem robust, as this use widely tested mechanism to bind shell environment to perl (running perl) and robust library to export them in a perl variable syntax for re-injecting in root perl session.

The line export COLOR tty was usefull to ask my bash to export newer variables... This seem work fine.

#!/usr/bin/perl -w

my $perldumpenv='perl -MData::Dumper -e '."'".
    '\$Data::Dumper::Terse=1;print Dumper(\%ENV);'."'";

eval '%ENV=('.$1.')' if `bash -c "
        . ./home/chronicles/logon.sh;
        export COLOR tty ID;
        $perldumpenv"`
    =~ /^\s*\{(.*)\}\s*$/mxs;

# map { printf "%-30s::%s\n",$_,$ENV{$_} } keys %ENV;
printf "%s\n", $ENV{'ID'};

Anyway, if you don't have access to logon.sh, you have to trust it before running such a solution.

Old...

There is my first post... for history purpose, don't look further.

The only way is to parse result command, while asking command to dump environ:

my @lines=split("\n",`. /home/chronicles/logon.sh;set`);

map { $ENV{$1}=$2 if /^([^ =])=(.*)$/; } @lines;
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • Nitpick: Your code is equivalent to ``print `. /home/chronicles/logon.sh;set`;``. In list context, the backtick operator returns a list of output lines. Also, it is unidiomatic to use `map` in void context. `say for @lines` or `print "$_\n" for @lines` would accomplish the same thing. – amon Dec 28 '12 at 15:14
1

You could do something like:

#/usr/bin/perl

use strict;
use warnings;

chomp(my @values = `. myscript.sh; env`);

foreach my $value (@values) {
    my ($k, $v) = split /=/, $value;
    $ENV{$k} = $v;
}

foreach my $key (keys %ENV) {
    print "$key => $ENV{$key}\n";
}
Giuliani Sanches
  • 650
  • 5
  • 20
1

This can now be done with the Env::Modify module

use Env::Modify 'source';
source("/home/chronicles/logon.sh");
... environment setup in logon.sh is now available to Perl ...
mob
  • 117,087
  • 18
  • 149
  • 283
0

Your Perl process is the parent of the shell process, so it won't inherit environment variables from it. Inheritance works the other way, from parent to child.

But when you run the script with backticks, as shown, the standard output of the script is returned to the Perl script. So, either modify the shell script to end with the echo $LOG statement you show, or create a new shell script that runs the login.sh and then has echo $LOG. Your Perl script would then be:

my $value = `./myscript.sh`;
print $value;
Charles Engelke
  • 5,569
  • 1
  • 29
  • 26