让perl执行shellscript&接管env vars

时间:2011-04-10 08:42:40

标签: perl

我有一个shell脚本除了设置一堆环境变量之外什么都不做:

export MYROOTDIR=/home/myuser/mytools
export PATH=$MYROOTDIR/bin:$PATH
export MYVERSION=0.4a

我有一个perl脚本,我希望perl脚本以某种方式让perl脚本与shell脚本中列出的env变量一起运行。我需要在perl脚本中发生这种情况,但我不希望perlscript的调用者必须首先手动获取shellcript。

尝试运行时

system("sh myshell.sh")

env vars不会“传播”到运行perl脚本的进程。

有办法做到这一点吗?

5 个答案:

答案 0 :(得分:4)

要正确回答这个问题,我需要了解更多。

  • 从perl脚本中实际运行shell脚本是否可以?
  • 变量赋值是否全部为export VAR=value形式(即具有固定赋值,无变量替换或命令替换)?
  • shell脚本是否会执行其他操作,只能分配变量?

根据这些问题的答案,存在不同复杂程度的选项。

感谢您的澄清。好的,这是怎么做的。除了分配变量之外,您的脚本没有副作用。这允许从perl中运行脚本。我们如何知道脚本中导出的变量?我们可以尝试解析shell脚本,但这不是Unix使用工具做得好的事情并将它们链接在一起的方式。相反,我们使用shell的export -p命令让它宣布所有导出的变量及其值。为了找到脚本实际设置的变量,而不是所有其他噪声,脚本是使用env -i(另一个低估的POSIX gem)的干净环境启动的。

全部放在一起:

#!/usr/bin/env perl
use strict;
use warnings;

my @cmd = (
  "env", "-i", "PATH=$ENV{PATH}", "sh", "-c", ". ./myshell.sh; export -p"
);

open (my $SCRIPT, '-|', @cmd) or die;
while (<$SCRIPT>) {
    next unless /^export ([^=]*)=(.*)/;
    print "\$ENV{$1} = '$2'\n";
    $ENV{$1} = $2;
}
close $SCRIPT;

注意:

  • 您需要将env -i所需的所有环境转移到myshell.sh,例如PATH
  • Shells通常会导出PWD变量;如果你不想在你的perl ENV哈希中使用它,请在第一个next if $1 eq 'PWD';之后添加next

这应该可以解决问题。如果有效,请告诉我。

另见:

答案 1 :(得分:1)

尝试Shell::Source

答案 2 :(得分:0)

您可以在BEGIN块中设置环境变量。 BEGIN块在其余代码之前执行,在此块中设置环境变量使其在编译和运行之前对其余代码可见。 如果你有任何perl模块根据环境设置“使用”,BEGIN块就可以实现。

Perl使用特殊的散列%ENV来维护环境变量。 您可以修改此哈希的内容以设置env变量。

示例:

BEGIN 
{
    $ENV { 'MYROOTDIR' } = '/home/myuser/mytools';
    $ENV { 'PATH' } = "$ENV{ 'MYROOTDIR' }/bin:$ENV{ 'PATH' }";
}

答案 3 :(得分:0)

shell脚本设置变量,然后调用perl程序会不会更容易?

即:

run.sh:

#!/bin/sh

export MYROOTDIR=/home/myuser/mytools
export PATH=$MYROOTDIR/bin:$PATH
export MYVERSION=0.4a

./program.pl

答案 4 :(得分:0)

现在可以使用Env::Modify完成此操作,只需对现有代码进行少量更改。

use Env::Modify 'system';
...
system("sh myshell.sh");
print $ENV{MYROOTDIR};      # "/home/myuser/mytools"

或者如果您的所有shell脚本都修改了环境,您可以使用source函数

use Env::Modify `source`;
source("myshell.sh");
print $ENV{MYVERSION};      # "0.4a"