Задний план
Меня попросили создать systemd
скрипт для нового сервиса, foo_daemon
который иногда попадает в «плохое состояние» и не погибает через него SIGTERM
(вероятно, из-за пользовательского обработчика сигнала). Это проблематично для разработчиков, так как им поручено запустить / остановить / перезапустить сервис через:
systemctl start foo_daemon.service
systemctl stop foo_daemon.service
systemctl restart foo_daemon.service
проблема
Иногда, из- foo_daemon
за плохого состояния, мы вынуждены его принудительно убивать:
systemctl kill -s KILL foo_daemon.service
Вопрос
Как я могу настроить свой systemd
сценарий foo_daemon
так, чтобы всякий раз, когда пользователь пытается остановить / перезапустить службу,systemd
он:
- Попытка постепенного отключения
foo_daemon
черезSIGTERM
. - Дайте до 2 секунд для выключения / прекращения
foo_daemon
завершения. - Попытайтесь принудительно отключить функцию
foo_daemon
via,SIGKILL
если процесс еще активен (поэтому у нас нет риска повторного использования PID иsystemd
проблемSIGKILL
с неправильным PID). Устройство, которое мы тестируем, быстро порождает / разветвляет многочисленные процессы, поэтому существует редкая, но очень реальная проблема, связанная с рециркуляцией ПИД, вызывающей проблему. - Если на практике я просто параноик по поводу рециркуляции PID, я в порядке со сценарием, который просто выдает
SIGKILL
против PID процесса, не заботясь об уничтожении переработанного PID.
Ответы:
systemd уже поддерживает это "из коробки", и он включен по умолчанию .
Единственное, что вы можете настроить - это время ожидания, которое вы можете использовать
TimeoutStopSec=
. Например:Теперь systemd отправит SIGTERM, подождите две секунды, пока служба не выйдет, а если нет, отправит SIGKILL.
Если ваша служба не поддерживает systemd, вам может потребоваться указать путь к ее файлу PID
PIDFile=
.Наконец, вы упомянули, что ваш демон порождает много процессов. В этом случае вы можете установить,
KillMode=control-group
и systemd будет посылать сигналы всем процессам в cgroup.источник
Type=simple
в модуле systemd.Type=forking
имеет преимущество (если служба была написана правильно), информируя systemd, когда она полностью «готова», что Type = simple не может сделать. Демонизация не проблема, даже без файла PID - systemd все равно отследит основной процесс.Type=notify
лучше всего подходит для systemd, и многие обычные сервисы уже делают это. Но, вероятно, не этот устаревший сервис. В случае ОП у него есть служба, которая порождает много процессов. Документы systemd предупреждают об этом случае .Поскольку никто не упомянул о необходимости
Type=oneshot
, вот полный пример, который завершается из-за сбоя тайм-аута.источник