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.

1

6 Answers 6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

This is printing the output of the script. (Not printing the exported data). I am not allowed to change the logon.sh script.
@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.
This is a nice approach, but I would change the example to: my $id = qx( . logon.sh; echo \$ID )
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

Comments

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";
}

Comments

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;

1 Comment

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.
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 ...

Comments

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.