Вопрос или проблема
Я пытаюсь сохранить службу systemd работающей как можно дольше во время процесса завершения работы.
Это необходимо для того, чтобы критически важный канал связи (по USB-сериалу) работал как можно дольше.
Точное поведение shutdown.target не совсем ясно для меня, и как добавление Before=shutdown.target
изменяет порядок уничтожения служб.
Моя текущая служба выглядит примерно так:
[Unit]
Description=ДОЛГОВЕЧНАЯ СЛУЖБА
DefaultDependencies=no
After=local-fs.target sysinit.target
Before=shutdown.target
[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=+/usr/bin/python3 -u /home/me/stay_alive.py
[Install]
WantedBy=multi-user.target
Буду очень признателен за любые советы по правильной реализации этого.
Кроме того, если есть описание того, как поведение изменяется с Before=shutdown.target
и без него.
Ответ или решение
Для того чтобы ваш сервис systemd работал как можно дольше во время последовательности завершения работы, вам необходимо учесть несколько аспектов конфигурации вашего юнита.
-
Понимание shutdown.target: Когда система начинает процесс завершения работы (shutdown), systemd запускает ряд служб, которые отвечают за правильное завершение работы системы. Отвечая на ваш вопрос о
Before=shutdown.target
, можно сказать, что добавление этой строки влияет на порядок выполнения (уничтожения) служб. Когда вы указываетеBefore=shutdown.target
, это значит, что ваш сервис будет завершён перед тем, как будут активированы службы, связанные с завершением работы системы. -
Отключение зависимостей: Вы уже указали
DefaultDependencies=no
, что предотвращает автоматическое добавление зависимостей, таких какshutdown.target
. Это правильно, так как вы хотите контролировать поведение вашего сервиса. -
Настройка времени завершения: Чтобы ваш сервис оставался активным до самого конца, вы можете использовать следующие параметры:
- TimeoutStopSec: Укажите достаточно большое время для завершения вашего сервиса. Например, вы можете установить
TimeoutStopSec=60s
, чтобы ваш сервис имел время завершить свои операции в течение одной минуту. - ExecStop: Если ваш сервис требует особых действий для корректного завершения, определите эту команду. Если никаких действий не требуется, это можно оставить пустым.
- TimeoutStopSec: Укажите достаточно большое время для завершения вашего сервиса. Например, вы можете установить
Вот обновлённый пример вашего юнита:
[Unit]
Description=LONG SURVIVING SERVICE
DefaultDependencies=no
After=local-fs.target sysinit.target
Before=shutdown.target
[Service]
Type=simple
Restart=always
RestartSec=1
TimeoutStopSec=60s
ExecStop=/bin/kill $MAINPID
ExecStart=/usr/bin/python3 -u /home/me/stay_alive.py
[Install]
WantedBy=multi-user.target
Пояснения по параметрам:
- TimeoutStopSec=60s: Дает вашему сервису до 60 секунд для завершения. Убедитесь, что ваш сервис может безопасно завершить свою работу за это время.
- ExecStop: Это команда, которая будет выполнена для остановки вашего сервиса. В данном случае, мы используем
kill $MAINPID
, чтобы отправить голос «SIGTERM» процессу, запущенному в вашем сервисе.
Рекомендации:
- В процессе тестирования, внимательно следите за журналами вашего сервиса. Вы можете использовать команду
journalctl -u <имя_вашего_сервиса>.service
для просмотра логов и убеждаться, что сервис правильно завершает свою работу и не обрывается непредвиденно. - Если ваш сервис управляет критически важными аспектами (такими как USB-подключение), проверьте, нет ли блокировок или задержек, которые могут повлиять на его работу в процессе завершения.
Соблюдение этих рекомендаций поможет сделать ваш сервис максимально устойчивым к завершению работы системы.