我如何运行长期(无限)的Python进程?

我最近开始尝试使用Python进行Web开发。 到目前为止,我已经使用Apache与mod_wsgi和Python 2.7的Django Web框架取得了一些成功。 然而,我遇到了一些问题,有不断运行的进程,更新信息等。

我已经写了一个我称之为“daemonManager.py”的脚本,可以启动和停止所有或单独的python更新循环(我应该把它们叫做守护进程?)。 它通过分叉,然后加载模块来运行它应该运行的特定function,并启动一个无限循环。 它将一个PID文件保存在/var/run以跟踪进程。 到现在为止还挺好。 我遇到的问题是:

  • 不时有一个进程将会退出。 我在早上检查ps ,这个过程已经结束了。 没有logging错误(我正在使用logging模块),并且覆盖了我能想到的所有exception并logging下来。 另外我不认为这些退出过程与我的代码有任何关系,因为我的所有进程都运行完全不同的代码,并以相似的时间间隔退出。 我当然可能是错的。 Python进程在运行了几天/几周后才死掉,这是正常的吗? 我应该如何解决这个问题? 我应该编写另一个守护进程来定期检查其他守护进程是否仍在运行? 如果守护进程停止了,该怎么办? 我不知如何处理这个问题。

  • 如何以编程方式知道进程是否仍在运行? 我将PID文件保存在/var/run并检查PID文件是否存在以确定进程是否正在运行。 但是,如果进程刚刚死于意想不到的原因,PID文件将保留。 因此,每次进程崩溃时(每周几次),我都必须删除这些文件,这种做法无法达到目的。 我想我可以检查一个进程是否在文件中的PID上运行,但是如果另一个进程已经启动并被分配了死进程的PID呢? 我的守护进程会认为这个进程运行良好,即使它已经很长时间了。 再次,我不知如何处理这个问题。

有关如何最好地运行无限Python进程的任何有用的答案,希望也可以解决上述问题,我会接受


我在Ubuntu机器上使用Apache 2.2.14。
我的Python版本是2.7.2

我会打开这个说明,这是管理一个长时间运行的过程(LRP)的一种方式 – 事实上并非如此。

根据我的经验,最好的产品来自专注于您正在处理的具体问题,同时将支持技术委托给其他图书馆。 在这种情况下,我指的是后台进程的行为(双叉),监视和日志重定向。

我最喜欢的解决方案是http://supervisord.org/

使用像supervisord这样的系统,你基本上可以编写一个传统的Python脚本,在“无限”循环中执行任务。

 #!/usr/bin/python import sys import time def main_loop(): while 1: # do your stuff... time.sleep(0.1) if __name__ == '__main__': try: main_loop() except KeyboardInterrupt: print >> sys.stderr, '\nExiting by user request.\n' sys.exit(0) 

以这种方式编写脚本使开发和调试变得简单方便(您可以在终端中轻松启动/停止脚本,并在事件展开时查看日志输出)。 当投入生产时,您只需定义一个调用您的脚本的主管配置(以下是定义“程序”的完整示例,其中大部分是可选的: http : //supervisord.org/configuration.html#program -x部分 – 示例 )。

主管有一堆配置选项,所以我不会列举他们,但我会说,它特别解决了你所描述的问题:

  • Backgrounding / Daemonizing
  • PID跟踪(可以配置为重新启动进程,如果它意外终止)
  • 通常在脚本中记录(如果使用日志记录模块而不是打印,则使用流处理程序),但让管理员重定向到一个文件。

我假设你正在运行Unix / Linux,但是你没有真正的说。 我对你的问题没有直接的建议。 所以我不期望成为这个问题的“正确”答案。 但是这里有一些东西要探索。

首先,如果你的守护进程崩溃了,你应该修复这个问题。 只有有bug的程序才会崩溃。 也许你应该在调试器下启动它们,看看它们在崩溃时会发生什么(如果可能的话)。 你在这些过程中有没有跟踪记录? 如果不是,请添加它们。 这可能有助于诊断您的崩溃。

其次,您的守护进程是否提供服务(打开管道和等待请求)还是定期清理? 如果他们是定期清理过程,你应该使用cron来定期启动它们,而不是让它们在无限循环中运行。 Cron进程应该比守护进程更受欢迎。 同样,如果他们是开放端口和服务请求的服务,你有没有考虑使他们与INETD? 同样,一个守护进程(inetd)应该比一群守护进程更受欢迎。

第三,在文件中保存一个PID不是很有效,正如你发现的那样。 也许像信号量这样的共享IPC会更好。 这里我没有任何细节。

第四,有时我需要在网站上下文中运行。 我使用一个cron过程来调用带有维护URL的wget。 您设置了一个特殊的cookie,并使用wget命令行包含cookie信息。 如果特殊cookie不存在,则返回403而不是执行维护过程。 这里的另一个好处是登录到数据库和其他避免的环境问题,因为服务于普通网页的代码正在服务于维护过程。

希望给你的想法。 我认为如果可以的话,避开守护进程是最好的开始。 如果你可以在mod_wsgi中运行你的python,这样你就不用再支持多个“环境”了。 在一次运行几天之后调试一个失败的进程是残酷的。

如果你的程序,Python解释器,或者你正在使用的任何Python库/模块没有任何内存泄漏,你应该考虑Python进程能够“永远”运行。 (即使面对内存泄漏,如果在64位机器上有足够的交换空间,也许可以永远运行,几十年(如果不是几个世纪的话)应该是可行的。两年在有限的硬件上 – 在硬件需要移动之前。)

当Linux发行版使用了SysV风格的init时,确保程序重启时非常简单 – 只需在/etc/inittab添加一行,然后init(8)就会在启动时产生程序并重新生成它如果它死了。 (我知道没有任何机制来复制这个功能,因为现在很多发行版都在使用新的init replacement,我不是说这是不可能的,我只是不知道该怎么做。

但是即使是过去几年的init(8)机制也不像有些人所希望的那样灵活。 DJB的daemontools软件包是过程控制和监视工具的一个例子,旨在让守护进程永远存在。 Linux-HA套件提供了另一个类似的工具,尽管它可能提供了太多的“额外”功能来证明这个任务是合理的。 monit是另一种选择。