2

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

4

2 回答 2

2

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

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 中涵盖的概念的进一步探索。

于 2014-09-30T15:09:30.847 回答
0

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

  1. 检查 pidfile 是否存在 -> 如果存在,则退出并显示错误消息,例如“pid 文件存在 - 如果您确定没有进程正在运行,则 rm it”

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

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

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

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

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

于 2014-09-30T14:38:38.577 回答