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

其他提示

下面是如何与蟒蛇守护库做到这一点:

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文件,等等。这是以外的所有问题的范围虽然。

您通过实例化的HttpServer启动。但你实际上并没有告诉它开始在任何提供的代码的服务。在你的子进程尝试调用server.serve_forever()

见本获得参考

这是为我工作的一个简单的解决办法是重写BaseHTTPRequestHandler方法log_message(),所以我们防止stdout中写的任何一种,并避免出现问题时妖魔化

class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

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

...
rest of custom class code
...

只需使用 守护进程工具 或其他类似的脚本,而不是滚动您自己的守护进程。最好将其从脚本中删除。

另外,你最好的选择:不要使用 BaseHTTPServer。这真的很糟糕。python 有很多好的 HTTP 服务器,即 樱桃皮 或者 粘贴. 。两者都包含现成的守护进程脚本。

由于这已征求答案,因为我最初发布,我以为我会分享一些信息。

与输出的问题有,对于日志模块的默认处理程序使用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服务器

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top