can we source a shell script in the perl script??
Example: Program 1:
cat test1.sh
#!/bin/ksh
DATE=/bin/date
program 2:
<
I met a close need from the OP's in a project, where I needed to configure a Perl script (it could be any language, for that matter) by sourcing a shell script defining the environment.
I personally rarely use sourcing for anything else than configuration and environment setting (the only other good reason for sourcing I am aware of, is for importing functions in shell scripts, but I may be missing some creative usage).
My solution was to source the configuration script from a launcher script (in shell), and then to exec the Perl script in the same launcher script (replacing effectively the launcher script by the Perl script, thus avoiding to create a subprocess).
# configuration_script.sh
export MY_ENV_VAR1=value1
export MY_ENV_VAR2=value2
# launcher_script.sh
. configuration_script.sh # source the configuration
exec /path/to/main_script.pl "$@" # could be any other language here (Python, Tcl, Ruby, C, Java...)
The "$@" allows to pass the command line arguments from the launcher script to the main script.
It's then up to the main script author to retrieve the environment (e.g. with $ENV{MY_ENV_VAR1} in Perl).
You cannot do a
system("source src.sh");
system()
starts a new sub-shell, your environment variables do not get passed to the shell your Perl script is running in. Even though your shell script exports variables, it will export them to the sub-shell, not to your actual shell.
One solution would be to write a wrapper script which
Yes, you can now do this with the Env::Modify module.
use Env::Modify qw(:ksh source);
source("./test1.sh"); # env settings from test1.sh now available in Perl
print `$ENV{DATE}`; # print `/bin/date`;
You can do something simple, like this:
system "source /path/to/shell_env.sh &&"
. "/path/to/script.sh";
NOTE that this is different than the following which is not recommended:
system "source /path/to/shell_env.sh &&"
. "/bin/sh /path/to/script.sh";
I don't know that this will help, but I felt compelled to come up with a way to write this in Perl. My intent was to have Perl run a shell script, and to assign any shell variables it sets to like-named variables in the Perl script.
The others are correct in that any shell script you "source" is going to be in a sub-shell. I figured I could use "sh -x cmd" to at least have the shell show the variables as they're set.
Here's what I wrote:
use strict; use warnings;
our $DATE;
my $sh_script = "./test1.sh";
my $fh;
open($fh, "sh -x '$sh_script' 2>&1 1>/dev/null |") or die "open: $!";
foreach my $line (<$fh>) {
my ($name, $val);
if ($line =~ /^\+ (\w+)='(.+)'$/) { # Parse "+ DATE='/bin/date;'
$name = $1;
($val = $2) =~ s{'\\''}{'}g; # handle escaped single-quotes (eg. "+ VAR='one'\''two'")
} elsif ($line =~ /^\+ (\w+)=(\S+)$/) { # Parse "+ DATE=/bin/date"
$name = $1;
$val = $2;
} else {
next;
}
print "Setting '$name' to '$val'\n" if (1);
# NOTE: It'd be better to use something like "$shell_vars{$name} = $val",
# but this does what was asked (ie. $DATE = "/bin/date")...
no strict 'refs';
${$name} = $val; # assign to like-named variable in Perl
}
close($fh) or die "close: ", $! ? $! : "Exit status $?";
print "DATE: ", `$DATE` if defined($DATE);
There's certainly more error-checking you could do, but this did the trick for me if all you want to catch is shell variables.
Uhm.. is the below cheating?
#!/bin/sh
. ./test1.sh # source the test script
echo Bash says $DATE
export DATE; # KEY to have the below Perl bit see $ENV{DATE}
perl <<'ENDPERL';
print "Perl says $ENV{DATE}\n";
ENDPERL
The problem is that sourcing the sh file may do whatever, and not just assign value X to variable Y...