Systemd «OnFailure=» не запускается при выходе двоичного файла или bash с кодом ошибки

#linux #bash #shell #embedded #systemd

Вопрос:

Итак, у меня есть блок systemd, который необходимо контролировать, перезапускать в случае сбоя, а также что-то делать в случае выхода устройства из строя. Я работаю над встроенной системой, поэтому она должна быть надежной.

В моем случае у нас есть служба systemd:

 Description=Demo unit
Wants=multi-user.target
OnFailure=FailHandler@%N.service


[Service]
ExecStart=/bin/bash /home/root/demo.sh
Restart=on-failure
RestartSec=1
Type=simple 
 

Ту тусовку, которую я начинаю:

 
echo "Started demo.sh"

current_date=`date`

sleep 10s

echo "${current_date} Demo was here" >> /home/root/demo.txt

exit 1 
 

Пока все хорошо. Bash всегда завершается с интервалом от 1 до 10 секунд и регистрирует время. Проблема в том, что в этом случае FailHandler никогда не вызывается. Теперь это просто демонстрация, все приложения на C , но поведение одинаковое. Теперь, если я вручную укажу неправильный путь к файлу bash, он не сработает, но запустится часть «OnFailure». Вот вывод системного журнала из правильного пути:

 2021-09-03T13:06:31.575094 00:00 hostname bash[1125]: Started demo.sh
2021-09-03T13:06:41.629450 00:00 hostname systemd[1]: demo.service: Main process exited, code=exited, status=1/FAILURE
2021-09-03T13:06:41.644681 00:00 hostname systemd[1]: demo.service: Failed with result 'exit-code'.
2021-09-03T13:06:41.818089 00:00 hostname systemd[1]: demo.service: Service RestartSec=100ms expired, scheduling restart.
2021-09-03T13:06:41.824005 00:00 hostname systemd[1]: demo.service: Scheduled restart job, restart counter is at 1.
2021-09-03T13:06:41.850933 00:00 hostname bash[1179]: Started demo.sh
2021-09-03T13:06:51.870376 00:00 hostname systemd[1]: demo.service: Main process exited, code=exited, status=1/FAILURE
2021-09-03T13:06:51.872611 00:00 hostname systemd[1]: demo.service: Failed with result 'exit-code'.
2021-09-03T13:06:52.117479 00:00 hostname systemd[1]: demo.service: Service RestartSec=100ms expired, scheduling restart.
2021-09-03T13:06:52.136102 00:00 hostname systemd[1]: demo.service: Scheduled restart job, restart counter is at 2.
2021-09-03T13:06:52.163865 00:00 hostname bash[1221]: Started demo.sh
 

Вот вывод, полученный при неправильном пути:

 2021-09-03T13:07:46.582269 00:00 hostnaem bash[1446]: /bin/bash: /ahome/root/daemo.sh: No such file or directory
2021-09-03T13:07:46.588715 00:00 hostnaem systemd[1]: daemo.service: Main process exited, code=exited, status=127/n/a
2021-09-03T13:07:46.590356 00:00 hostnaem systemd[1]: daemo.service: Failed with result 'exit-code'.
2021-09-03T13:07:46.694616 00:00 hostnaem systemd[1]: daemo.service: Service RestartSec=100ms expired, scheduling restart.
2021-09-03T13:07:46.701519 00:00 hostnaem systemd[1]: daemo.service: Scheduled restart job, restart counter is at 1.
2021-09-03T13:07:46.720879 00:00 hostnaem systemd[1]: daemo.service: Start request repeated too quickly.
2021-09-03T13:07:46.721405 00:00 hostnaem systemd[1]: daemo.service: Failed with result 'exit-code'.
2021-09-03T13:07:46.722723 00:00 hostnaem systemd[1]: daemo.service: Triggering OnFailure= dependencies.
2021-09-03T13:07:46.804815 00:00 hostnaem FailHandler.sh[1457]: Failed application: daemo
2021-09-03T13:07:46.822342 00:00 hostnaem bash[1457]: error: cannot stat /etc/logrotate.d/daemo: No such file or directory
2021-09-03T13:07:46.841577 00:00 hostnaem FailHandler.sh[1457]: ERROR: Failed logrotate for daemo crash
2021-09-03T13:07:46.977003 00:00 hostnaem systemd[1]: FailHandler@daemo.service: Succeeded.
 

Из системного журнала я понимаю, что он запускает обработчик сбоев всякий раз, когда количество перезапусков достигает StartLimitBurst=1 в течение 100 мс, но есть ли способ запустить его в любое время, когда приложение завершает работу с кодом ошибки?

Комментарии:

1. Я предполагаю, что одним из способов было бы использовать ExecStopPost и использовать статус выхода в качестве условия для запуска сценария сбоя или нет: unix.stackexchange.com/a/441662/494713

Ответ №1:

Спасибо тебе, парень. Я бросил один взгляд на ссылку, которую вы отправили, и она появилась. Решение в моем случае было:

 ExecStopPost=/bin/bash -c 'if [ "$EXIT_STATUS" != 0 ]; then systemctl start FailHandler@%N.service; fi'