2011-12-31 15 views
25

मैंने हाल ही में वेब विकास के लिए पायथन का उपयोग करने के साथ प्रयोग करना शुरू कर दिया है। अब तक मुझे अपाचे का उपयोग mod_wsgi और पायथन 2.7 के लिए Django वेब ढांचे के साथ कुछ सफलता मिली है। हालांकि मैंने कुछ मुद्दों में भाग लिया है जिसमें प्रक्रियाएं लगातार चल रही हैं, सूचनाएं अपडेट कर रही हैं।मैं लंबी अवधि (अनंत) पायथन प्रक्रिया कैसे चला सकता हूं?

मैंने एक स्क्रिप्ट लिखी है जिसे मैं "daemonManager.py" कहता हूं जो सभी या व्यक्तिगत पायथन अपडेट लूप को शुरू और बंद कर सकता है (क्या मुझे उन्हें डेमन्स कहा जाना चाहिए?)। यह फोर्किंग द्वारा करता है, फिर मॉड्यूल को विशिष्ट कार्यों के लिए लोड करना चाहिए जो इसे चलाना चाहिए और एक अनंत लूप शुरू करना चाहिए। यह प्रक्रिया का ट्रैक रखने के लिए /var/run में एक पीआईडी ​​फ़ाइल सहेजता है। अब तक सब ठीक है। जिन समस्याओं का सामना मैंने किया है वे हैं:

  • अब और फिर प्रक्रियाओं में से एक अभी निकल जाएगी। मैं सुबह ps की जांच करता हूं और प्रक्रिया अभी खत्म हो गई है। कोई त्रुटि लॉग नहीं हुई थी (मैं logging मॉड्यूल का उपयोग कर रहा हूं), और मैं उन सभी अपवादों को कवर कर रहा हूं जिन्हें मैं सोच सकता हूं और उन्हें लॉगिंग कर सकता हूं। साथ ही मुझे नहीं लगता कि इन छोड़ने की प्रक्रियाओं में मेरे कोड के साथ कुछ भी करना है, क्योंकि मेरी सभी प्रक्रियाएं पूरी तरह से अलग कोड चलाती हैं और बहुत ही समान अंतराल पर बाहर निकलती हैं। हो सकता है मै गलत हूँ। क्या पाइथन प्रक्रियाओं के लिए दिन/सप्ताह के लिए दौड़ने के बाद यह मरना सामान्य है? मुझे इस समस्या से कैसे निपटना चाहिए? क्या मुझे एक और डिमन लिखना चाहिए जो समय-समय पर जांच करता है कि अन्य डिमन्स अभी भी चल रहे हैं या नहीं? क्या होगा यदि वह डिमन बंद हो जाए? मैं इसे संभालने के तरीके पर एक नुकसान में हूँ।

  • मैं प्रोग्राम प्रोग्रामिक रूप से कैसे जान सकता हूं कि कोई प्रक्रिया अभी भी चल रही है या नहीं? मैं /var/run में पीआईडी ​​फाइलों को सहेज रहा हूं और जांच रहा हूं कि पीआईडी ​​फाइल यह निर्धारित करने के लिए है कि प्रक्रिया चल रही है या नहीं। लेकिन अगर प्रक्रिया अप्रत्याशित कारणों से मर जाती है, तो पीआईडी ​​फाइल बनी रहेगी। इसलिए जब भी एक प्रक्रिया दुर्घटनाग्रस्त हो जाती है (प्रति सप्ताह दो बार), तो इस तरह के उद्देश्य को हराने के लिए इन फ़ाइलों को हटाना होगा। मुझे लगता है कि मैं जांच सकता हूं कि फाइल में पीआईडी ​​पर कोई प्रक्रिया चल रही है, लेकिन क्या होगा यदि कोई और प्रक्रिया शुरू हो गई है और मृत प्रक्रिया के पीआईडी ​​को सौंपा गया है? मेरा डिमन सोचता है कि यह प्रक्रिया ठीक चल रही है भले ही यह लंबे समय तक मर जाए। फिर मैं इस बात से निपटने के लिए एक नुकसान में हूं।

