正如@mark 澄清的那样,它是一个 Linux 系统,通过遵循这个recipe,脚本可以很容易地使自己完全独立,即一个守护进程。 (您也可以在 os.fork 之后在父进程中执行此操作,然后才在子进程 os.exec... 之后执行此操作。
编辑:澄清@mark对我的回答的评论的一些细节:根据食谱食谱“守护”进程不需要超级用户权限,也不需要更改当前工作目录(尽管配方中的代码确实做到了这一点,而且更多,这不是关键部分——而是fork、_exit 和setsid 调用的正确逻辑顺序)。不以e 结尾的各种os.exec... 变体 使用父进程的环境,因此这部分也很简单——参见Python online docs。
解决其他人的 cmets 和答案中提出的建议:我相信 subprocess 和 multiprocessing 本身不会守护子进程,这似乎是 @mark 需要的;脚本可以自己完成,但由于 一些 代码必须执行 forks 和 setsid,所以在我看来,将所有产卵都保持在低级平面上而不是而不是在运行过程中混合一些高级和一些低级代码。
在上面的 URL 中,这是一个大大简化和简化的配方版本,专为在父进程中调用以生成一个守护进程子进程而设计——这样,代码也可以用于执行非 Python 可执行文件。如给定的那样,代码应该满足@mark 解释的需求,当然它可以通过多种方式进行定制——我强烈建议阅读原始配方及其 cmets 和讨论,以及它推荐的书籍,以获取更多信息。
import os
import sys
def spawnDaemon(path_to_executable, *args)
"""Spawn a completely detached subprocess (i.e., a daemon).
E.g. for mark:
spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx")
"""
# fork the first time (to make a non-session-leader child process)
try:
pid = os.fork()
except OSError, e:
raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno))
if pid != 0:
# parent (calling) process is all done
return
# detach from controlling terminal (to make child a session-leader)
os.setsid()
try:
pid = os.fork()
except OSError, e:
raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno))
raise Exception, "%s [%d]" % (e.strerror, e.errno)
if pid != 0:
# child process is all done
os._exit(0)
# grandchild process now non-session-leader, detached from parent
# grandchild process must now close all open files
try:
maxfd = os.sysconf("SC_OPEN_MAX")
except (AttributeError, ValueError):
maxfd = 1024
for fd in range(maxfd):
try:
os.close(fd)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
pass
# redirect stdin, stdout and stderr to /dev/null
os.open(os.devnull, os.O_RDWR) # standard input (0)
os.dup2(0, 1)
os.dup2(0, 2)
# and finally let's execute the executable for the daemon!
try:
os.execv(path_to_executable, args)
except Exception, e:
# oops, we're cut off from the world, let's just give up
os._exit(255)