【问题标题】:Export variable from a shell script into a perl script将变量从 shell 脚本导出到 perl 脚本
【发布时间】:2017-01-31 00:20:29
【问题描述】:

Perl 代码

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

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

在 logon.sh 中,我们正在导出变量“ID”(shell 脚本的来源)。

手动运行

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

当我在终端中手动运行时(不是从脚本中运行)。我得到了输出。 (但不能从脚本中工作)

我关注了这篇文章:

How to export a shell variable within a Perl script?

但没有解决问题。

注意

我不允许更改“logon.sh”脚本。

【问题讨论】:

标签: perl bash unix


【解决方案1】:

反引号内的脚本在子进程中执行。虽然环境变量继承自进程,但父进程无法访问子进程的环境。

但是,您可以返回子环境变量的内容并将其放入 Perl 变量中,例如

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

输出:

DATA: 42

这里是一个示例 shell 会话:

$ 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

正常的输出被重定向到/dev/null,所以只显示echo $test_var

【讨论】:

  • 这是打印脚本的输出。 (不打印导出的数据)。我不允许更改 logon.sh 脚本。
  • @Chronicles 然后让脚本静默——反正你没有使用输出。请参阅我的更新。如果您确实需要输出,请将其重定向到文件并从那里读取。
  • 这是一个不错的方法,但我会将示例更改为:my $id = qx( . logon.sh; echo \$ID )
【解决方案2】:

这行不通。

环境变量不能从子进程继承。

环境变量可以在您的“手动运行”中更新,因为它在同一个“bash”进程中。

源命令只是在当前shell下运行login.sh中的每个命令。

更多信息可以参考:can we source a shell script in perl script

【讨论】:

    【解决方案3】:

    你可以这样做:

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

    【讨论】:

      【解决方案4】:

      嗯,我找到了一个解决方案,对我来说听起来不错:这看起来很健壮,因为它使用经过广泛测试的机制将 shell 环境绑定到 perl(运行 perl)和健壮的库以导出它们以 perl 变量语法 用于在根 perl 会话中重新注入。

      export COLOR tty 行有助于让我的 bash 导出较新的变量...这似乎工作正常。

      #!/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'};
      

      无论如何,如果您无权访问 logon.sh,则必须在运行此类解决方案之前信任它。

      旧...

      这是我的第一篇文章......出于历史目的,不要再看了。

      唯一的方法是解析结果命令,同时要求命令转储环境:

      my @lines=split("\n",`. /home/chronicles/logon.sh;set`);
      
      map { $ENV{$1}=$2 if /^([^ =])=(.*)$/; } @lines;
      

      【讨论】:

      • Nitpick:您的代码相当于print `. /home/chronicles/logon.sh;set`;。在列表上下文中,反引号运算符返回输出行列表。此外,在 void 上下文中使用 map 是不习惯的。 say for @linesprint "$_\n" for @lines 会完成同样的事情。
      【解决方案5】:

      现在可以使用Env::Modify module 完成此操作

      use Env::Modify 'source';
      source("/home/chronicles/logon.sh");
      ... environment setup in logon.sh is now available to Perl ...
      

      【讨论】:

        【解决方案6】:

        你的 Perl 进程是 shell 进程的父进程,所以它不会从它继承环境变量。继承以另一种方式起作用,从父母到孩子。

        但是当您使用反引号运行脚本时,如图所示,脚本的标准输出将返回到 Perl 脚本。因此,要么修改 shell 脚本以您显示的 echo $LOG 语句结束,要么创建一个新的 shell 脚本来运行 login.sh,然后使用 echo $LOG。您的 Perl 脚本将是:

        my $value = `./myscript.sh`;
        print $value;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-27
          • 2018-05-27
          • 1970-01-01
          • 1970-01-01
          • 2020-05-01
          • 2016-10-29
          相关资源
          最近更新 更多