如何在 Python 中创建守护进程?

2024-12-09 08:29:00
admin
原创
187
摘要:问题描述:在 Google 上搜索会显示 x2 代码片段。第一个结果是这个代码配方,其中包含大量文档和解释,以及一些有用的讨论。但是,另一个代码示例虽然没有包含太多文档,但包含传递启动、停止和重启等命令的示例代码。它还创建了一个 PID 文件,可以方便地检查守护进程是否已在运行等。这两个示例都解释了如何创建守...

问题描述:

在 Google 上搜索会显示 x2 代码片段。第一个结果是这个代码配方,其中包含大量文档和解释,以及一些有用的讨论。

但是,另一个代码示例虽然没有包含太多文档,但包含传递启动、停止和重启等命令的示例代码。它还创建了一个 PID 文件,可以方便地检查守护进程是否已在运行等。

这两个示例都解释了如何创建守护进程。还有其他需要考虑的事情吗?一个示例是否比另一个示例更好,为什么?


解决方案 1:

当前解决方案

PEP 3143(标准守护进程库)的参考实现现已作为python-daemon提供。

历史答案

Sander Marechal 的代码示例优于最初于 2004 年发布的原始代码。我曾经为 Pyro 贡献过一个守护进程,但如果必须重做的话,我可能会使用 Sander 的代码。

解决方案 2:

在成为一个行为良好的守护进程时,有很多棘手的事情需要处理:

  • 防止核心转储(许多守护进程以 root 身份运行,核心转储可能包含敏感信息)

  • 在监狱里行为端正chroot

  • 根据用例适当地设置 UID、GID、工作目录、umask 和其他进程参数

  • 放弃suid特权sgid

  • 关闭所有打开的文件描述符,根据用例排除

  • 如果在已经分离的上下文中启动,则行为正确,例如initinetd等。

  • 设置信号处理程序以实现合理的守护进程行为,但也根据用例确定特定的处理程序

  • 重定向标准流stdinstdout因为stderr守护进程不再具有控制终端

  • 将 PID 文件作为协作咨询锁来处理,这本身就是一个很棘手的问题,有许多相互矛盾但有效的行为方式

  • 允许在进程终止时进行适当的清理

  • 实际上成为一个守护进程,而不会导致僵尸进程

其中一些是标准的,如经典 Unix 文献(《UNIX 环境高级编程》,由已故的 W. Richard Stevens 编著,Addison-Wesley,1992 年)中所述。其他一些,如流重定向和PID 文件处理,是大多数守护进程用户期望的常规行为,但标准化程度较低。

所有这些都包含在PEP 3143 “标准守护进程库”规范中。python -daemon参考实现适用于 Python 2.7 或更高版本以及 Python 3.2 或更高版本。

解决方案 3:

这是我在开发新的守护进程应用程序时开始使用的基本“Howdy World”Python 守护进程。

#!/usr/bin/python
import time
from daemon import runner

class App():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/foo.pid'
        self.pidfile_timeout = 5
    def run(self):
        while True:
            print("Howdy!  Gig'em!  Whoop!")
            time.sleep(10)

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

请注意,您需要该python-daemon库。您可以通过以下方式安装它:

pip install python-daemon

然后只需用 启动它./howdy.py start,并用 停止它./howdy.py stop

解决方案 4:

另一种方法是创建一个普通的、非守护进程的 Python 程序,然后使用Supervisord在外部对其进行守护进程化。这可以省去很多麻烦,并且可以在 *nix 和语言之间移植。

解决方案 5:

请注意python-daemon包,它解决了守护进程背后的许多问题。

它还可以实现以下功能(来自 Debian 软件包描述):

  • 将进程分离到其自己的进程组中。

  • 设置适合在 chroot 内运行的进程环境。

  • 放弃 suid 和 sgid 权限。

  • 关闭所有打开的文件描述符。

  • 更改工作目录、uid、gid 和 umask。

  • 设置适当的信号处理程序。

  • 为 stdin、stdout 和 stderr 打开新的文件描述符。

  • 管理指定的PID锁文件。

  • 注册用于退出处理的清理函数。

解决方案 6:

这可能不是问题的直接答案,但 systemd 可用于将您的应用程序作为守护进程运行。以下是示例:

[Unit]
Description=Python daemon
After=syslog.target
After=network.target

