代码之家  ›  专栏  ›  技术社区  ›  Gavin M. Roy

监控python的basehttpserver

  •  9
  • Gavin M. Roy  · 技术社区  · 17 年前

    我正在开发一个守护进程,我需要在其中嵌入一个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显示在我的分叉后台守护进程中,我正在一个接一个地点击代码。

    6 回复  |  直到 17 年前
        1
  •  7
  •   k0pernikus    11 年前

    我在谷歌上搜索了一下 finally stumbled over this BaseHTTPServer documentation 在那之后,我得到了:

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

    这在很大程度上是在我分叉并最终解决了我的问题之后发生的。

        2
  •  3
  •   bignose    10 年前

    以下是如何使用 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文件等,这些都超出了问题的范围。

        3
  •  2
  •   monowerker    17 年前

    首先实例化httpserver。但实际上您并没有告诉它开始在任何提供的代码中提供服务。在你孩子的过程中,试着打电话 server.serve_forever() .

    See this 供参考

        4
  •  1
  •   Carlos García    14 年前

    对于我来说,一个简单的解决方案是重写 BaseHTTPRequestHandler 方法 log_message() 因此,我们防止在stdout中写入任何类型的内容,并避免在妖魔化时出现问题。

    class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    
        def log_message(self, format, *args):
                pass
    
    ...
    rest of custom class code
    ...
    
        5
  •  0
  •   nosklo    17 年前

    只使用 daemontools 或者其他类似的脚本,而不是滚动自己的守护进程。最好不要在你的剧本上写这个。

    另外,最好的选择是:不要使用basehttpserver。真的很糟糕。有许多很好的针对python的HTTP服务器,即 cherrypy paste . 两者都包括准备好使用的后台监控脚本。

        6
  •  0
  •   Gavin M. Roy    16 年前

    自从我最初发表这篇文章以来,一直在征求答案,我想我会分享一些信息。

    输出的问题与日志模块的默认处理程序使用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)
    

    在这一点上,我已经开始使用非常好的 Tornado 我的嵌入式HTTP服务器的项目。

    推荐文章