1

我正在运行来自 Perl 的系统命令的动态列表。有时,这些命令是对环境变量进行(临时/进程中)修改的脚本。例如,考虑这个简单的脚本(目前是为 Windows 制作的):

Script-A-pl:

use strict;
use warnings;
use feature ':5.16';

$ENV{NEW_VAR} = 'this is new var';
say "Script-A.pl can read the new var: ", `echo %NEW_VAR%`;

Output: Script-A.pl can read the new var: this is new var

现在想象一下Parent.pl,我需要调用from ,Script-A.pl然后调用Script-B.pl,这取决于环境变量NEW_VAR。所以这就是它们的执行方式:

Parent.pl:

use strict;
use warnings;
use feature ':5.16';

my @commands = ('perl Script-A.pl', 'perl Script-B.pl');

for my $i (@commands) {
    system($i);
}

除了Script-A.pl无法看到由Script-B.pl.

我尝试了不同的方法来调用脚本,即使 IPC::Open3 打开一个 shell 并在那里一个一个地运行命令列表,但这也不起作用。

有没有办法可以从 Parent.pl 使这些更改对后续系统调用可见?

感谢您的评论!

弗朗西斯科

4

1 回答 1

0

%ENV代表您的 Perl 脚本的系统环境,而不是永久的系统环境。对其所做的更改仅适用于您的脚本进程(以及任何子进程)。由于您使用 调用所有脚本system,因此每个脚本的更改仅在该脚本的持续时间内持续进行。

要克服这个问题,请尝试在同一进程而不是不同进程中运行所有 Perl 脚本。

my @commands = ('Script-A.pl', 'Script-B.pl', 'echo "some other command"');

for my $cmd (@commands) {
    if ($cmd =~ /\.pl$/)
    {
        do $cmd;
    }
    else
    {
        system($cmd);
    }
}

do <FILE>是一种包含另一个 Perl 脚本中的代码并运行它的简单方法。它确保您的所有脚本都在同一个进程中,因此更改%ENV将在您的主脚本中持续存在。

do <FILE>为每个文件提供一个单独的词法变量空间,因此您不必担心声明的变量会my在文件之间发生冲突。但是,它们确实共享相同的全局变量空间,因此在以这种方式运行时,表现不佳的脚本(例如设置特殊变量,例如$/不使用local)可能会弄乱其他脚本的行为。使用此方法时,您需要检查一切是否正常。

另一个问题是,上面的代码假设 Perl 脚本没有参数。如果他们有争论,那是行不通的。但是,您可以解决此问题:

my @commands = ('Script-A.pl arg1 arg2');

for my $cmd (@commands) {
    if ($cmd =~ /\.pl\b\s*(.*)$/)
    {
        local @ARGV = split ' ', $1;
        do $cmd;
    }
    else
    {
        system($cmd);
    }
}

给每个脚本一个本地副本@ARGV使它看起来像是用参数调用它。此代码仅适用于简单参数(无空格,无 shell 魔术)。

于 2013-04-13T07:32:28.237 回答