2012-09-26 36 views
6

मैं पर्ल में एक प्रोग्राम चला रहा हूं कि एक बिंदु पर एक subroutine के भीतर से एक कथन में डेटा का मूल्यांकन करता है, उदा।पर्ल में वर्तमान में चल रहे प्रोग्राम को पुनरारंभ करने का कोई तरीका है?

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

मेरी समस्या में बाहर निकलने और पुनरारंभ करने के साथ है। मुझे पता है कि मैं सीधे बाहर निकलने के लिए exit 0; का उपयोग कर सकता हूं, लेकिन जाहिर है कि अगर मैं शुरुआत में वापस जाना चाहता हूं तो यह सही नहीं है। मैंने subroutine को कॉल करने की कोशिश की जो अनिवार्य रूप से प्रोग्राम शुरू करता है, लेकिन निश्चित रूप से इसे चलाने के बाद यह फिर से इस बिंदु पर वापस जायेगा। मैंने इसे थोड़ी देर में डालने के बारे में सोचा, लेकिन इसका मतलब यह होगा कि पूरी फाइल लूप में डालें और यह बहुत अव्यवहारिक होगा।

मुझे वास्तव में पता नहीं है कि यह संभव है, इसलिए कोई इनपुट बहुत अच्छा होगा।

उत्तर

8

यदि आपने @ARGV नहीं बदला है, या आप इसकी प्रतिलिपि रखते हैं, तो आप संभवतः exec($^X, $0, @ARGV) जैसे कुछ कर सकते हैं।

$^X and $0 (या $EXECUTABLE_NAME और $PROGRAM_NAME, नीचे ब्रायन की टिप्पणी देखें) क्रमशः वर्तमान 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 गुना होता है। – 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... 

सरल परिदृश्य जहां सिर्फ एक बार पुनः आरंभ करना चाहते हैं में, यह एक बिट overkill हो सकता है। लेकिन यदि आप किसी भी बिंदु पर अन्य त्रुटि परिदृश्यों को संभालने में सक्षम होने की आवश्यकता है तो यह विधि बेहतर हो सकती है।

उदाहरण के लिए यदि निकास कोड 255 है, तो यह इंगित करता है कि मुख्य स्क्रिप्ट मर() कहा जाता है। इस मामले में आप स्क्रिप्ट को पुनरारंभ करने, त्रुटि को अनदेखा करने, या समस्या को आगे बढ़ाने के लिए कुछ निर्णय प्रक्रिया को लागू करना चाहते हैं।

ऐसे पर्यवेक्षकों को लागू करने वाले सीपीएएन पर काफी कुछ मॉड्यूल हैं। Proc::Launcher उनमें से एक है और मैन्युअल पृष्ठ में संबंधित कार्यों की व्यापक चर्चा शामिल है। (मैंने प्रो :: लॉन्चर का कभी भी उपयोग नहीं किया है, यह मुख्य रूप से इस चर्चा के कारण है, मैं इसे जोड़ रहा हूं)