सबसे अच्छा रन अनंत अजगर प्रक्रियाओं के लिए, उम्मीद है कि यह भी उपर्युक्त समस्याओं पर कुछ प्रकाश बहा, मैं


मैं अपाचे 2.2.14 उपयोग कर रहा हूँ पर स्वीकार करने पर कोई उपयोगी जवाब एक उबंटू मशीन।
मेरा पायथन संस्करण 2.7.2

+0

यदि आप क्रैश होने वाले डेमन्स के लिए कोड दिखाते हुए कुछ कोड नमूने जोड़ते हैं, तो हम विशिष्टताओं को संबोधित करने में सक्षम हो सकते हैं। सबसे पहले बात यह है कि, मैं आपकी स्क्रिप्ट से सभी कोड हटा दूंगा जो फोर्किंग, मॉनिटरिंग, रीडायरेक्शन इत्यादि से निपटते हैं। –

+0

क्या आप यह स्पष्ट कर सकते हैं कि क्या आप इन डीमन प्रक्रियाओं को डब्ल्यूएसजीआई एप्लिकेशन से mod_wsgi या अलग से चल रहे हैं। आपको mod_wsgi के तहत चल रहे किसी एप्लिकेशन से ऐसी प्रक्रिया निर्माण नहीं करनी चाहिए। –

+0

बहुत सारे प्रचार की तरह लगता है कि यहां जा रहा है। मेरा मतलब है, यह एक अच्छी तरह से सवाल है, जिस पर एक विशिष्ट तकनीक को एक उत्तर दिया जाता है, जिसके लिए एक और उत्तर दिया जाता है जिसमें इसे फिर से उत्तर दिया जाता है "मैं अभी भी एक और (प्रतिस्पर्धी?) तकनीक का उपयोग कर समाप्त हुआ ... – citn

उत्तर

24

मैं यह कहकर खुलेगा कि यह एक एक लंबी चल रही प्रक्रिया (एलआरपी) का प्रबंधन करने के लिए तरीका है - किसी भी खिंचाव से वास्तव में नहीं।

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

मेरा पसंदीदा समाधान http://supervisord.org/

है supervisord की तरह एक प्रणाली का उपयोग करके आप मूल रूप से एक पारंपरिक अजगर स्क्रिप्ट है कि एक कार्य करते समय एक "अनंत" पाश में फंस करता लिखें।

#!/usr/bin/python 

import sys 
import time 

def main_loop(): 
    while 1: 
     # do your stuff... 
     time.sleep(0.1) 

if __name__ == '__main__': 
    try: 
     main_loop() 
    except KeyboardInterrupt: 
     print >> sys.stderr, '\nExiting by user request.\n' 
     sys.exit(0) 

