2

我正在使用此处或此处引用的著名代码在 Python 中执行守护程序,如下所示:

import sys, daemon

class test(daemon.Daemon):
    def run(self):
        self.db = somedb.connect()            # connect to a DB
        self.blah = 127
        with open('blah0.txt', 'w') as f:
            f.write(self.blah)
        # doing lots of things here, modifying self.blah

    def before_stop(self):
        self.db.close()                      # properly close the DB (sync to disk, etc.)
        with open('blah1.txt', 'w') as f:
            f.write(self.blah)

daemon = test(pidfile='_.pid')

if 'start' == sys.argv[1]: 
    daemon.start()
elif 'stop' == sys.argv[1]: 
    daemon.before_stop()               # AttributeError: test instance has no attribute 'blah'
    daemon.stop()

问题是,在调用时./myscript.py stopdaemon.before_stop()不再引用self.blah!

AttributeError:测试实例没有属性'blah'

因此,使用这种守护程序方法,在停止守护程序之前无法访问守护程序的变量......

问题:如何在之前访问守护程序类的变量:

  • 停在./myscript.py stop

  • 被 SIGTERM 停止

  • (被杀?)


编辑:已解决,这是一个带有quit()方法的工作守护程序代码。

4

2 回答 2

5

守护进程代码向守护进程发送一个 SIGTERM 信号,要求它停止。如果您希望守护进程本身运行某些东西,则它必须从信号处理程序或被atexit.register调用方法运行。

daemonize方法已经安装了这样的方法,只需beforestop从那里调用:

# this one could be either in a subclass or in a modified base daemeon class
def delpid(self):
        if hasattr(self, 'before_stop'):
                self.before_stop()
        os.remove(self.pidfile)

# this one should be in subclass
def before_stop(self):
    self.db.close()                      # properly close the DB (sync to disk, etc.)
    with open('blah1.txt', 'w') as f:
        f.write(self.blah)

但这还不够!Python 标准库文档说atexit

当程序被 Python 未处理的信号杀死时,不会调用通过此模块注册的函数

由于该进程预计会收到 SIGTERM 信号,因此您必须安装一个处理程序。如一个活动状态配方所示,它非常简单:只要程序收到信号就停止:

...
from signal import signal, SIGTERM
...

atexit.register(self.delpid)
signal(SIGTERM, lambda signum, stack_frame: exit(1))
于 2016-11-04T13:21:24.490 回答
0

该类Daemon在您调用时不会检索前一个对象before_stop(),它只是通过 PID 找到进程并使用SIGTERM. 如果您需要一些实例属性,请将它们初始化__init__()或将它们写在某个临时文件中,以便稍后在您的before_stop()实现中读取它们。

作为一般规则,__init__()无论如何您都应该始终初始化所有实例绑定属性。

于 2016-11-04T11:40:39.637 回答