Нет SIGTERM до SIGKILL/ завершение работы с systemd в Ubuntu 16.04
Я столкнулся с этой проблемой, пытаясь ответить на вопрос о Stackoverflow.
При выключении Ubuntu 12.04 отправляет SIGTERM
для всех процессов и ждет не более 10 секунд, прежде чем убить их SIGKILL
(если они не прекращены раньше). Мой ответ на SO даже содержит скрипт Python, который проверяет это поведение. Сценарий запускается в терминале, отправляется в фоновый режим и затем отвергается терминалом. При получении SIGTERM
, скрипт просто продолжает работать и непрерывно печатает в файл, сколько времени он работал после получения SIGTERM
,
Ubuntu 16.04 однако сценарий убивается сразу при выключении (нет SIGTERM
вошел).
Некоторое время я гуглил, но ничего полезного не нашел. Никто никогда не сталкивался с такими серьезными изменениями в текущей версии LTS?
Вот сценарий signaltest.py
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
signal.signal(signal.SIGTERM, stop)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)
Скрипт использует файл log.txt
в текущем каталоге для всего вывода. У него есть цикл, который печатает "работает" каждую секунду. получающий SIGTERM
разрывает цикл и запускает другой цикл, который печатает секунды, прошедшие с момента получения SIGTERM
,
Скрипт запускается из терминала отдельно disown
:
python signaltest.py &
disown
Просто чтобы быть ясно: это не дубликат Ubuntu не отправляет SIGTERM при завершении работы. Вопрос о настольных приложениях и ответы тоже не подходят.
1 ответ
systemd (в отличие от upstart в более ранних версиях Ubuntu) дополнительно отправляет сигнал SIGHUP при завершении работы (и перед отправкой ждет 90 секунд вместо 10 секунд) SIGKILL
). Предлагаю проигнорировать SIGHUP
или справиться SIGTERM
а также SIGHUP
таким же (идемпотентным) способом.
Модифицированный тестовый скрипт можно изменить следующим образом:
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
def ignore(sig, frsma):
out.write('ignoring signal %d\n' % sig)
out.flush()
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGHUP, ignore)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)