6

我在 Perl 中运行一个程序,该程序在某一时刻评估从子例程中调用的 if 语句中的数据,例如

sub check_good {
    if (!good) {
         # exit this subroutine
         # restart program
    } 
    else {
         # keep going
    }
} # end sub

我遇到的问题是退出和重新启动。我知道我可以直接使用exit 0;退出,但是如果我想回到开头,显然这是不正确的。我尝试调用基本上启动程序的子程序,但是当然一旦它运行它会再次回到这一点。我想过把它放在一个while循环中,但这意味着把整个文件放在循环中,这是非常不切实际的。

我实际上不知道这是否可能,所以任何输入都会很棒。

4

3 回答 3

10

如果您没有更改@ARGV,或者您保留它的副本,您可能会执行类似的操作exec($^X, $0, @ARGV)

$^Xand$0(或$EXECUTABLE_NAMEand $PROGRAM_NAME,见下面 Brian 的评论)分别是当前的 perl 解释器和当前的 perl 脚本。

于 2012-09-26T16:58:28.130 回答
3

另一种选择是始终有两个进程:一个主管和一个工人。

将所有逻辑重构为一个名为runmain或其他)的子例程。当您的真实逻辑检测到它需要重新启动时,它应该使用预定义的非零退出代码(例如 1)退出。

然后您的主脚本和主管将如下所示:

if (my $worker = fork) {
    # child process
    run(@ARGV);
    exit 0;
}
# supervisor process
waitpid $worker;
my $status = ($? >> 8);

if ($status == 1) { ... restart .. }

exit $status; # propagate exit code...

在您只想重新启动一次的简单场景中,这可能有点矫枉过正。但是,如果您在任何时候都需要能够处理其他错误情况,则此方法可能更可取。

例如,如果退出代码是 255,这表明主脚本调用了 die()。在这种情况下,您可能需要执行一些决策过程来重新启动脚本、忽略错误或升级问题。

CPAN 上有很多模块实现了这样的监督者。Proc::Launcher就是其中之一,手册页包含对相关作品的广泛讨论。(我从未使用过 Proc::Launcher,这主要是由于我链接到它的讨论)

于 2012-09-26T18:13:59.433 回答
-1

没有什么可以阻止你呼唤system自己。像这样的东西(显然需要整理一下),我传入一个命令行参数以防止代码永远调用自己。

#!/usr/bin/perl
use strict;
use warnings;

print "Starting...\n";
sleep 5;

if (! @ARGV) {
        print "Start myself again...\n";
        system("./sleep.pl secondgo");
        print "...and die now\n";
        exit;
} elsif ((@ARGV) && $ARGV[0] eq "secondgo") {
        print "Just going to die straightaway this time\n";
        exit;
}
于 2012-09-26T17:08:21.167 回答