如何将Parallel :: ForkManager和Exec的STDOUT重定向到文件

时间:2017-03-15 08:51:41

标签: perl parallel-processing fork

我正在尝试使用Perl Parallel:ForkManager运行多个命令。我希望这些命令在不同的时间段运行。我正在使用子程序is_time_elapsed来检查是否是运行命令的时间。如果子例程返回0,那么我正在使用并行fork管理器运行该命令。命令正在执行,但我在屏幕上看到STDOUT。相反,我想将STDOUT和STDERR重定向到一个文件。如何防止STDOUT在屏幕上看到并重定向到文件

我的要求是在时间结束后在后台运行命令。我需要在命令完成执行时记录执行时间。该脚本将是一个主脚本,它将无限运行并在时间结束后运行命令。除了Parallel :: ForkManager之外,还有其他任何模块可以实现这一目标。

my $forkMgr = Parallel::ForkManager->new(15);
$forkMgr->run_on_finish(
    sub {
        ($pid, $exitCode, $ident) = @_;
        print "Ended ==> $ident\n";
    }
);

while (1) {
    foreach my $cmd (@commands) {
        if (is_time_elapsed($cmd)) {
            $forkMgr->start($cmd)
               and next;
            exec("$cmd")
               or die("exec: $!");
            $forkMgr->finish;
        }
    }
    sleep 30
}

2 个答案:

答案 0 :(得分:3)

重定向整个程序及其子程序的所有输出:

main_program >log 2>&1

仅重定向子项的输出:

if (is_time_elapsed($cmd)) {
    $forkMgr->start($cmd)
       and next;
    open(STDOUT, '>>', 'log')
       or die("open: $!");
    open(STDERR, '>>&', \*STDOUT)
       or die("open: $!");
    exec("$cmd")
       or die("exec: $!");
}

如果您愿意,您甚至可以将每个孩子的输出重定向到另一个文件。

注意:我摆脱了$forkMgr->finish。从来没有达到过(这很好)。

答案 1 :(得分:2)

与Perl一样,有几种方法可以实现这一点。您还没有说明要将哪些输出发送到文件,或者根本不需要真正的STDOUT。让我们探讨一下您的选择。

您的程序中任何地方都不需要STDOUT

如果您的主程序以及所有工作人员永远不应该向STDOUT打印任何内容,您可以使用输出重定向来运行它。这使您可以在开发期间对STDOUT进行调试,并在生产中写入文件。

只需使用附加到命令的>output.log启动程序即可。所有分叉的输出也将转到该文件。 STDERR将保持不变。

$ perl forker.pl >output.log

如果您希望所有输出都转到文件,这应该是首选方法。

或者,您可以在Perl中实现此功能。这会让你失去在控制台上调试的能力,你总是要看文件。使用select更改print的默认句柄。请务必使用append-mode >>作为新句柄。

open my $fh, '>>', 'output.log' or die $!;
select $fh;

my $forkMgr = Parallel::FormManager->new(15);
# ...

现在所有输出也将转到该文件。 See this blog post了解有关其工作原理的详细信息,以及如何恢复原始STDOUT

Catpure STDOUT

Capture::Tiny非常适合抓住STDOUT的东西。您可以使用它来包装exec

use Capture::Tiny 'capture_stdout';

# ...

my $stdout = capture_stdout {
    exec($cmd);
}

现在您可以将其写入文件。

使用记录器

Log::Log4Perl是高级日志记录的首选模块。您应该能够告诉它不仅从STDERR获取所有内容,还从STDOUT获取所有内容。我没有研究过这个,但它应该有用。