在关闭信号时在 python 脚本中运行代码

use*_*341 6 python shutdown raspberry-pi

我有一个在启动时在后台运行的 python 脚本。启动方法是使用 /etc/rc.local 调用的 run.sh 文件中的一个条目。确切的条目是“sudo python /home/pi/run/main.py &”。该系统是一个带有喘息的树莓派。

脚本正在运行,目前没有问题。如果关闭命令发送到系统(通过控制台“sudo shutdown -h now”),我需要进一步的脚本不要立即中止,而是先执行一些代码。这就是我到目前为止所得到的:

#!/usr/bin/env python

import atexit

@atexit.register
def byebye():
    c = "End"
    datei = open("/home/pi/logfile",'a+b')
    datei.write(c + "\n")
    datei.close()

def main():

   while True:
     ...do anything...

main()
Run Code Online (Sandbox Code Playgroud)

现在它似乎只是在关机时退出主循环。我是否需要使用不同的方式来关闭系统以便将信号传输到我的脚本,或者我可能没有使用“@atexit”方法?有任何想法吗?

谢谢

roi*_*ppi 8

shutdown发送不处理的SIGTERM信号atexit。上下文管理器、finally块等也不会。

import signal

signal.getsignal(signal.SIGTERM)
Out[64]: 0 #i.e. nothing
Run Code Online (Sandbox Code Playgroud)

对比一下,说 ctrl-C:

signal.getsignal(signal.SIGINT)
Out[65]: <function signal.default_int_handler> #i.e. something
Run Code Online (Sandbox Code Playgroud)

你可以注册你的byebye函数signal来运行而不是什么都不做(这会导致解释器最终被 shell 杀死)

signal.signal(signal.SIGTERM,byebye)
Run Code Online (Sandbox Code Playgroud)

如果您执行上述操作,则需要做两件事:

  • 更改签名byebye以接受signal将传递给它的两个参数。
  • 你应该sys.exit()在你的byebye函数结束时做一些类似 call 的事情,让 python 优雅地关闭商店。

你也可以做一些signal 和的 组合atexit

import sys
signal.signal(signal.SIGTERM, lambda num, frame: sys.exit(0))
Run Code Online (Sandbox Code Playgroud)

这将直接放入您当前的代码中。这确保了清理操作的原子性(即byebye保证是最后的 I/O 操作),但代价是有点笨重。