Perl Windows的"系统"替代品(打开多个进程)



长话短说,我正在尝试在Windows中运行Linux perl脚本(几乎没有修改)。

在Unix上它工作得很好,但是在Windows上,我得出的结论是,调用系统与Unix不同,因此它不会创建多个进程。

下面是代码:

use strict;
use warnings;
open (FIN, 'words.txt'); while (<FIN>) {
chomp;
my $line = $_;
system( "perl script.pl $line &" );

}
close (FIN);

所以基本上,我在"words.txt"中有 5 个不同的词,我希望在调用 script.pl 时逐个使用每一个词,意思是:

word1 script.pl
word2 script.pl
word3 script.pl
etc

到目前为止,它只打开单词的第一个单词.txt并且只与那个单词循环。正如我所说,在Unix上它可以完美运行,但在Windows上则不然。

我尝试使用"启动">系统("start perl script.pl $line &" );它有效...除了它打开 5 个额外的 CMD 来完成这项工作。我希望它在同一窗口上完成工作。

如果有人知道这如何在窗口上工作,我将不胜感激。

谢谢!

根据 perlport :

系统

(Win32) [...]system(1, @args)生成一个外部进程和 立即返回其过程指示符,而无需等待它 终止。返回值可以在随后的waitwaitpid中使用。 无法spawn()子流程通过将$?设置为 255 <<来指示 8.$?以与Unix兼容的方式设置(即子进程的退出状态由$? >> 8获得,如中所述 文档)。

我试过这个:

use strict;
use warnings;
use feature qw(say);
say "Starting..";
my @pids;
for my $word (qw(word1 word2 word3 word3 word5)) {
my $pid = system(1, "perl script.pl $word" );
if ($? == -1) {
say "failed to execute: $!";
}
push @pids, $pid; 
}
#wait for all children to finish
for my $pid (@pids) {
say "Waiting for child $pid ..";
my $ret = waitpid $pid, 0;
if ($ret == -1) {
say " No such child $pid";
}
if ($? & 127) {
printf " child $pid died with signal %dn", $? & 127;
}
else {
printf " child $pid exited with value %dn", $? >> 8;
}
}
say "Done.";

使用以下子脚本script.pl

use strict;
use warnings;
use feature qw(say);
say "Starting: $$";
sleep 2+int(rand 5);
say "Done: $$";
sleep 1;
exit int(rand 10);

我得到以下输出:

Starting..
Waiting for child 7480 ..
Starting: 9720
Starting: 10720
Starting: 9272
Starting: 13608
Starting: 13024
Done: 13608
Done: 10720
Done: 9272
Done: 9720
Done: 13024
child 7480 exited with value 9
Waiting for child 13344 ..
child 13344 exited with value 5
Waiting for child 17396 ..
child 17396 exited with value 3
Waiting for child 17036 ..
child 17036 exited with value 6
Waiting for child 17532 ..
child 17532 exited with value 8
Done.

似乎工作正常..

您可以使用Win32::Process来获得比system在Windows上更精细地控制创建新进程。特别是,以下内容不会像使用system("start ...")那样为每个进程创建新的控制台:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
# Older versions don't work with an undef appname argument.
# Use the full path to perl.exe on them if you can't upgrade
use Win32::Process 0.17; 
my @lines = qw/foo bar baz quux/; # For example instead of using a file
my @procs;
for my $line (@lines) {
my $proc;
if (!Win32::Process::Create($proc, undef, "perl script.pl $line", 1,
NORMAL_PRIORITY_CLASS, ".")) {
$_->Kill(1) for @procs;
die "Unable to create process: $!n";
}
push @procs, $proc;
}
$_->Wait(INFINITE) for @procs;
# Or
# use Win32::IPC qw/wait_all/;
# wait_all(@procs);

作为另一种方法,start命令采用/b选项来不打开新的命令提示符。

system("start /b perl script.pl $line");