Dinesh
Dinesh

Reputation: 1868

Perl set and get env in different bash script

I have created a perl script which invokes two bash script. First script will set a envirnomental variable and the second will echo the environmental variable. I have given the contents of the files bellow

# perlscript.pl

print `. setnameenv.sh`;
print `. getnameenv.sh`;

# setnameenv.sh

export my_msg='hello world!'

# getnameenv.sh

echo $my_msg

now when I run the perl script perl perlscript.pl I am expecting the 'hello world' to be printed on the screen but actually I don't see any output. I there any way to do this without modifying the bash scripts?

Upvotes: 1

Views: 872

Answers (5)

mob
mob

Reputation: 118645

This can now be done in Perl with the Env::Modify module.

use Env::Modify qw(source);

source("setnameenv.sh");
# env settings from setnameenv.sh are now available to Perl
# and to the following  system  call

print `. getenvname.sh`;   # or source again, like source("getenvname.sh")

Upvotes: 1

Vouze
Vouze

Reputation: 1784

Variables are only exported for the child processes.

You cannot export variables back to the father process.

You'll need another way to transport variables back to the father or the brothers.

For example, here is a example where all exported variables are saved and read from a file :

#!/bin/dash
# setnameenv.sh

export my_msg='hello world!'

export > savedVariables.sh

and

#!/bin/dash
# getnameenv.sh

. ./savedVariables.sh

echo "$my_msg"

Note : this works with dash. bash generates one line he cannot read back.

Upvotes: 0

ikegami
ikegami

Reputation: 386361

You spawn a shell, execute some commands to change its environment, then exit the shell. You never used the environment variable you created before exiting the shell. If you want a perl to see it, you're going to have to launch Perl from that shell.

. setnameenv.sh ; perlscript.pl

If you can't change how perlscript.pl is launched, you have a couple of options, none of which are that friendly. One of the options is to bootstrap.

BEGIN {
   if (!length($ENV{my_msg})) {
      require String::ShellQuote;
      my $cmd = join(' ; ',
         '. setnameenv.sh',
         String::ShellQuote::shell_quote($^X, $0, @ARGV),
      );
      exec($cmd)
         or die $!;
   }
}

Upvotes: 1

Dinesh
Dinesh

Reputation: 1868

The child process can inherit the parent's environment but cannot make any changes. Similarly the parent cannot have access to the child's environment as well. Hence to catch environment of the child in parent the child should print the values as shown in the bellow code. The below code will set already existing environment variables as well, but this can be optimized

# perlscript.pl

my $env_val = `. setnameenv.sh; env`;
my @env_list = split "\n", $env_str;

foreach (@env_list)
{
   /([\w_]+)=(.*)/;
   $ENV{$1} = $2;
}

print `. getnameenv.sh`;

find the actual explanation in this SO answer

Upvotes: 0

mpapec
mpapec

Reputation: 50657

You can embed perl into bash script,

#!/bin/bash
. setnameenv.sh
exec perl -x "$0" "$@"

#!perl
# your script below

print `. getnameenv.sh`;

From perldoc

-x -xdirectory tells Perl that the program is embedded in a larger chunk of unrelated text, such as in a mail message. Leading garbage will be discarded until the first line that starts with #! and contains the string "perl". Any meaningful switches on that line will be applied.

Upvotes: 3

Related Questions