在谷歌上搜索显示x2个代码片段。第一个结果是这个代码配方,它有很多文档和解释,以及下面一些有用的讨论。
然而,另一个代码示例虽然不包含这么多文档,但包含了传递启动、停止和重启等命令的示例代码。它还创建了一个PID文件,可以方便地检查守护进程是否已经在运行等。
这些示例都解释了如何创建守护进程。还有其他需要考虑的事情吗?一个样本比另一个更好吗?为什么?
在谷歌上搜索显示x2个代码片段。第一个结果是这个代码配方,它有很多文档和解释,以及下面一些有用的讨论。
然而,另一个代码示例虽然不包含这么多文档,但包含了传递启动、停止和重启等命令的示例代码。它还创建了一个PID文件,可以方便地检查守护进程是否已经在运行等。
这些示例都解释了如何创建守护进程。还有其他需要考虑的事情吗?一个样本比另一个更好吗?为什么?
当前回答
当前的解决方案
PEP 3143(标准守护进程库)的参考实现现在作为python-daemon提供。
历史的答案
Sander Marechal的代码样例优于2004年发布的原始代码。我曾经为Pyro贡献了一个daemonizer,但如果我必须重新做的话,可能会使用Sander的代码。
其他回答
YapDi是一个python包。它可用于从脚本内部将python脚本转换为守护进程模式。
这个函数将应用程序转换为守护进程:
import sys
import os
def daemonize():
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open(os.devnull, 'w')
se = open(os.devnull, 'w')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
经过几年的努力和多次尝试(我尝试了这里给出的所有答案,但最后都有一些小缺点),现在我意识到有一种比直接从Python启动、停止和重新启动守护进程更好的方法:使用OS工具。
例如,对于Linux,我不做python myapp start和python myapp stop,而是这样启动应用程序:
screen -S myapp python myapp.py
# CTRL+A, D to detach
或者screen -dmS myapp python myapp.py在一个命令中启动和卸载它。
然后:
screen -r myapp
重新连接到这个终端。进入终端后,可以使用CTRL+C来停止它。
在python中进行daemonization时,还有一件需要考虑的事情:
如果您正在使用python日志记录,并且希望在守护进程完成后继续使用它,请确保在处理程序(特别是文件处理程序)上调用close()。
如果您不这样做,处理程序仍然可以认为它有文件打开,并且您的消息将简单地消失-换句话说,确保记录器知道它的文件是关闭的!
这假设当你守护进程时,你不加区别地关闭所有打开的文件描述符——相反,你可以尝试关闭除了日志文件以外的所有文件(但是关闭所有文件然后重新打开你想要的文件通常更简单)。
虽然你可能更喜欢Python -daemon模块提供的纯Python解决方案,但在libc中有一个daemon(3)函数——至少在BSD和Linux上是这样——它可以做正确的事情。
从python调用它很简单:
import ctypes
ctypes.CDLL(None).daemon(0, 0) # Read the man-page for the arguments' meanings
剩下要做的唯一一件事就是创建(和锁定)pid文件。但你能处理好自己…