2012-02-12 76 views
3

目前,我打个电话这样的:的Perl:执行多个系统进程,并等待他们在我的Perl脚本结束

system(" ./long_program1 & ./long_program2 & ./long_program3 & wait "); 

我希望能够在记录每个长时间运行的命令执行时仍然异步执行它们。我知道系统调用会导致perl生成一个fork,所以可能会这样吗?这可以被多个perl fork()和exec()调用所取代吗?

请帮我找到更好的解决方案。

+0

你要记录的结束时间或只是开始时间?当进程启动时,你想记录哪些信息,当进程退出时你想记录什么信息? – ikegami 2012-02-13 10:18:52

回答

6

是的,当然。您可以为每个要执行的程序分出一个子进程。

您可以做system()exec()分叉后,这取决于你想要多少处理您的Perl代码在系统调用完成后做(因为EXEC()在功能上system(); exit $rc;非常相似)

foreach my $i (1, 2, 3) { 
    my $pid = fork(); 
    if ($pid==0) { # child 
     exec("./long_program$i"); 
     die "Exec $i failed: $!\n"; 
    } elsif (!defined $pid) { 
     warn "Fork $i failed: $!\n"; 
    } 
} 

1 while wait() >= 0; 

请注意,如果您需要做很多叉子,您最好通过Parallel::ForkManager来控制它们,而不是手动分叉。

+0

'exec'在许多方面与'system'&'exit'不同。 (事实上​​,'system'使用'exec'。) – ikegami 2012-02-13 03:02:18

+0

@ikegami - 真的,我过于简单,因为它不是主问:我会重新字 – DVK 2012-02-13 10:58:44

3

两种选择:


use IPC::Open3 qw(open3); 

sub launch { 
    open(local *CHILD_STDIN, '<', '/dev/null') or die $!; 
    return open3('<&CHILD_STDIN', '>&STDOUT', '>&STDERR', @_); 
} 

my %children; 
for my $cmd (@cmds) { 
    print "Command $cmd started at ".localtime."\n"; 
    my $pid = launch($cmd); 
    $children{$pid} = $cmd; 
} 

while (%children) { 
    my $pid = wait(); 
    die $! if $pid < 1; 
    my $cmd = delete($children{$pid}); 
    print "Command $cmd ended at ".localtime." with \$? = $?."\n"; 
} 

我用open3因为它比短的甚至是微不足道的fork + exec并且因为它不misattribute exec错误您启动像命令琐碎fork + exec


use threads; 

my @threads; 
for my $cmd (@cmds) { 
    push @threads, async { 
     print "Command $cmd started at ".localtime."\n"; 
     system($cmd); 
     print "Command $cmd ended at ".localtime." with \$? = $?."\n"; 
    }; 
} 

$_->join() for @threads; 
+0

过有关什么是优势,使用多线程,而不是多进程在这样的情况下? – Blaskovicz 2012-02-13 04:41:07

+0

@Blaskovicz,它不使用线程而不是进程。它启动完全相同的过程。至于代码在第一个代码片段中代码的优点,它应该很明显:简单。 – ikegami 2012-02-13 10:14:15

+0

线程使用选项是美丽的,干净的和工作的一种享受!谢谢! – Balthasar 2015-04-23 05:40:19