Как запустить определенную программу до того, как сторожевой таймер systemd остановит службу

У меня есть программа, которая запускается systemd с таким служебным файлом:

[Unit]
Description=...

[Service]
Type=notify
ExecStart=/usr/sbin/myprogram
WatchdogSec=1
KillMode=process
KillSignal=SIGTERM
Restart=always

Он регулярно посылает соответствующий сигнал сторожевому таймеру. Время от времени программа как бы зависает и завершается сторожевым таймером, а затем перезапускается. Прежде чем сторожевой таймер завершит его, я хотел бы получить некоторую информацию из программы, выполнив команду или запустив какой-либо другой скрипт (например, запустить gdb -p <PID> --batch -ex 'thread apply all backtrace'). Как бы я это сделал?


person jotrocken    schedule 17.10.2018    source источник


Ответы (1)


Добавьте ExecStop= в свой сервис.

[Service]
ExecStart=....
ExecStop=/path/to/SomeOtherProgram
....

Согласно руководству systemd, если доступна опция ExecStop, она будет запущена первой, а затем, если процесс под ExecStart все еще доступен после этого, он запустит KillMode.

ExecStop= Команды, которые нужно выполнить, чтобы остановить службу, запущенную через ExecStart=. Этот аргумент принимает несколько командных строк по той же схеме, что и для ExecStart= выше. Использование этого параметра не является обязательным. После запуска команд, настроенных в этой опции, подразумевается, что служба остановлена, а все оставшиеся для нее процессы завершаются в соответствии с настройкой KillMode= (см. systemd.kill(5)). Если эта опция не указана, процесс завершается отправкой сигнала, указанного в KillSignal=, когда запрашивается остановка службы. Поддерживается подстановка спецификаторов и переменных среды (включая $MAINPID, см. выше).

РЕДАКТИРОВАТЬ

Как указано в комментарии ниже, это решение может не работать для параметра Watchdog в файле service.

person iamauser    schedule 17.10.2018
comment
Это должно помочь, но есть две вещи, которые мне не нравятся в этом подходе: 1) Он будет выполнять команду ExecStop= также, когда служба намеренно остановлена, например. во время развертывания. 2) Если я правильно понимаю, это переопределяет команду остановки по умолчанию. Таким образом, служба не будет остановлена, если только не будет установлена ​​TimeoutStopSec=, которая запускает SIGKILL, или добавлена ​​другая ExecStop= с исходной командой остановки (чего я не знаю), или что-то еще, что создает условие, описанное в вашей цитате. Тем не менее, я попробую. Вы видите какое-то другое решение? - person jotrocken; 18.10.2018
comment
Нет, вам не нужны никакие дополнительные атрибуты. ExecStop= останавливает другой сценарий, и после этого, если systemd все еще находит process-id, начавшийся с ExecStart=, он вызывает KillMode=process с KillSignal=SIGTERM. Без ExecStop= все равно было бы то же самое. - person iamauser; 18.10.2018
comment
К сожалению, оказалось, что это не работает так, как мы ожидали. systemd запускает команду ExecStop= после, когда сторожевой таймер завершает работу службы (сначала отправляет SIGABRT, а затем SIGTERM по истечении 90 секунд). Я думаю, что я не могу использовать здесь какую-либо механику systemd, но должен обрабатывать SIGABRT внутри и собирать информацию внутри службы. - person jotrocken; 19.10.2018
comment
хорошо, тбх, я проверил это, но без Watchdog, и это убивает процесс ... Возможно, Watchdog переопределяет структуру. - person iamauser; 19.10.2018