我发布了一个关于如何捕获" sudo shutdown -r 2"的问题。 Python中的事件。我被发送到这个帖子:Run code in python script on shutdown signal。
我正在和Jessy一起运行Raspberry Pi v2。
我已阅读
信号
并试图遵循上述主题中的想法,但到目前为止我还没有成功。这是我的代码:
import time
import signal
import sys
def CloseAll(Code, Frame):
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Signal Code:' + Code)
f.write('Signal Frame:' + Frame)
f.write('\r\n')
f.close()
sys.exit(0)
signal.signal(signal.SIGTERM,CloseAll)
print('Program is running')
try:
while True:
#get readings from sensors every 15 seconds
time.sleep(15)
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Hello ')
f.write('\r\n')
f.close()
except KeyboardInterrupt:
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Done')
f.write('\r\n')
f.close()
该程序在"屏幕"会话/窗口并按预期对CNTL-C作出反应。但是,当我退出屏幕会话,让程序继续运行,并输入" sudo shutdown -r 2"时,Pi会在2分钟后按预期重新启动,但TestSignal.txt文件未显示该信号.SIGTERM事件已处理完毕。
我做错了什么?或者更好的是,我如何捕获通常由cron作业启动的关闭事件,并优雅地关闭在屏幕会话中运行的Python程序?
答案 0 :(得分:0)
如果您不尝试等待此类事件,但在并行会话中将kill -15 $PID
发送到该进程(例如,通过在python脚本的进程标识$PID
上调用TypeError: cannot concatenate 'str' and 'int' objects
你应该看到一条有启发性的错误信息; - )
修复python错误(import time
import signal
import sys
LOG_PATH = '/mnt/usbdrive/output/TestSignal.txt'
def CloseAll(Code, Frame):
f = open(LOG_PATH, 'a')
f.write('Signal Code:' + str(Code) + ' ')
f.write('Signal Frame:' + str(Frame))
f.write('\r\n')
f.close()
sys.exit(0)
signal.signal(signal.SIGTERM, CloseAll)
print('Program is running')
try:
while True:
# get readings from sensors every 15 seconds
time.sleep(15)
f = open(LOG_PATH, 'a')
f.write('Hello ')
f.write('\r\n')
f.close()
except KeyboardInterrupt:
f = open(LOG_PATH, 'a')
f.write('Done')
f.write('\r\n')
f.close()
)之后,还应该对挂载点的注释感兴趣。
尝试类似:
# ... 8< - - -
def close_all(signum, frame):
with open(LOG_PATH, 'a') as f:
f.write('Signal Code:%d Signal Frame:%s\r\n' % (signum, frame))
sys.exit(0)
signal.signal(signal.SIGTERM, close_all)
# 8< - - - ...
作为起点。如果这在您的系统上以某种方式工作,为什么不重写一些部分,如:
#! /usr/bin/env python
import datetime as dt
import time
import signal
import sys
import syslog
LOG_PATH = 'foobarbaz.log' # '/mnt/usbdrive/output/TestSignal.txt'
def close_all(signum, frame):
"""Log to system log. Do not spend too much time after receipt of TERM."""
syslog.syslog(syslog.LOG_CRIT, 'Signal Number:%d {%s}' % (signum, frame))
sys.exit(0)
# register handler for SIGTERM(15) signal
signal.signal(signal.SIGTERM, close_all)
def get_sensor_readings_every(seconds):
"""Mock for sensor readings every seconds seconds."""
time.sleep(seconds)
return dt.datetime.now()
def main():
"""Main loop - maybe check usage patterns for file resources."""
syslog.syslog(syslog.LOG_USER, 'Program %s is running' % (__file__,))
try:
with open(LOG_PATH, 'a') as f:
while True:
f.write('Hello at %s\r\n' % (
get_sensor_readings_every(15),))
except KeyboardInterrupt:
with open(LOG_PATH, 'a') as f:
f.write('Done at %s\r\n' % (dt.datetime.now(),))
if __name__ == '__main__':
sys.exit(main())
编辑:为了进一步隔离错误并更多地适应生产模式,人们可能会重写这样的代码(假设syslog在机器上运行,应该这样,但我从未工作过)在那种设备上):
syslog
注意事项:
syslog.LOG_USER
频道。syslog.LOG_ERR
为我提供了一条消息,而信号处理程序中的SIGTERM
优先级消息仅针对系统日志。 / LI>
最后一点(5.)非常重要,以防所有进程在关闭期间收到screen
,即所有进程都想做某事(减慢速度),也许stdout
也不接受任何缓冲再输入(或不刷新),注意template<typename T, typename F>
struct S;
template<template <typename...> class C, typename R, typename... A>
struct S<C<A...>, R(A...)> {
using Apply = R(C<A...>::*)(A...);
// ...
};
是块缓冲而不是行缓冲。
输出通道的去耦也应该可以减轻测量日志文件的挂载点的最终消失。