2009-05-20 3 views
9

私はHTTPサーバーを埋め込む必要のあるデーモンを開発中です。私はBaseHTTPServerでこれをやろうとしています。フォアグラウンドで実行するとうまくいきますが、デーモンをバックグラウンドでフォークしようとすると、動作しなくなります。私の主なアプリケーションは引き続き動作しますが、BaseHTTPServerは動作しません。pythonのBaseHTTPServerをDaemonizing

これは、BaseHTTPServerがログデータをSTDOUTとSTDERRに送信するということと関係していると思います。私はそれらをファイルにリダイレクトしています。ここでは、コードスニペットは次のとおりです。

# Start the HTTP Server 
server = HTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']),HTTPHandler) 

# Fork our process to detach if not told to stay in foreground 
if options.foreground is False: 
    try: 
     pid = os.fork() 
     if pid > 0: 
      logging.info('Parent process ending.') 
      sys.exit(0)    
    except OSError, e: 
     sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) 
     sys.exit(1) 

    # Second fork to put into daemon mode 
    try: 
     pid = os.fork() 
     if pid > 0: 
      # exit from second parent, print eventual PID before 
      print 'Daemon has started - PID # %d.' % pid 
      logging.info('Child forked as PID # %d' % pid) 
      sys.exit(0) 
    except OSError, e: 
     sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) 
     sys.exit(1) 


    logging.debug('After child fork') 

    # Detach from parent environment 
    os.chdir('/') 
    os.setsid() 
    os.umask(0) 

    # Close stdin  
    sys.stdin.close() 

    # Redirect stdout, stderr 
    sys.stdout = open('http_access.log', 'w') 
    sys.stderr = open('http_errors.log', 'w')  

# Main Thread Object for Stats 
threads = [] 

logging.debug('Kicking off threads') 

while ... 
    lots of code here 
... 

server.serve_forever() 

私はここで何か間違ったことをやっているかBaseHTTPServerは何とかデーモン化することが防止されますか?

編集:以前に見つからなかった追加のコードフローを示すコードが更新され、フォークバックされたバックグラウンドデーモンにlog.debugが表示されます。フォーク後にコードが表示されます。

答えて

7

ため

See thisその後、私はなってしまった:私はフォークと私の問題を解決してしまった後に大部分が来る

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 
from SocketServer import ThreadingMixIn 

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 
    """Handle requests in a separate thread.""" 

server = ThreadedHTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']), HTTPHandler) 
server.serve_forever() 

0

独自のデーモンプロセスを実行する代わりに、daemontoolsまたは他の同様のスクリプトを使用してください。これをあなたのスクリプトから離しておくほうがずっと良いです。

また、最良のオプション:BaseHTTPServerを使用しないでください。それは本当に悪いです。 Pythonには多くのHTTPサーバーがあります。つまり、cherrypyまたはpasteです。両方ともすぐに使えるデーモン化スクリプトが含まれています。

+1

なぜそれが悪いのですか?してください、これはGoogleのトップ結果の1つです...あまりにも驚くほど素晴らしいものになるので、httpのための事前ビルドされたPythonライブラリの膨大な量があります。 – nsij22

2

まず、HTTPServerのインスタンスを作成します。しかし、実際には、提供されたコードのいずれかでサービスを開始するように指示するわけではありません。あなたの子プロセスでserver.serve_forever()を呼び出してみてください。 I finally stumbled over this BaseHTTPServer documentationグーグルのビットの後に参照

+0

実際、私はフォークの後でそれを実行していました、そして、私のデバッグ出力によれば、2番目のフォークの後に、私はコードを打っています。 –

+0

あなたは正しいです。私は私の答えを編集しました。 – monowerker

4

はここpython-daemonライブラリでこれを行う方法は次のとおりです。

from BaseHTTPServer import (HTTPServer, BaseHTTPRequestHandler) 
import contextlib 

import daemon 

from my_app_config import config 

# Make the HTTP Server instance. 
server = HTTPServer(
    (config['HTTPServer']['listen'], config['HTTPServer']['port']), 
    BaseHTTPRequestHandler) 

# Make the context manager for becoming a daemon process. 
daemon_context = daemon.DaemonContext() 
daemon_context.files_preserve = [server.fileno()] 

# Become a daemon process. 
with daemon_context: 
    server.serve_forever() 

はデーモンのいつものように、あなたはそれがデーモンになった後、あなたがプログラムと対話する方法を決定する必要があります。たとえば、systemdサービスを登録したり、PIDファイルなどを書き込んだりすることができます。これはすべて問題の範囲外です。

+1

デーモンを起動するのに最適ですが、起動コマンドと停止コマンドでどのように使用しますか?これまで私はデーモンを止めることができませんでした。 – anno1337

+0

このデーモンはどのように停止しますか? – MohitC

0

これは私が最初に投稿して以来、回答を求めているので、私は少し情報を共有すると思った。

出力の問題は、ロギングモジュールのデフォルトハンドラがStreamHandlerを使用していることと関係があります。これを処理する最善の方法は、独自のハンドラを作成することです。私は私の組み込みhttpサーバのための非常に素晴らしいTornadoプロジェクトを使用して移動してきた、この時点でも

# Get the default logger 
default_logger = logging.getLogger('') 

# Add the handler 
default_logger.addHandler(myotherhandler) 

# Remove the default stream handler 
for handler in default_logger.handlers: 
    if isinstance(handler, logging.StreamHandler): 
     default_logger.removeHandler(handler) 

:デフォルトのロギングモジュールを使用したい場合、あなたはこのような何かを行うことができます。

1

BaseHTTPRequestHandlerメソッドlog_message()を上書きするという単純な解決策がありました。私たちはstdoutに何らかの書き込みを防止し、デーモン化する際に問題を回避します。

class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 

    def log_message(self, format, *args): 
      pass 

... 
rest of custom class code 
... 
関連する問題