2015-11-19 22 views
5

Şu anda ilk python programımı yazıyorum (Python 2.6.6'da). Program, kullanıcının ortak komutlarını sağlayan bir sunucu üzerinde çalışan farklı uygulamaları başlatmayı ve durdurmayı kolaylaştırır (Linux sunucusundaki sistem hizmetlerini başlatma ve durdurma gibi).Bir işlemi nasıl başlatıp python'da arka plana nasıl yerleştirebilirim?

Bir uygulamanın başlangıç ​​komut ön planda kalır ve böylece p.communicate() sonsuza bekleyeceği,

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

sorundur tatbikata başlatma komut dosyalarını başlıyorum. Zaten startCommand'ın önünde "nohup startCommand &" kullanmayı denedim ama beklendiği gibi çalışmadı. bash komut dosyası benim piton kodundan

#!/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" 

denir:

Çözüm olarak şimdi uygulamanın başlangıç ​​komut dosyası çağırmak için aşağıdaki bash komut dosyasını kullanın.

yanlış şekilde subprocess.Popen mı ... Bu geçici çözüm mükemmel çalışır ama tüm python yapmayı tercih ediyorum? Görevimi sadece Python'da nasıl aktarabilirim?

+1

muhtemelen bir çift http://stackoverflow.com/questions/1196074/starting- python a-background-process-in-python – daTokenizer

+0

Sadece ihtiyaç duyulduğunda 'iletişim 'kullanın .. sonuçları kontrol etmeniz gerekmez mi? Sadece ondan kaçının ... – klashxx

+0

@klashxx: Sonuçlara ihtiyacım var. Bu benim problemim ... ("RUNNING modunda başlatılan sunucu" için çıkışı kontrol etmek gerekiyor ...) – Ronzo

cevap

1

İlk önce iletişimde Python komut dosyasını engellememek kolaydır ... iletişim kurmayarak! Sadece doğru mesajı bulana kadar komuttan çıkan çıktı veya hata çıktısını okuyun ve sadece komutu unutun.

# 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 

yukarıdaki sorun, sunucu hala Python sürecinin bir çocuk ve böyle SIGHUP olarak istenmeyen sinyalleri alabilir olmasıdır. Bunu bir daemon yapmak istiyorsanız, önce sunucunuzu başlatan bir alt işlem başlatmalısınız. Bu şekilde, ilk çocuk bittiğinde, arayan tarafından beklenebilir ve sunucu 1 (bir PPID) kazanacaktır (init işlemi ile kabul edilir).

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() 

Bir dosya nesnesi kendisi de bir satır döndüren Yineleyicinin getlines jeneratör ihtiyacı ne olduğunu merak olabilir: Sen

Kod gibi olabilir Bu bölümü kolaylaştırmak için çoklu işlem modülünü kullanabilirsiniz zaman. Sorun, dahili olarak bir terminale bağlanmadığında EOF olana kadar okunan read numaralı telefonu çağırmasıdır. Şimdi bir BORU'a bağlı olduğu gibi, sunucu bitene kadar hiçbir şey almayacaksınız ... hangi değil nedir

+0

Mükemmel! Cevabınız için çok teşekkür ederim. Şimdi tam olarak nasıl yapacağımı biliyorum! – Ronzo

İlgili konular