从Perl运行时,为什么不设置批处理文件的环境变量?

时间:2009-10-12 05:03:44

标签: perl batch-file environment-variables

我正在尝试从perl脚本调用bat文件,如下所示:

 system("call D:/SIP/run_$file_idx.bat");

但是我发现bat中的环境变量无法解决。 如果我从命令提示符单独运行bat文件,它就可以运行。

system()是否创建了一个新环境并执行bat文件? 我错过了什么?

if (($ENV{'IPSL_RUN_FLAG'}) eq "TRUE") {

my $Book = $Excel->Workbooks->Open(
    "$ENV{'IPSL_TESTCASES_PATH'}IPSLFeatureLoadRunResults.xls"); 

# Make transparent where the IPSL tarball is installed. 
# Have ControlPanel save results here.

# You can dynamically obtain the number of worksheets, rows, and columns
# through the Excel OLE interface.  Excel's Visual Basic Editor has more
# information on the Excel OLE interface.  Here we just use the first
# worksheet, rows 1 through 4 and columns 1 through 3.

# select worksheet number 1 (you can also select a worksheet by name)

my $count=0;

my $Sheet = $Book->Worksheets("LOADDATA");
my $tmp=0;


foreach my $row (13..776) {
    foreach my $col (17..17) {
        if(($Sheet->Cells($row,$col)->{'Value'} eq "Failed") || 
            ($Sheet->Cells($row,$col)->{'Value'} eq "No Run") ) {
            $cnt_of_current_rerun_testcases++;
            foreach my $col (18..18) {
                # skip empty cells
                next unless defined $Sheet->Cells($row,$col)->{'Value'};
                my $a = $Sheet->Cells($row,$col)->{'Value'};

                my $i = index($a, 'run');  
                $a = substr($a, 0, $i); #remove runTest*  

                print OUT "\n";
                if($count == 0) {
                    print OUT "\nREM "; 
                    print OUT  "*" x 100; 
                    print OUT "\n";
                    print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ips32.exe";
                    print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ipsldb.exe";
                    print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ipsltiu.ex\n";    
                }

                print OUT "c:\n";            
                print OUT "\ncd ";

                $a =~ s/%I/\"%I/g;
                $a=~s/H%/H%\"/g;

                print OUT " $a\n";

                print OUT "\n";
                print OUT "CALL run_SubscribeFeatureOnHIQ.bat";
                print OUT "\n";

                print OUT "sleep 10\n";

                print OUT "\ncd ";
                print OUT " $a\n";
                print OUT "\n";

                print OUT "CALL ";
                $i=$Sheet->Cells($row,$col)->{'Value'};
                $i=~ s/%I/\"%I/g;
                $i=~s/H%/H%\"/g;
                print OUT $i;
                #print OUT  $Sheet->Cells($row,$col)->{'Value'};
                print OUT "\n";

                $count++;
                if($count == $no_simul_tcases) {
                    $sleep_cnt++;
                    print OUT "echo Going for sleep $sleep_cnt\n";
                    print OUT "SLEEP 300";
                    print OUT "\n";
                    $count=0;
                }
            }
        }
    }
}

print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ips32.exe";
print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ipsldb.exe";
print OUT "\ntaskkill /F /FI \"USERNAME eq %USERNAME%\" /IM ipsltiu.ex\n";         
print OUT "\nset IPSL_RUN_FLAG=TRUE";
close OUT ;
system(\"start $ENV{'IPSL_TESTCASES_PATH'}SIP\\run_$file_idx.bat\");

批处理文件是:

taskkill /F /FI "USERNAME eq %USERNAME%" /IM ips32.exe
taskkill /F /FI "USERNAME eq %USERNAME%" /IM ipsldb.exe
taskkill /F /FI "USERNAME eq %USERNAME%" /IM ipsltiu.ex
c:

cd  "%IPSL_TESTCASES_PATH%"SIP\TestCASE\FEATURESINT\INT_cfSRS\INT_cfSRS_cfSERRNG\

CALL run_SubscribeFeatureOnHIQ.bat
sleep 10


cd  "%IPSL_TESTCASES_PATH%"SIP\TestCASE\FEATURESINT\INT_cfSRS\INT_cfSRS_cfSERRNG\

CALL "%IPSL_TESTCASES_PATH%"SIP\TestCASE\FEATURESINT\INT_cfSRS\INT_cfSRS_cfSERRNG\runTest_SRS_INT_SERRNG.bat

可能的解决方法:

通过使用exec并专门将ENV写入bat文件给了我一个解决方法:

print OUT map { "set $_=$ENV{$_}\n" } 
          qw( path USERPROFILE USERNAME ProgramFiles ComSpec APPDATA );

但是系统()仍然会出现问题。我在回答者中尝试了思南的建议..

3 个答案:

答案 0 :(得分:1)

子进程继承其父进程的环境。 bat文件应该与Perl脚本具有相同的环境。如果您没有正确设置环境,您的bat文件将无法看到它。

你可以扩展你的答案来展示你的测试案例,类似于思南所做的事情吗?虽然您在评论中说代码很简单,但事实并非如此。向我们展示您拥有的完整Perl程序以及您拥有的完整bat文件。不要让我们猜测或做很多工作来弄清楚你在做什么。

更新:现在您已经提供了一些代码,开始从中切割部分以制作仍然显示问题的最简单的测试用例。在调查这些问题时,请停止处理大脚本并编写一个脚本来解决您认为自己遇到的问题。这样,你可以将它与其他可能搞乱的东西隔离开来。

答案 1 :(得分:0)

更新2:让我们更仔细地查看您的system来电:

 system(\"start $ENV{'IPSL_TESTCASES_PATH'}SIP\\run_$file_idx.bat\");

这应该是语法错误,您的脚本甚至不能调用批处理文件。尝试

 system(qq{start $ENV{IPSL_TESTCASES_PATH}SIP\\run_$file_idx.bat\\});

更新1:查看您发布的代码,您在系统调用中使用start。这会启动一个新的cmd.exe进程,并且在您的脚本终止后cmd.exe将保持很长时间。但是,我仍然没有按照您的描述观察行为,我将更仔细地查看您的代码转储。

C:\Temp> cat bg.bat
@echo %YAEV%
@echo %*
C:\Temp> cat t.pl
#!/usr/local/bin/perl

use strict;
use warnings;

$ENV{YAEV} = 'Yet another environment variable';
system 'start bg.bat "This is a test"';

在新的cmd.exe窗口中:

C:\Temp> t
Yet another environment variable
"This is a test"

答案 2 :(得分:-1)

如果系统调用的参数是标量,系统命令[contested:/ function]将在默认批处理文件上下文(这是系统范围的环境)中启动批处理脚本。它与使用“cmd / c myfile.bat”启动命令基本相同。如果你对system()的参数是一个数组[contested:/ list],你就不会遇到这个问题。请阅读this for more information