2012-09-26 31 views
6

我正在Perl中運行一個程序,它在一個點上評估從子程序中調用的if語句中的數據,例如,在Perl中有沒有一種方法可以重新啓動當前正在運行的程序?

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

我遇到的問題是退出並重新啓動。我知道我可以直接使用exit 0;直接退出,但顯然這是不正確的,如果我想回到開始。我試着調用基本上啓動程序的子程序,但是當它運行後,它會再次回到這一點。 我想過把它放在while循環中,但這意味着將整個文件放在循環中,這將是非常不切實際的。

我實際上並不知道這是否可能,所以任何輸入都會很好。

回答

8

如果你還沒有改變@ARGV,或者你保留一份它的副本,你可能會做一些像exec($^X, $0, @ARGV)

$^X and $0(或$EXECUTABLE_NAME$PROGRAM_NAME,請參閱Brian的下面的評論)分別是當前的perl解釋器和當前的perl腳本。

+0

原諒我的無知 - 我知道@ARGV用於命令行參數,但我已使用所以可以我假設他們將數據存儲在相同的內存位置(或其他)? – dgBP

+0

這是您可以輕鬆測試的主張。 – DavidO

+0

如果你使用stdin,那麼你將不得不緩衝它自己,也許在臨時文件中。 – tripleee

-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; 
} 
+0

此解決方案取決於預先固定的文件名。當我們有多個鏈接或符號鏈接指向這個腳本時,開始吸引人,用不同的名字。這仍然假設沒有'chdir'被執行......而且,你正在創建一個完整的級聯進程。自己調用一次並不重要,但通過這種方式重新啓動1000次往往會填滿進程表和RAM。 – amon

+0

同意所有這些觀點,我只是想表明可以重新開始自己。下面和上面的答案顯然更全面。 –

3

另一種方法是總是有兩個過程:一個主管和一個工人。

重構所有的邏輯到一個名爲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就是其中之一,手冊頁包含了對相關作品的廣泛討論。 (我從來沒有使用Proc :: Launcher,這主要是由於這個討論我鏈接到它)

相關問題