2009-05-26 12 views
10

मैं कुछ पर्ल कोड है कि एक से अधिक पैरामीटर के लिए एक खोल स्क्रिप्ट निष्पादित करता है, को आसान बनाने के लिए है, मैं सिर्फ मान लेंगे कि मैं कोड है कि इस तरह दिखता है:मैं पर्ल को सिस्टम() के साथ पृष्ठभूमि में बाल प्रक्रियाओं के लिए कैसे शुरू कर सकता हूं?

for $p (@a){ 
    system("/path/to/file.sh $p&"); 
} 

मैं के बाद कुछ और काम करने के लिए करना चाहते हैं कि, लेकिन मुझे जारी रखने से पहले सभी बाल प्रक्रियाओं को समाप्त करने का इंतजार करने का कोई तरीका नहीं मिल रहा है।

फोर्क() का उपयोग करने के लिए कोड को कनवर्ट करना मुश्किल होगा। क्या कोई आसान तरीका नहीं है?

+0

क्या आपको file.sh से वास्तविक रिटर्न कोड की आवश्यकता है? क्या आप स्क्रिप्ट बदल सकते हैं ताकि यह पूर्ण होने पर फ़ाइल को लिख सके? – mkb

+1

कोड को फोर्क में परिवर्तित क्यों करना मुश्किल होगा? सबराउटिन में सभी विवरण छुपाएं। आप इसके बजाय अपने नए सबराउटिन को कॉल करने के लिए सिस्टम() को फिर से परिभाषित कर सकते हैं। –

+0

मैं शायद इस भाग को एक अलग लिपि में विभाजित करूंगा जो फोकस करता है, और सिस्टम कॉल से कॉल करें ... –

उत्तर

16

कांटा का उपयोग करना/exec/wait इतना बुरा नहीं है:

my @a = (1, 2, 3); 
for my $p (@a) { 
    my $pid = fork(); 
    if ($pid == -1) { 
     die; 
    } elsif ($pid == 0) { 
     exec '/bin/sleep', $p or die; 
    } 
} 
while (wait() != -1) {} 
print "Done\n"; 
+1

आप एक असफल फोर्क की जांच नहीं कर रहे हैं और आप नर्डवर्ड पिड को @pids पर नहीं दबा रहे हैं, न कि $ pid। निकास शायद इसके बजाय मर जाना चाहिए, अगर यह निष्पादित करता है तो इसका मतलब है कि निष्पादन विफल रहा है। –

+0

फिक्स्ड। धन्यवाद, मैं वास्तव में पर्ल का मूल निवासी नहीं हूं। – Dave

+0

$ pid == -1 शायद इसके बजाय परिभाषित ($ pid) होना चाहिए। –

8

फोर्क() में कनवर्ट करना मुश्किल हो सकता है, लेकिन यह सही उपकरण है। सिस्टम() एक अवरुद्ध कॉल है; आप एक खोल को निष्पादित करके और पृष्ठभूमि में अपनी स्क्रिप्ट चलाने के लिए कहकर गैर-अवरुद्ध व्यवहार प्राप्त कर रहे हैं। इसका मतलब है कि पर्ल को पता नहीं है कि बच्चों के पीआईडी ​​क्या हो सकते हैं, जिसका मतलब है कि आपकी स्क्रिप्ट को पता नहीं है कि किसके लिए इंतजार करना है।

आप पीआईडी ​​को पर्ल स्क्रिप्ट तक संवाद करने का प्रयास कर सकते हैं, लेकिन वह जल्दी से हाथ से बाहर हो जाता है। कांटा() का प्रयोग करें।

13

आपको कुछ बदलना होगा, फोर्क का उपयोग करने के लिए कोड को बदलना शायद आसान है, लेकिन यदि आप कांटे का उपयोग करने के खिलाफ मृत सेट हैं, तो आप एक रैपर शैल स्क्रिप्ट का उपयोग कर सकते हैं जो फ़ाइल को तब किया जाता है जब यह किया जाता है और फिर फ़ाइलों के अस्तित्व के लिए अपने पर्ल कोड की जांच करें।

#!/bin/bash 

$* 

touch /tmp/$2.$PPID 

आपका पर्ल कोड दिखाई देगा::

for my $p (@a){ 
    system("/path/to/wrapper.sh /path/to/file.sh $p &"); 
} 
while (@a) { 
    delete $a[0] if -f "/tmp/$a[0].$$"; 
} 

लेकिन मुझे लगता है forking के कोड सुरक्षित और स्पष्ट है:

यहाँ आवरण है

my @pids; 
for my $p (@a) { 
    die "could not fork" unless defined(my $pid = fork);\ 
    unless ($pid) { #child execs 
     exec "/path/to/file.sh", $p; 
     die "exec of file.sh failed"; 
    } 
    push @pids, $pid; #parent stores children's pids 
} 

#wait for all children to finish 
for my $pid (@pids) { 
    waitpid $pid, 0; 
} 
+0

यह एक बेहतर जवाब है। – zdim

+0

स्पष्ट रूप से ऐसा करने से ज़ोंबी प्रक्रियाएं बहुत अधिक होती हैं। https://en.wikipedia.org/wiki/Zombie_process –

+1

@PratyushRathore यह नहीं होना चाहिए। एक ज़ोंबी परिणाम जब माता-पिता की प्रक्रिया प्रतीक्षा या प्रतीक्षापैड को कॉल नहीं करती है। जैसा कि आप देख सकते हैं कि माता-पिता बाहर निकलने वाले बच्चे के लिए वेटपिड को कॉल कर रहा है। यदि आपको ज़ोंबी का गुच्छा मिल रहा है तो आप कुछ गलत कर रहे हैं या पहले बच्चों में से एक लंबा समय ले रहा है और बाद के बच्चे बाहर निकल गए हैं (लेकिन इसकाटा नहीं गया है)। आप अगली बहिष्कृत बच्चे को काटने के लिए 'while (प्रतीक्षापिड (-1, WNOHANG)> 0) {नींद 1} 'पर स्विच कर सकते हैं। –

संबंधित मुद्दे

 संबंधित मुद्दे