Фон

Фон

Фон

Меня попросили создать 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_daemonvia SIGTERM.
  • Дайте время до 2 секунд на foo_daemonзавершение работы/прекращения.
  • Попытайтесь принудительно завершить работу foo_daemonvia SIGKILL, если процесс все еще активен (чтобы не было риска повторного использования PID и systemdпроблем SIGKILLс неправильным PID). Устройство, которое мы тестируем, быстро порождает/разветвляет многочисленные процессы,поэтому существует редкая, но вполне реальная обеспокоенность тем, что переработка ФИД может стать причиной возникновения проблем.
  • Если на практике я просто параноидально отношусь к повторному использованию PID, то меня вполне устраивает, если скрипт просто выдает SIGKILLкоманду PID процесса, не беспокоясь об остановке повторно используемого PID.

решение1

systemd уже поддерживает это из коробки, и этовключено по умолчанию.

Единственное, что вы, возможно, захотите настроить, это тайм-аут, что вы можете сделать с помощью TimeoutStopSec=. Например:

[Service]
TimeoutStopSec=2

Теперь systemd отправит сигнал SIGTERM, подождет две секунды, пока служба не завершит работу, и если этого не произойдет, отправит сигнал SIGKILL.

Если ваша служба не поддерживает systemd, вам может потребоваться указать путь к ее PID-файлу с помощью PIDFile=.

Наконец, вы упомянули, что ваш демон порождает много процессов. В этом случае вы можете захотеть установить KillMode=control-groupи systemd будет отправлять сигналы всем процессам в cgroup.

решение2

Поскольку никто не упомянул о необходимости Type=oneshot, вот полный пример, который завершается из-за сбоя по тайм-ауту.

[Unit]
Description=timeout test

[Service]
Type=oneshot
TimeoutStartSec=2
ExecStart=/bin/sleep 10

Связанный контент