Когда вы не пытаетесь ждать такое событие, но в параллельной сессии отправить SIGTERM
этот процесс (например, путем вызова kill -15 $PID
на идентификаторе процесса $PID
в управлении питоном скрипт), вы должны увидеть сообщение поучительных ошибок; -)
Также комментарий о точке монтирования должен представлять интерес после устранения ошибок python (TypeError: cannot concatenate 'str' and 'int' objects
).
Try что-то вроде:
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< - - - ...
Edit: Для того, чтобы еще больше изолировать ошибку и адаптироваться к производству, как режим, можно переписать код, как это (при условии, что системный журнал является работает на машине, которую он должен, но я никогда не работал на устройствах такого рода):
#! /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.LOG_USER
в моей системе (OS X) дает мне во всех терминалах сообщение, в то время как сообщение приоритета syslog.LOG_ERR
в обработчике сигналов предназначено только для системного журнала.
- должен быть более точным во время остановки работы (не открывать файл и т. Д.).)
Последний пункт (5) имеет важное значение в случае, если все процессы получать SIGTERM
во время остановки, то есть все хотят что-то сделать (замедляя вещи вниз), может быть screen
также не принимает каких-либо буферизованный ввод больше (или не сбрасывается), примечание stdout
блокируется буфером, а не буфером.
Развязка выходных каналов также должна облегчить возможное исчезновение точки монтирования файла журнала измерений.
Вы уверены, что носитель все еще установлен, когда выполняется обработчик? –
@RDK, пожалуйста, проверьте мой ответ (он работает на моей системе), но попробуйте также быть атомарным в корпусе функции «CloseAll» и следить за доступностью точки монтирования во время выключения как http://stackoverflow.com/ пользователей/20862/ignacio-vazquez-abrams, указанных выше. – Dilettant