2015-11-19 6 views
5

私は最初のPythonプログラム(Python 2.6.6)を書いています。このプログラムは、ユーザーの共通コマンド(Linuxサーバー上でシステム・サービスの開始および停止など)を提供するサーバー上で実行されているさまざまなアプリケーションの開始および停止を容易にします。プロセスを開始して、それをバックグラウンドにするにはどうすればいいですか?

は、私は1つのアプリケーションの起動スクリプトがフォアグラウンドに留まりのでp.communicateは、()永遠に待つこと、

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

問題があることにより、アプリケーションの起動スクリプトを始めています。私はすでにstartCommandの前で "nohup startCommand &"を使用しようとしましたが、期待どおりに動作しませんでした。

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

bashスクリプトは、私のPythonコードから呼び出されます。私は今、アプリケーションの起動スクリプトを呼び出すために、次のbashスクリプトを使用する回避策として

。この回避策は完璧に機能しますが、私はPythonですべてを行うことをお勧めします...

サブプロセスですか? Pythonで私の仕事をどうやって満足させることができますか?

+1

おそらくdstのhttp://stackoverflow.com/questions/1196074/starting- a-background-process-in-python – daTokenizer

+0

必要なときに 'communications'を使うだけです。結果を確認する必要はありませんか?ちょうどそれをavoit ... – klashxx

+0

@klashxx:私は結果が必要です。それは私の問題です...(サーバーが「実行モードで起動しました」の出力を確認する必要があります...) – Ronzo

答えて

1

最初に、コミュニケーションのPythonスクリプトをブロックしないようにしてください。正しいメッセージを見つけてコマンドを忘れるまで、コマンドの出力またはエラー出力から読み込みます。

# 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 

上記の問題は、サーバーがまだPythonプロセスの子であり、SIGHUPなどの不要な信号を受け取る可能性があることです。デーモンにしたい場合は、まずサーバーを次に起動するサブプロセスを開始する必要があります。こうすることで、最初の子が終了すると、呼び出し元が待機することができ、サーバーはPPIDを1にします(initプロセスによって採用されます)。

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

一つは、ファイルオブジェクトは、それ自体で1行を返すイテレータであるgetlines発電の必要性はあるのだろうことができます:あなたは

コードは次のように可能性があり、その部分を容易にするために、マルチプロセッシングモジュールを使用することができます時間。問題は、ファイルが端末に接続されていないときにEOFまで読み取るreadを内部的に呼び出していることです。今はPIPEに接続されているので、サーバが終了するまでは何も取得しません... ではない期待するものは

+0

パーフェクト!ご回答どうもありがとうございました。今私はそれを行う方法を正確に知っている! – Ronzo

関連する問題