在 Google 上搜索会显示 x2 代码片段。 第一个结果是这个代码配方,它有很多文档和解释,以及一些下面进行有用的讨论。
然而,另一个代码示例虽然不包含太多文档,但包含用于传递命令的示例代码,例如启动、停止和重新启动。 它还创建一个 PID 文件,可以方便地检查守护进程是否已经在运行等。
这些示例都解释了如何创建守护进程。 还有其他需要考虑的事情吗? 一个样本是否优于另一个样本,为什么?
Searching on Google reveals x2 code snippets. The first result is to this code recipe which has a lot of documentation and explanation, along with some useful discussion underneath.
However, another code sample, whilst not containing so much documentation, includes sample code for passing commands such as start, stop and restart. It also creates a PID file which can be handy for checking if the daemon is already running etc.
These samples both explain how to create the daemon. Are there any additional things that need to be considered? Is one sample better than the other, and why?
发布评论
评论(16)
当前解决方案
PEP 3143(标准守护进程库)的参考实现) 现在作为 python-daemon 提供。
历史答案
Sander Marechal 的 代码示例优于原始代码,原始代码最初发布于 2004 年。我曾经为 Pyro 贡献过一个守护程序,但如果我必须重新做的话,可能会使用 Sander 的代码。
Current solution
A reference implementation of PEP 3143 (Standard daemon process library) is now available as python-daemon.
Historical answer
Sander Marechal's code sample is superior to the original, which was originally posted in 2004. I once contributed a daemonizer for Pyro, but would probably use Sander's code if I had to do it over.
成为 许多繁琐的事情需要处理="noreferrer">行为良好的守护进程:
防止核心转储(许多守护进程以 root 身份运行,核心转储可能包含敏感信息)
在 内正确运行
chroot
gaol设置 UID、GID、适合用例的工作目录、umask 和其他流程参数
放弃提升的
suid
、sgid
权限关闭所有打开的文件描述符,并根据用例进行排除
如果在已经分离的上下文中启动,例如
init
、inetd
等,则行为正确。< /p>为合理的守护进程行为设置信号处理程序,但也使用特定的处理程序由用例决定
重定向标准流
stdin
,stdout
,stderr 因为守护进程不再有控制终端
将 PID 文件作为协作进程处理咨询锁,本身就是一个蠕虫 有许多矛盾但有效的行为方式
允许在进程终止时进行适当的清理
实际上成为守护进程,而不会导致僵尸< /p>
其中一些是标准 ,如规范 Unix 文献中所述(UNIX 环境中的高级编程,已故 W. Richard Stevens,Addison-Wesley,1992 年)。 其他,例如流重定向和 PID 文件处理 ,是大多数守护程序用户所期望的常规行为,但标准化程度较低。
所有这些都包含在PEP 3143“标准守护进程库”中” 规范。 python-daemon 参考实现适用于 Python 2.7 或更高版本以及 Python 3.2 或更高版本。
There are many fiddly things to take care of when becoming a well-behaved daemon process:
prevent core dumps (many daemons run as root, and core dumps can contain sensitive information)
behave correctly inside a
chroot
gaolset UID, GID, working directory, umask, and other process parameters appropriately for the use case
relinquish elevated
suid
,sgid
privilegesclose all open file descriptors, with exclusions depending on the use case
behave correctly if started inside an already-detached context, such as
init
,inetd
, etc.set up signal handlers for sensible daemon behaviour, but also with specific handlers determined by the use case
redirect the standard streams
stdin
,stdout
,stderr
since a daemon process no longer has a controlling terminalhandle a PID file as a cooperative advisory lock, which is a whole can of worms in itself with many contradictory but valid ways to behave
allow proper cleanup when the process is terminated
actually become a daemon process without leading to zombies
Some of these are standard, as described in canonical Unix literature (Advanced Programming in the UNIX Environment, by the late W. Richard Stevens, Addison-Wesley, 1992). Others, such as stream redirection and PID file handling, are conventional behaviour most daemon users would expect but that are less standardised.
All of these are covered by the PEP 3143 “Standard daemon process library” specification. The python-daemon reference implementation works on Python 2.7 or later, and Python 3.2 or later.
这是我在开发新的守护程序应用程序时开始使用的基本“Howdy World”Python 守护程序。
请注意,您将需要
python-daemon
库。 您可以通过以下方式安装它:然后只需使用
./howdy.py start
启动它,并使用./howdy.py stop
停止它。Here's my basic 'Howdy World' Python daemon that I start with, when I'm developing a new daemon application.
Note that you'll need the
python-daemon
library. You can install it by:Then just start it with
./howdy.py start
, and stop it with./howdy.py stop
.另一种选择——创建一个普通的、非守护进程的 Python 程序,然后使用 supervisord 在外部对其进行守护进程。 这可以避免很多麻烦,并且是 *nix 和语言可移植的。
An alternative -- create a normal, non-daemonized Python program then externally daemonize it using supervisord. This can save a lot of headaches, and is *nix- and language-portable.
请注意 python-daemon 包,它解决了开箱即用的守护进程背后的许多问题。
除其他功能外,它还可以(来自 Debian 软件包描述):
Note the python-daemon package which solves a lot of problems behind daemons out of the box.
Among other features it enables to (from Debian package description):
可能不是问题的直接答案,但 systemd 可用于将应用程序作为守护进程运行。 这是一个示例:
我更喜欢这种方法,因为很多工作都为您完成,然后您的守护程序脚本的行为与系统的其余部分类似。
Probably not a direct answer to the question, but systemd can be used to run your application as a daemon. Here is an example:
I prefer this method because a lot of the work is done for you, and then your daemon script behaves similarly to the rest of your system.
该函数会将应用程序转换为守护进程:
This function will transform an application to a daemon:
YapDi 是一个 python 包。 它可用于将 python 脚本从脚本内部转换为守护进程模式。
YapDi is a python package. It can be used to convert a python script into daemon mode from inside the script.
由于 python-daemon 尚未支持 python 3.x,并且从邮件列表上可以看到,它可能永远不会支持,我编写了 PEP 3143 的新实现: python.org/pypi/pep3143daemon" rel="noreferrer">pep3143daemon
pep3143daemon 应该至少支持 python 2.6、2.7 和 3.x
它还包含一个 PidFile 类。
该库仅依赖于标准库和六个模块。
它可以用作 python-daemon 的替代品。
这是文档。
since python-daemon has not yet supported python 3.x, and from what can be read on the mailing list, it may never will, i have written a new implementation of PEP 3143: pep3143daemon
pep3143daemon should support at least python 2.6, 2.7 and 3.x
It also contains a PidFile class.
The library only depends on the standard library and on the six module.
It can be used as a drop in replacement for python-daemon.
Here is the documentation.
我担心@Dustin 提到的守护进程模块对我不起作用。 相反,我安装了 python-daemon 并使用了以下代码:
运行很容易
为了完整性, 这里是samplemodule目录内容
moduleclass.py的内容可以是
I am afraid the daemon module mentioned by @Dustin didn't work for me. Instead I installed python-daemon and used the following code:
Running is easy
just for completeness here is samplemodule directory content
The content of moduleclass.py can be
在 python 中进行守护进程时还需要考虑一件事:
如果您正在使用 python logging 并且希望在守护进程之后继续使用它,请确保调用
close()
处理程序(特别是文件处理程序)。如果您不这样做,处理程序仍然可以认为它打开了文件,并且您的消息将消失 - 换句话说,确保记录器知道其文件已关闭!
这假设当您守护进程时,您将不加区别地关闭所有打开的文件描述符 - 相反,您可以尝试关闭除日志文件之外的所有文件(但通常关闭所有文件然后重新打开您想要的文件描述符更简单)。
One more to thing to think about when daemonizing in python:
If your are using python logging and you want to continue using it after daemonizing, make sure to call
close()
on the handlers (particularly the file handlers).If you don't do this the handler can still think it has files open, and your messages will simply disappear - in other words make sure the logger knows its files are closed!
This assumes when you daemonise you are closing ALL the open file descriptors indiscriminatingly - instead you could try closing all but the log files (but it's usually simpler to close all then reopen the ones you want).
尽管您可能更喜欢 python-daemon 模块提供的纯 Python 解决方案,但
libc
中有一个daemon(3)
函数——至少在 BSD 和 Linux ——这会做正确的事情。从 python 调用它很简单:
唯一剩下的事情就是创建(和锁定)PID 文件。 但前提是你自己能处理好...
Though you may prefer the pure Python solution provided by the python-daemon module, there is a
daemon(3)
function inlibc
-- at least, on BSD and Linux -- which will do the right thing.Calling it from python is easy:
The only remaining thing to do is creation (and locking) of the PID-file. But that you can handle yourself...
我修改了 Sander Marechal 的代码示例中的几行(@JeffBauer 在 接受的答案 中提到)以添加
quit()
方法,在守护进程停止之前执行。 这有时非常有用。就是这里。
注意:我不使用“python-daemon”模块,因为文档仍然缺失(另请参阅许多其他 SO 问题)并且相当晦涩(如何使用此模块从命令行正确启动/停止守护进程?)
I modified a few lines in Sander Marechal's code sample (mentioned by @JeffBauer in the accepted answer) to add a
quit()
method that gets executed before the daemon is stopped. This is sometimes very useful.Here it is.
Note: I don't use the "python-daemon" module because the documentation is still missing (see also many other SO questions) and is rather obscure (how to start/stop properly a daemon from command line with this module?)
经过几年和多次尝试(我尝试了这里给出的所有答案,但最终都有一些小缺点),现在我意识到有一种比直接从 Python 启动、停止、重新启动守护进程更好的方法:改用操作系统工具。
例如,对于 Linux,我不执行
python myapp start
和python myapp stop
,而是执行以下操作来启动应用程序:或
screen -dmS myapp python myapp. py
到用一个命令启动并分离它。然后:
再次连接到该终端。 进入终端后,可以使用 CTRL+C 来停止它。
After a few years and many attempts (I tried all the answers given here, but all of them had minor drawbacks at the end), now I realize that there is a better way than wanting to start, stop, restart a daemon directly from Python: use the OS tools instead.
For example, for Linux, instead of doing
python myapp start
andpython myapp stop
, I do this to start the app:or
screen -dmS myapp python myapp.py
to start and detach it in one command.Then:
to attach to this terminal again. Once in the terminal, it's possible to use CTRL+C to stop it.
使用 Python 创建守护程序的最简单方法是使用 Twisted 事件驱动框架。 它为您处理守护进程所需的所有内容。 它使用反应器模式来处理并发请求。
The easiest way to create daemon with Python is to use the Twisted event-driven framework. It handles all of the stuff necessary for daemonization for you. It uses the Reactor Pattern to handle concurrent requests.
80% 的情况下,当人们说“守护进程”时,他们只想要一个服务器。 由于问题在这一点上完全不清楚,因此很难说答案的可能范围是什么。 既然服务器就足够了,那就从那里开始吧。 如果确实需要一个实际的“守护进程”(这种情况很少见),请阅读
nohup
作为守护服务器的一种方法。在实际需要实际守护进程之前,只需编写一个简单的服务器即可。
另请参阅 WSGI 参考 实现。
另请参阅简单 HTTP 服务器。
“还有其他需要考虑的事情吗?” 是的。 大约一百万件事。 什么协议? 有多少请求? 服务每个请求需要多长时间? 他们多久到达一次? 您会使用专用流程吗? 线程? 子流程? 编写守护进程是一项艰巨的工作。
80% of the time, when folks say "daemon", they only want a server. Since the question is perfectly unclear on this point, it's hard to say what the possible domain of answers could be. Since a server is adequate, start there. If an actual "daemon" is actually needed (this is rare), read up on
nohup
as a way to daemonize a server.Until such time as an actual daemon is actually required, just write a simple server.
Also look at the WSGI reference implementation.
Also look at the Simple HTTP Server.
"Are there any additional things that need to be considered? " Yes. About a million things. What protocol? How many requests? How long to service each request? How frequently will they arrive? Will you use a dedicated process? Threads? Subprocesses? Writing a daemon is a big job.