अपनी स्क्रिप्ट लेखन इस तरह से यह सरल और सुविधाजनक विकसित करने के लिए और डिबग (आप आसानी से शुरू कर सकते हैं/टर्मिनल में इसे रोकने, लॉग उत्पादन देख के रूप में की घटनाओं उधेड़ना) बनाता है। जब उत्पादन में फेंकने का समय आता है, तो आप बस एक पर्यवेक्षक कॉन्फ़िगरेशन को परिभाषित करते हैं जो आपकी स्क्रिप्ट को कॉल करता है (यहां "प्रोग्राम" को परिभाषित करने के लिए पूर्ण उदाहरण है, जिनमें से अधिक वैकल्पिक है: http://supervisord.org/configuration.html#program-x-section-example)।

पर्यवेक्षक विन्यास विकल्पों में से एक गुच्छा है तो मैं उन्हें बताना नहीं होगा, लेकिन मैं कहना है कि यह विशेष रूप से समस्याओं को आप का वर्णन हल करती है:

  • backgrounding/Daemonizing
  • पीआईडी ​​ट्रैकिंग (कर सकते हैं किसी प्रक्रिया को पुनरारंभ करने के लिए कॉन्फ़िगर किया जाना चाहिए, इसे अप्रत्याशित रूप से समाप्त करना चाहिए)
  • सामान्य रूप से अपनी स्क्रिप्ट में लॉग ऑन करें (स्ट्रीमिंग के बजाय लॉगिंग मॉड्यूल का उपयोग करते हुए स्ट्रीम हैंडलर) लेकिन पर्यवेक्षक को आपके लिए एक फ़ाइल पर रीडायरेक्ट करने दें।
+0

मैंने अपने स्वयं के डिमनोइज़ समाधान को डंप कर दिया क्योंकि यह पता चला कि मेरे पास इस विषय पर पर्याप्त अनुभव नहीं है। मैं [हमेशा के लिए nodejitsu] (https://github.com/nodejitsu/forever) का उपयोग करके समाप्त हुआ जो कि एक स्वादिष्ट नो-कॉन्फिगर-आवश्यक है (लेकिन कॉन्फ़िगरेशन के बहुत सारे संभव) एप्लिकेशन जहां आपको निष्पादन योग्य और तर्क निर्दिष्ट करने की आवश्यकता है, और स्क्रिप्ट क्रैश होने पर पुनरारंभ करने के लिए हमेशा के लिए एक डेमन के रूप में चलाएगा। मैंने स्वचालित आउटपुट-लॉग की जांच करके कुछ लंबी चल रही बग भी हल की। मैं आपके उत्तर को स्वीकार कर रहा हूं क्योंकि मेरे समाधान के सबसे नज़दीकी – Hubro

+0

क्या पर्यवेक्षक आपकी स्क्रिप्ट को मैन्युअल रूप से बाहर निकलने के बाद आपकी स्क्रिप्ट को पुनरारंभ करेंगे? –

+1

@ जैकोबुड जब पर्यवेक्षक बाहर निकलने वाली प्रक्रिया का प्रबंधन कर रहा है ('sys.exit()' के माध्यम से, एक अपरिचित अपवाद, या यदि स्क्रिप्ट अन्यथा इसके अंत तक पहुंच जाती है - शायद कोई लूप नहीं था?), यह इसे पुनरारंभ करने का प्रयास करेगा। प्रयास करने के प्रयासों को पुन: प्रारंभ करने की संख्या को नियंत्रित करने के लिए सेटिंग्स हैं, और प्रयासों के बीच में कितना इंतजार करना है। एक बार सभी प्रयासों का खर्च हो जाने के बाद, यह हार जाएगा। यदि आप चल रहे नौकरी को रोकना चाहते हैं, तो आपको इसे बंद करने के लिए पर्यवेक्षक का उपयोग करना चाहिए। –

2

मुझे लगता है कि आप यूनिक्स/लिनक्स चला रहे हैं लेकिन आप वास्तव में नहीं कहते हैं। मुझे आपकी समस्या पर कोई सीधी सलाह नहीं है। तो मुझे इस सवाल का "सही" जवाब होने की उम्मीद नहीं है। लेकिन यहां तलाशने के लिए कुछ है।

सबसे पहले, यदि आपके डिमांड क्रैश हो रहे हैं, तो आपको इसे ठीक करना चाहिए। केवल बग के साथ प्रोग्राम क्रैश होना चाहिए। शायद आपको उन्हें डीबगर के तहत लॉन्च करना चाहिए और देखें कि क्या होता है जब वे दुर्घटनाग्रस्त होते हैं (यदि यह संभव है)। क्या आपके पास इन प्रक्रियाओं में कोई निशान लॉगिंग है? यदि नहीं, तो उन्हें जोड़ें। इससे आपके दुर्घटना का निदान करने में मदद मिल सकती है।

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

तीसरा, फ़ाइल में पीआईडी ​​को सहेजना बहुत प्रभावी नहीं है, जैसा आपने पाया है। शायद एक साझा आईपीसी, एक सेमफोर की तरह, बेहतर काम करेगा। हालांकि मेरे पास यहां कोई विवरण नहीं है।

चौथा, कभी-कभी मुझे वेबसाइट के संदर्भ में चलाने के लिए सामान की आवश्यकता होती है। मैं एक क्रॉन प्रक्रिया का उपयोग करता हूं जो एक रखरखाव यूआरएल के साथ wget कहते हैं। आप एक विशेष कुकी सेट करते हैं और कुकी जानकारी को wget कमांड लाइन के साथ शामिल करते हैं। यदि विशेष कुकी मौजूद नहीं है, तो रखरखाव प्रक्रिया करने के बजाए 403 लौटें। यहां अन्य लाभ डेटाबेस में लॉगिन है और अन्य पर्यावरणीय चिंताओं से बचा है क्योंकि सामान्य वेब पेज परोसने वाले कोड रखरखाव प्रक्रिया की सेवा कर रहे हैं।

आशा है कि आपको विचार दें। मुझे लगता है कि अगर आप शुरू करने के लिए सबसे अच्छी जगह कर सकते हैं तो डेमन्स से परहेज करना। यदि आप mod_wsgi के भीतर अपना पायथन चला सकते हैं जो आपको कई "वातावरण" का समर्थन करने के लिए बचाता है। ऐसी प्रक्रिया को डीबग करना जो एक समय में दिनों के लिए दौड़ने में विफल रहता है, केवल क्रूर है।

+1

में सलाह देने के लिए पर्याप्त सलाह देता हूं, अच्छी सलाह के लिए धन्यवाद। मैं निर्दिष्ट करता हूं कि मैं रास्ते से उबंटू चला रहा हूं :) – Hubro

+0

ओह, अंत में। इसे नहीं देखा – jmucchiello

2

आप "हमेशा के लिए" चलाने के लिए यह सोचते हैं कि आप अपने कार्यक्रम, पायथन दुभाषिया, या कि आप प्रयोग कर रहे हैं अजगर पुस्तकालयों/मॉड्यूल में से किसी में किसी भी मेमोरी लीक नहीं है में सक्षम के रूप में अजगर प्रक्रियाओं पर विचार करना चाहिए। (यहां तक ​​कि मेमोरी लीक के चेहरे में भी, यदि आप 64-बिट मशीन पर पर्याप्त स्वैप स्पेस रखते हैं तो आप हमेशा के लिए दौड़ सकते हैं। दशकों, यदि सदियों से नहीं, तो करने योग्य होना चाहिए। मेरे पास पाइथन प्रक्रियाएं लगभग ठीक से जीवित रहती हैं सीमित हार्डवेयर पर दो साल - हार्डवेयर को स्थानांतरित करने से पहले।)

सुनिश्चित करना कार्यक्रमों को पुनः आरंभ डाई जब वे जब लिनक्स वितरण SysV-style init इस्तेमाल किया वापस बहुत सरल हुआ करता था - तुम सिर्फ /etc/inittab और init(8) को एक नई लाइन जोड़ने के बूट और फिर से अंडे यह अगर यह मर जाता है पर अपने कार्यक्रम अंडे जाएगा। (मुझे इस कार्यक्षमता को नए upstartinit के साथ इस कार्यक्षमता को दोहराने के लिए कोई तंत्र नहीं है - यह पता नहीं है कि कई वितरण इन दिनों उपयोग कर रहे हैं। मैं यह नहीं कह रहा कि यह असंभव है, मुझे नहीं पता कि यह कैसे करना है।)

लेकिन यहां तक ​​कि init(8) वर्षों तक की व्यवस्था भी लचीली नहीं थी क्योंकि कुछ पसंद आएंगे। डीजेबी द्वारा daemontools पैकेज प्रक्रिया नियंत्रण-और-निगरानी उपकरणों का एक उदाहरण है जिसका उद्देश्य डेमॉन हमेशा के लिए रहना है। Linux-HA सुइट एक और समान टूल प्रदान करता है, हालांकि यह इस कार्य के लिए उचित होने के लिए बहुत अधिक "अतिरिक्त" कार्यक्षमता प्रदान कर सकता है। monit एक और विकल्प है।