You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用python-daemon实现守护进程时未生成pidfile的解决方法

解决python-daemon守护进程不生成PID文件的问题

核心问题分析

你遇到的PID文件未生成情况,主要集中在权限不足、PID文件类使用不当以及代码潜在异常导致进程提前退出这几个方面,以下是针对性解决方案:

1. 解决权限问题

/var/run目录默认属于root用户,普通用户无写入权限,这是最常见的原因。你有两个选择:

  • 以root身份启动守护进程(比如用sudo)
  • 将PID文件路径改为普通用户有权限的目录,例如~/run/test.pid(需先手动创建~/run目录)

2. 修正代码中的潜在异常

原代码中Runner类的terminate方法会访问self.timer,但第一次调用scheduleNextRun前该属性未初始化,会触发AttributeError导致进程异常退出,PID文件被自动清理。需要在类初始化时默认初始化self.timer:

class Runner:
    def __init__(self):
        self.timer = None  # 提前初始化timer属性,避免终止时触发异常

    def run(self):
        syslog.syslog("Running something")

    def scheduleNextRun(self):
        self.run()
        self.timer = threading.Timer(3, self.scheduleNextRun)
        self.timer.start()

    def terminate(self, signum, frame):
        syslog.syslog("Received {}".format(signal.Signals(signum).name))
        if self.timer:
            syslog.syslog("Stopping the timer")
            self.timer.cancel()
        syslog.syslog("Will now terminate")

3. 正确使用python-daemon自带的PID文件类

使用daemon.pidfile.PIDLockFile是规范方式,需确保DaemonContext正确管理文件生命周期。修正后的完整代码如下:

import daemon
import daemon.pidfile
import threading
import syslog
import signal
import os

class Runner:
    def __init__(self):
        self.timer = None

    def run(self):
        syslog.syslog("Running something")

    def scheduleNextRun(self):
        self.run()
        self.timer = threading.Timer(3, self.scheduleNextRun)
        self.timer.start()

    def terminate(self, signum, frame):
        syslog.syslog("Received {}".format(signal.Signals(signum).name))
        if self.timer:
            syslog.syslog("Stopping the timer")
            self.timer.cancel()
        syslog.syslog("Will now terminate")
        os._exit(0)  # 确保进程正常退出

def setup():
    runner = Runner()
    signal.signal(signal.SIGTERM, runner.terminate)
    signal.signal(signal.SIGINT, runner.terminate)
    runner.scheduleNextRun()
    # 阻塞主线程,避免DaemonContext提前退出
    while True:
        threading.Event().wait(1)

# 示例:使用root权限路径或普通用户可写路径
pid_file_path = "/var/run/test.pid"
# pid_file_path = os.path.expanduser("~/run/test.pid")

# 确保PID文件所在目录存在
pid_dir = os.path.dirname(pid_file_path)
if not os.path.exists(pid_dir):
    os.makedirs(pid_dir, exist_ok=True)

with daemon.DaemonContext(
    pidfile=daemon.pidfile.PIDLockFile(pid_file_path),
    working_directory="/tmp"  # 指定工作目录,避免影响原环境
):
    setup()

关键补充说明

  • DaemonContext会在进程正常退出时自动清理PID文件,若进程因异常崩溃,PID文件也会被删除,这是正常行为。可通过查看syslog日志排查进程是否异常退出。
  • 优先使用python-daemon自带的daemon.pidfile模块,第三方PID文件库需实现acquire()和release()接口才能被DaemonContext正确管理。

内容的提问来源于stack exchange,提问作者Tobias Leupold

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:33:35