python 守护python的BaseHTTPServer
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/888834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Daemonizing python's BaseHTTPServer
提问by Gavin M. Roy
I am working on a daemon where I need to embed a HTTP server. I am attempting to do it with BaseHTTPServer, which when I run it in the foreground, it works fine, but when I try and fork the daemon into the background, it stops working. My main application continues to work, but BaseHTTPServer does not.
我正在开发一个需要嵌入 HTTP 服务器的守护进程。我正在尝试使用 BaseHTTPServer 来完成它,当我在前台运行它时,它工作正常,但是当我尝试将守护程序分叉到后台时,它停止工作。我的主应用程序继续工作,但 BaseHTTPServer 没有。
I believe this has something to do with the fact that BaseHTTPServer sends log data to STDOUT and STDERR. I am redirecting those to files. Here is the code snippet:
我相信这与 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()
Am I doing something wrong here or is BaseHTTPServer somehow prevented from becoming daemonized?
我在这里做错了什么还是 BaseHTTPServer 以某种方式阻止了守护进程?
Edit: Updated code to demonstrate the additional, previously missing code flow and that log.debug shows in my forked, background daemon I am hitting code after fork.
编辑:更新代码以演示额外的、以前缺少的代码流,并且 log.debug 显示在我的分叉后台守护程序中我在分叉后点击代码。
采纳答案by Gavin M. Roy
After a bit of googling I finally stumbled over this BaseHTTPServer documentationand after that I ended up with:
经过一番谷歌搜索,我终于偶然发现了这个 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()
Which for the most part comes after I fork and ended up resolving my problem.
这在大多数情况下是在我分叉并最终解决我的问题之后发生的。
回答by bignose
Here's how to do this with the python-daemonlibrary:
以下是使用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()
As usual for a daemon, you need to decide how you will interact with the program after it becomes a daemon. For example, you might register a systemd service, or write a PID file, etc. That's all outside the scope of the question though.
与守护进程一样,您需要决定在程序成为守护进程后如何与该程序交互。例如,您可能会注册一个 systemd 服务,或者编写一个 PID 文件等。不过,这些都超出了问题的范围。
回答by monowerker
回答by Carlos García
A simple solution that worked for me was to override the BaseHTTPRequestHandler
method log_message()
, so we prevent any kind of writing in stdout and avoid problems when demonizing.
一个对我有用的简单解决方案是覆盖BaseHTTPRequestHandler
method log_message()
,因此我们防止在标准输出中进行任何类型的写入并避免在妖魔化时出现问题。
class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def log_message(self, format, *args):
pass
...
rest of custom class code
...
回答by Gavin M. Roy
Since this has solicited answers since I originally posted, I thought that I'd share a little info.
自从我最初发布以来,这已经征求了答案,我想我会分享一些信息。
The issue with the output has to do with the fact that the default handler for the logging module uses the StreamHandler. The best way to handle this is to create your own handlers. In the case where you want to use the default logging module, you can do something like this:
输出问题与日志模块的默认处理程序使用 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)
Also at this point I have moved to using the very nice Tornadoproject for my embedded http servers.
同样在这一点上,我已经开始为我的嵌入式 http 服务器使用非常好的Tornado项目。
回答by nosklo
Just use daemontoolsor some other similar script instead of rolling your own daemonizing process. It is much better to keep this off your script.
只需使用daemontools或其他一些类似的脚本,而不是滚动您自己的守护进程。最好不要在脚本中使用它。
Also, your best option: Don't use BaseHTTPServer. It is really bad. There are many good HTTP servers for python, i.e. cherrypyor paste. Both includes ready-to-use daemonizing scripts.
此外,您最好的选择是:不要使用 BaseHTTPServer。这真的很糟糕。python有很多很好的HTTP服务器,即cherrypy或paste。两者都包括现成的守护程序脚本。