我正在运行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
开始,我需要调用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将这些更改显示给后续系统调用?
感谢您的评论!
旧金山
答案 0 :(得分: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魔法)。