6

サブルーチン内から呼び出された if ステートメントでデータを評価するプログラムを Perl で実行しています。

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)

$^X$0(または$EXECUTABLE_NAME$PROGRAM_NAME、以下の Brian のコメントを参照) は、それぞれ現在の perl インタープリターと現在の perl スクリプトです。

于 2012-09-26T16:58:28.130 に答える
3

別の方法は、常に2つのプロセス(スーパーバイザーとワーカー)を持つことです。

すべてのロジックをrun(またはその他)と呼ばれるサブルーチンにリファクタリングしますmain。実際のロジックが再起動する必要があることを検出すると、事前定義されたゼロ以外の終了コード(たとえば、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はその1つであり、マニュアルページには関連する作業の広範な議論が含まれています。(私は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 に答える