【问题标题】:Python Daemon: checking to have one daemon run at all timesPython 守护进程:检查是否始终运行一个守护进程
【发布时间】:2014-09-30 14:18:05
【问题描述】:

myalert.py

from daemon import Daemon
import os, time, sys

class alertDaemon(Daemon):
    def run(self):
        while True:
            time.sleep(1)

if __name__ == "__main__":
    alert_pid = '/tmp/ex.pid'

    # if pid doesnt exists run
    if os.path.isfile(alert_pid):            # is this check enough?
        sys.exit(0)

    daemon = alertDaemon(alert_pid)
    daemon.start()

鉴于没有其他程序或用户会创建 pid 文件:

1) 是否存在pid不存在但守护进程仍在运行的情况?
2) 是否存在 pid 存在但守护进程未运行的情况?

因为如果对上述至少一个问题的回答是肯定的,那么如果我的目标是始终运行一个守护程序,那么仅仅检查 pid 文件的存在是不够的。

问:如果我必须检查进程,我希望避免使用系统调用 ps -ef 和 grep 来获取脚本名称。有这样做的标准方法吗?

注意:脚本 myalert.py 将是一个 cronjob

【问题讨论】:

标签: python daemon python-daemon


【解决方案1】:

python-daemon 库是 PEP 3143 的参考实现:“标准守护进程库”,它通过在传递给 @ 的 pid 文件上使用文件锁(通过 lockfile 库)来处理此问题987654327@ 对象。底层操作系统保证当守护进程退出时文件锁将被释放,即使它不干净地退出。下面是一个简单的用法示例:

import daemon
from daemon.pidfile import PIDLockFile

context = daemon.DaemonContext(
    pidfile= PIDLockFile('/var/run/spam.pid'),
    )

with context:
    main()

因此,如果一个新实例启动,它不必确定创建现有 pid 文件的进程是否仍在通过 pid 本身运行;如果它可以获取文件锁,则没有其他实例正在运行(因为它们已经获取了锁)。如果无法获取锁,则必须运行另一个守护程序实例。

您遇到麻烦的唯一方法是,如果有人出现并在守护程序运行时手动删除了 pid 文件。但我认为您不必担心有人故意以这种方式破坏事物。

理想情况下,python-daemon 将成为标准库的一部分,这也是 PEP 3143 的最初目标。不幸的是,PEP 被推迟了,主要是因为没有人愿意实际完成添加所需的剩余工作到标准库:

对本 PEP 中涵盖的概念的进一步探索是 由于缺乏有兴趣推广的现任冠军而被推迟 PEP 的目标以及收集和整合反馈,以及 有足够的可用时间来有效地做到这一点。

【讨论】:

  • 虽然 pypi 页面已多年未更新,但原作者 here 库似乎仍在积极开发中。特别是,看起来 Python 3 的兼容性正在研究中(尽管看起来它实际上仍然与 Python 3.x 不兼容)。
【解决方案2】:

我看到它的几种实现方式:

  1. 检查 pidfile 是否存在 -> 如果存在,则退出并显示错误消息,例如“pid file exists -- rm it if you are sure no process is running”

  2. 检查 pidfile 是否存在 -> 如果存在,则检查具有该 pid 的进程是否存在 -> 如果存在,则死告诉用户“进程正在运行..”。 PID 编号冲突(重用于另一个进程)的风险非常小,以至于被忽略;告诉用户在发生错误时如何让程序重新启动

提示:要检查进程是否存在,可以检查/proc/<pid>目录

还要确保在脚本退出时尽一切可能删除 pidfile,例如:

  1. 将代码包装在try .. finally:

    # Check & create pidfile
    try:
        # your application logic
    
    finally:
        # remove pidfile
    
  2. 您甚至可以安装信号处理程序(通过signal 模块)以在接收到通常不会引发异常但直接退出的信号时删除 pidfile。

【讨论】:

    最近更新 更多