2015-11-19 11 views
5

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

मैं, द्वारा

p = subprocess.Popen(startCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
output, err = p.communicate() 
print(output) 

समस्या है अनुप्रयोगों 'स्टार्टअप स्क्रिप्ट शुरू कर रहा हूँ कि एक आवेदन के स्टार्टअप स्क्रिप्ट अग्रभूमि में रहता है और इसलिए p.communicate() हमेशा के लिए इंतजार कर रहा है। मैंने शुरूआत के सामने "नोहप स्टार्ट कमांड &" का उपयोग करने की कोशिश की है लेकिन यह अपेक्षा के अनुसार काम नहीं करता है।

समाधान के लिए मैं अब निम्नलिखित बैश स्क्रिप्ट का उपयोग अनुप्रयोग की शुरुआत स्क्रिप्ट कॉल करने के लिए:

#!/bin/bash 

LOGFILE="/opt/scripts/bin/logs/SomeServerApplicationStart.log" 

nohup /opt/someDir/startSomeServerApplication.sh >${LOGFILE} 2>&1 & 

STARTUPOK=$(tail -1 ${LOGFILE} | grep "Server started in RUNNING mode" | wc -l) 
COUNTER=0 

while [ $STARTUPOK -ne 1 ] && [ $COUNTER -lt 100 ]; do 
    STARTUPOK=$(tail -1 logs/SomeServerApplicationStart.log | grep "Server started in RUNNING mode" | wc -l) 
    if ((STARTUPOK)); then 
     echo "STARTUP OK" 
     exit 0 
    fi 
    sleep 1 
    COUNTER=$(($COUNTER + 1)) 
done 

echo "STARTUP FAILED" 

बैश स्क्रिप्ट मेरे अजगर कोड से कहा जाता है। यह कामकाज सही काम करता है लेकिन मैं सभी को पाइथन में करना पसंद करूंगा ...

उपप्रोसेसर है। गलत तरीके से खोलें? मैं केवल अपने पायथन में अपना काम कैसे जमा कर सकता हूं?

+1

शायद http://stackoverflow.com/questions/1196074/starting- ए-बैकग्राउंड-प्रोसेस-इन-पायथन – daTokenizer

+0

जरूरी होने पर बस 'संवाद' का उपयोग करें .. आपको परिणामों की जांच करने की आवश्यकता नहीं है? बस इसे छोड़ दें ... – klashxx

+0

@klashxx: मुझे परिणामों की आवश्यकता है। यह मेरी समस्या है ... ("रनिंग मोड में सर्वर शुरू हुआ" के लिए आउटपुट की जांच करने की आवश्यकता है ...) – Ronzo

उत्तर

1

सबसे पहले यह आसान है कि पाइथन लिपि को संवाद में अवरुद्ध न करें ... संचार को कॉल न करें! जब तक आपको सही संदेश नहीं मिल जाता है और केवल कमांड को भूल जाते हैं, तब तक कमांड से आउटपुट या त्रुटि आउटपुट से पढ़ें।

# to avoid waiting for an EOF on a pipe ... 
def getlines(fd): 
    line = bytearray() 
    c = None 
    while True: 
     c = fd.read(1) 
     if c is None: 
      return 
     line += c 
     if c == '\n': 
      yield str(line) 
      del line[:] 

p = subprocess.Popen(startCommand, shell=True, stdout=subprocess.PIPE, 
       stderr=subprocess.STDOUT) # send stderr to stdout, same as 2>&1 for bash 
for line in getlines(p.stdout): 
    if "Server started in RUNNING mode" in line: 
     print("STARTUP OK") 
     break 
else: # end of input without getting startup message 
    print("STARTUP FAILED") 
    p.poll() # get status from child to avoid a zombie 
    # other error processing 

ऊपर के साथ समस्या यह है कि सर्वर अभी भी अजगर प्रक्रिया एक एक बच्चा है और इस तरह के रूप में SIGHUP अवांछित सिग्नल मिल सकता है। यदि आप इसे एक डिमन बनाना चाहते हैं, तो आपको पहले एक उपप्रोसेसर शुरू करना होगा जो आपके सर्वर को अगली बार शुरू करे। इस तरह जब पहला बच्चा खत्म हो जाएगा, तो उसे कॉलर द्वारा इंतजार किया जा सकता है और सर्वर को 1 का पीपीआईडी ​​मिलेगा (इनिट प्रक्रिया द्वारा अपनाया गया है)। आप वह हिस्सा कम करने के लिए बहु मॉड्यूल का उपयोग कर सकते हैं

कोड हो सकता है जैसे:

import multiprocessing 
import subprocess 

# to avoid waiting for an EOF on a pipe ... 
def getlines(fd): 
    line = bytearray() 
    c = None 
    while True: 
     c = fd.read(1) 
     if c is None: 
      return 
     line += c 
     if c == '\n': 
      yield str(line) 
      del line[:] 

def start_child(cmd): 
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 
         shell=True) 
    for line in getlines(p.stdout): 
     print line 
     if "Server started in RUNNING mode" in line: 
      print "STARTUP OK" 
      break 
    else: 
     print "STARTUP FAILED" 

def main(): 
    # other stuff in program 
    p = multiprocessing.Process(target = start_child, args = (server_program,)) 
    p.start() 
    p.join() 
    print "DONE" 
    # other stuff in program 

# protect program startup for multiprocessing module 
if __name__ == '__main__': 
    main() 

एक आश्चर्य हो सकता है क्या getlines जनरेटर जब किसी फ़ाइल वस्तु अपने आप में एक iterator है कि एक में एक पंक्ति रिटर्न है के लिए की जरूरत है पहर। समस्या यह है कि यह आंतरिक रूप से read पर कॉल करता है जो ईओएफ तक पढ़ता है जब फाइल टर्मिनल से कनेक्ट नहीं होती है। चूंकि यह अब एक पीआईपीई से जुड़ा हुआ है, आपको सर्वर समाप्त होने तक कुछ भी नहीं मिलेगा ...

+0

बिल्कुल सही! उत्तर देने के लिए आपका धन्यवाद। अब मुझे पता है कि यह कैसे करना है! – Ronzo

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

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