12

HTTPサーバーを埋め込む必要があるデーモンに取り組んでいます。BaseHTTPServerで実行しようとしています。フォアグラウンドで実行すると正常に動作しますが、デーモンをバックグラウンドにフォークしようとすると動作を停止します。私のメインアプリケーションは引き続き機能しますが、BaseHTTPServerは機能しません。

これは、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がフォークされたバックグラウンドデーモンに表示され、フォーク後にコードをヒットしています。

4

6 に答える 6

8

少しグーグルした後、私はついにこのBaseHTTPServerのドキュメントに出くわし、その後、次のようになりました。

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

ほとんどの場合、これは私がフォークして問題を解決した後に発生します。

于 2009-05-20T21:17:13.127 に答える
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ファイルを書き込んだりすることができます。ただし、それはすべて質問の範囲外です。

特に、質問の範囲外です。デーモンプロセスになると(必要に応じて制御端末から切り離されます)、デーモンプロセスを停止するにはどうすればよいですか?プログラムの動作を定義する一環として、それを決定するのはあなた次第です。

于 2010-02-11T23:13:09.603 に答える
2

HTTPServerをインスタンス化することから始めます。ただし、提供されたコードのいずれかでサービスを開始するように実際に指示することはありません。子プロセスで、を呼び出してみてくださいserver.serve_forever()

参考のためにこれを参照してください

于 2009-05-20T17:06:00.043 に答える
1

私にとってうまくいった簡単な解決策は、BaseHTTPRequestHandlerメソッドをオーバーライドすることでしlog_message()た。そのため、stdoutでの書き込みを防ぎ、デモンストレーション時の問題を回避します。

class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

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

...
rest of custom class code
...
于 2011-12-20T15:58:56.323 に答える
0

独自のデーモン化プロセスを実行する代わりに、 daemontoolsまたは他の同様のスクリプトを使用するだけです。これをスクリプトから除外することをお勧めします。

また、最善のオプション:BaseHTTPServerを使用しないでください。本当に悪いです。Python用の優れたHTTPサーバーはたくさんあります。つまり、cherrypypasteです。どちらにも、すぐに使用できるデーモン化スクリプトが含まれています。

于 2009-05-20T16:15:36.230 に答える
0

もともと投稿してから回答を募っていたので、ちょっと情報を共有したいと思いました。

出力の問題は、ロギングモジュールのデフォルトハンドラーがStreamHandlerを使用するという事実に関係しています。これを処理する最良の方法は、独自のハンドラーを作成することです。デフォルトのロギングモジュールを使用する場合は、次のようにすることができます。

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

また、この時点で、組み込みhttpサーバーに非常に優れたTornadoプロジェクトを使用するようになりました。

于 2010-02-13T05:07:24.410 に答える