[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py

# Give the script some time to startup
TimeoutSec=300

[Install]
WantedBy=multi-user.target

我更喜欢这种方法,因为很多工作都是为您完成的,然后您的守护进程脚本的行为与系统的其余部分类似。

解决方案 7:

该函数将把应用程序转换为守护进程:

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}
'.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}
'.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())

解决方案 8:

YapDi是一个 Python 包。它可用于将 Python 脚本从脚本内部转换为守护进程模式。

解决方案 9:

由于 python-daemon 尚未支持 python 3.x,并且从邮件列表中可以看到,它可能永远不会支持,因此我编写了 PEP 3143 的新实现:pep3143daemon

pep3143daemon 至少应支持 python 2.6、2.7 和 3.x

它还包含一个 PidFile 类。

该库仅依赖于标准库和六个模块。

它可以用作 python-daemon 的替代品。

这是文档。

解决方案 10:

恐怕@Dustin 提到的守护进程模块对我来说不起作用。相反,我安装了python-daemon并使用了以下代码:

# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass 

with daemon.DaemonContext():
    moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.

跑步很容易

> python myDaemon.py

出于完整性考虑,这里是 samplemodule 目录内容

>ls samplemodule
__init__.py __init__.pyc moduleclass.py

moduleclass.py 的内容可以是

class moduleclass():
    ...

def do_running():
    m = moduleclass()
    # do whatever daemon is required to do.

解决方案 11:

虽然您可能更喜欢 python-daemon 模块提供的纯 Python 解决方案,但是至少在BSD和Linuxdaemon(3)上有一个函数可以做正确的事情。libc

从 python 调用它很容易:

import ctypes

ctypes.CDLL(None).daemon(0, 0) # Read the man-page for the arguments' meanings

剩下要做的唯一一件事就是创建(并锁定)PID 文件。不过你可以自己处理……

解决方案 12:

在 python 中进行守护进程时还有一件事需要考虑:

如果您正在使用 python日志记录,并且想要在守护进程之后继续使用它,请确保调用close()处理程序(特别是文件处理程序)。

如果您不这样做,处理程序仍然可以认为它已打开文件,并且您的消息将会消失 - 换句话说,确保记录器知道其文件已关闭!

这假设当您守护进程时,您会不加区分地关闭所有打开的文件描述符 - 相反,您可以尝试关闭除日志文件之外的所有文件(但关闭所有文件然后重新打开您想要的文件通常更简单)。

解决方案 13:

我修改了 Sander Marechal 的代码示例中的几行(@JeffBauer 在接受的答案中提到),以添加quit()在守护进程停止之前执行的方法。这有时非常有用。

这里是。

注意:我不使用“python-daemon”模块,因为文档仍然缺失(另请参阅许多其他 SO 问题)并且相当晦涩(如何使用此模块从命令行正确启动/停止守护进程?)

解决方案 14:

经过几年和多次尝试(我尝试了这里给出的所有答案,但最后它们都有一些小缺点),现在我意识到有一种比直接从 Python 启动、停止、重新启动守护进程更好的方法:使用操作系统工具。

例如,对于 Linux,我不会执行python myapp startpython myapp stop,而是执行以下操作来启动应用程序:

screen -S myapp python myapp.py    
# CTRL+A, D to detach

或者用一个命令screen -dmS myapp python myapp.py来启动和分离它。

然后:

screen -r myapp

再次连接到此终端。进入终端后,可以使用 CTRL+C 停止它。

解决方案 15:

使用 Python 创建守护进程的最简单方法是使用Twisted事件驱动框架。它会为您处理守护进程所需的所有工作。它使用Reactor 模式来处理并发请求。

解决方案 16:

80% 的时间里,当人们说“守护进程”时,他们只是想要一个服务器。由于这个问题在这一点上完全不清楚,很难说答案的可能范围是什么。由于服务器就足够了,那就从那里开始吧。如果确实需要一个真正的“守护进程”(这种情况很少见),请阅读有关nohup如何将服务器守护进程化的内容。

在真正需要真正的守护进程之前,只需编写一个简单的服务器。

另请查看WSGI 参考实现。

另请查看简单 HTTP 服务器。

“还有其他需要考虑的事情吗?”是的。大约有一百万件事情。什么协议?有多少请求?每个请求的服务时间有多长?它们到达的频率是多少?您会使用专用进程吗?线程?子进程?编写守护进程是一项艰巨的工作。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2500  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1541  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   16  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   23  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   26  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用