2009-04-30 28 views
22

मेरे पास एक लंबी चल रही प्रक्रिया है और मुझे इसे एक और प्रक्रिया लॉन्च करने की आवश्यकता है (जो भी एक अच्छा समय के लिए चलाएगा)। मुझे केवल इसे शुरू करने की आवश्यकता है, और फिर इसके बारे में पूरी तरह से भूल जाओ।कैसे एक उपप्रजाति को आग और भूलना है?

प्रोग्रामिंग रूबी पुस्तक से कुछ कोड स्कूप करके मुझे जो कुछ चाहिए, वह करने में कामयाब रहा, लेकिन मैं सबसे अच्छा/सही तरीका ढूंढना चाहता हूं, और समझ रहा हूं कि क्या हो रहा है। यहाँ है कि मैं क्या शुरू में मिल गया है:

exec("whatever --take-very-long") if fork.nil? 
Process.detach($$) 


तो, यह तरीका है, या मैं उसे और कैसे करना चाहिए?

जवाब नीचे मैं इस कोड है, जो अधिक समझ बनाने के लिए लगता है के साथ समाप्त हो गया की जाँच के बाद:

(pid = fork) ? Process.detach(pid) : exec("foo") 


मैं कैसे fork काम करता है पर कुछ स्पष्टीकरण की सराहना करेंगे। [इसे पहले से मिला है]

$$ सही से अलग था? मुझे नहीं पता कि यह क्यों काम करता है, और मैं वास्तव में स्थिति की बेहतर समझ लेना चाहता हूं।

उत्तर

20

fork फ़ंक्शन आपकी प्रक्रिया को दो में अलग करता है।

प्रक्रियाओं दोनों को फ़ंक्शन का परिणाम प्राप्त होता है। बच्चे को शून्य/nil का मूल्य प्राप्त होता है (और इसलिए जानता है कि यह बच्चा है) और माता-पिता को बच्चे का पीआईडी ​​प्राप्त होता है।

इसलिए

:

exec("something") if fork.nil? 

बच्चे प्रक्रिया शुरू "कुछ" कर देगा, और माता पिता की प्रक्रिया जहां यह था के साथ पर ले जाएगा।

ध्यान दें कि exec() को "कुछ" के साथ वर्तमान प्रक्रिया को प्रतिस्थापित करता है, इसलिए बाल प्रक्रिया किसी भी बाद के रूबी कोड को कभी निष्पादित नहीं करेगी।

Process.detach() पर कॉल ऐसा लगता है कि यह गलत हो सकता है। मैं उम्मीद करता था कि इसमें बच्चे का पीआईडी ​​होगा, लेकिन अगर मैं आपका कोड सही पढ़ता हूं तो यह वास्तव में मूल प्रक्रिया को अलग कर रहा है।

+1

ठीक है, मुझे लगता है कि मुझे .nil मिला है? चेक। बच्चे में यह वास्तव में 0 नहीं लौटाता है, यह शून्य लौटाता है। तो यदि आप बच्चे में हैं तो निष्पादन चलाएगा। तो फिर, मैं कांटा की दूसरी वापसी कैप्चर कैसे करूं, जो कि बच्चे की प्रक्रिया की आईडी लौटाता है? इस तरह मैं $$ पर भरोसा करने के बजाय इसे सीधे इस्तेमाल कर सकता था। – kch

+2

बस कांटा कॉल करें और परिणाम कैप्चर करें। तो अगर आपको शून्य मिलती है, तो निष्पादन करें, अन्यथा आप माता-पिता में हैं। – Alnitak

+0

यह 'कांटा' की इतनी शानदार स्पष्ट और संक्षिप्त परिभाषा है। महान काम, धन्यवाद। – KomodoDave

28

अल्निटक सही है। यहाँ अलग करने के उद्देश्य सिर्फ इतना कहना है, "मुझे परवाह नहीं है जब बच्चे समाप्त हो जाता है" zombie processes से बचना है $$

pid = Process.fork 
if pid.nil? then 
    # In child 
    exec "whatever --take-very-long" 
else 
    # In parent 
    Process.detach(pid) 
end 

के बिना एक अधिक स्पष्ट जिस तरह से यह लिखने के लिए है,।

+1

हाय, मैं अपने नए अधिग्रहित ज्ञान के साथ खेल रहा था, और मैं मूल रूप से इसके एक संक्षिप्त संस्करण में आया: (pid = कांटा)? Process.detach (पिड): exec ("foo") – kch

+0

हाँ। यह काम करता है। –

+0

@MatthewFlaschen यदि इसमें 'exec' नहीं है, तो क्या मुझे ज़ोंबी प्रक्रिया के लिए बच्चे कोड में' निकास 'की आवश्यकता नहीं है? – oldergod

2

$$ अलग करना सही नहीं था। पी से पिकैक्स के 348 (2 एड):

$$ फ़िक्सनम प्रोग्राम की प्रक्रिया संख्या निष्पादित की जा रही है।[आर/ओ]

यह खंड, "चर और स्थिरांक" "रूबी भाषा" अध्याय में, विभिन्न माणिक कम $ स्थिरांक डीकोड करने के लिए बहुत आसान है - लेकिन ऑनलाइन संस्करण (प्रथम

तो क्या आप वास्तव में से ही कार्यक्रम अलग करने गया था, इसके बच्चे से नहीं कर रहे थे। अन्य लोगों की तरह कहा है, बच्चे से अलग करने के लिए उचित तरीके से बच्चे की पीआईडी ​​fork() से लौटे उपयोग करने के लिए है।

+0

कुछ ने आपके उत्तर को बोर्क किया। वैसे भी मेरे पास पिकैक्स का तीसरा संस्करण है। तो, $$ सही नहीं है, तथ्य। लेकिन फिर भी यह काम क्यों किया? – kch

+2

यदि आप $$ पर अलग-अलग कॉल करते हैं तो यह सही काम नहीं करता है। लेकिन फिर, अलग-अलग ज़ोंबी प्रक्रियाओं से बचने के लिए है। पृष्ठभूमि में नौकरी चलाने के लिए जरूरी नहीं है। –

2

अन्य उत्तर अच्छे हैं यदि आप सुनिश्चित हैं कि आप बच्चे की प्रक्रिया को अलग करना चाहते हैं। हालांकि, अगर आपको कोई फर्क नहीं पड़ता है, या बच्चे की प्रक्रिया को संलग्न रखना पसंद करेंगे (उदा। यदि आप एक वेब अनुप्रयोग के लिए उप-सर्वर/सेवाओं लॉन्च कर रहे हैं), तो आप निम्नलिखित आशुलिपि

fork do 
    exec('whatever --option-flag') 
end 

बच्चे की प्रक्रिया में है कि ब्लॉक (और केवल कि ब्लॉक) निष्पादित करने के लिए कांटा बताता है एक ब्लॉक प्रदान का लाभ ले सकते, जबकि माता-पिता में जारी है।

0

मुझे ऊपर दिए गए उत्तरों को मेरे टर्मिनल को तोड़ दिया और आउटपुट को गड़बड़ कर दिया। यह समाधान मैंने पाया है।

system("nohup ./test.sh &") 

सिर्फ मामले में किसी को भी एक ही मुद्दा है, मेरा लक्ष्य एक ssh सर्वर में प्रवेश करने और फिर उस प्रक्रिया को अनिश्चित काल के चालू रखने था। तो test.sh यह

#!/usr/bin/expect -f 
spawn ssh host -l admin -i cloudkey 
expect "pass" 
send "superpass\r" 
sleep 1000000 
संबंधित मुद्दे