Назад | Перейти на главную страницу

Разрешить службе systemd останавливаться позже без блокировки на `systemctl stop`

У меня есть куча служб, отвечающих за выполнение действий, потребляемых из очереди.

Я хочу иметь возможность аккуратно перезапускать службы (не прерывая действия, которые уже выполняются)

Это может быть решено обработкой SIGTERM, отправленным systemd, и сохранением информации о том, что программа должна выйти после обработки текущего действия.
Есть еще одна небольшая проблема, связанная с тем, что через некоторое время определяется как TimeoutStopSec в файле конфигурации службы systemd отправит дополнительный сигнал SIGKILL, чтобы жестоко прервать мой процесс.
Я легко могу избежать этого, установив TimeoutStopSec=infinity. затем systemctl stopПодожду, пока скрипт не завершится сам, что может длиться даже больше часа, и приведет меня к основной проблеме.

Я не хочу systemctl команда дождаться завершения скрипта

Это выглядит как SendSIGKILL=no конфигурация делает свою работу. Это приводит к повторной попытке SIGTERM после TimeoutStopSec, затем создайте нового рабочего и оставив старый работающим.

journalctl журнал

May 06 14:14:43 jaku systemd[1]: Stopping Jaku test worker...
May 06 14:14:43 jaku python3[31597]: * 15 <frame object at 0x14d8108>
May 06 14:14:53 jaku systemd[1]: jaku-test-worker.service: State 'stop-sigterm' timed out. Skipping SIGKILL.
May 06 14:14:53 jaku python3[31597]: * 15 <frame object at 0x14d8108>
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode.
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: Failed with result 'timeout'.
May 06 14:15:03 jaku systemd[1]: Stopped Jaku test worker.
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: Found left-over process 31597 (python3) in control group while starting unit. Ignoring.
May 06 14:15:03 jaku systemd[1]: This usually indicates unclean termination of a previous run, or service implementation deficiencies.
May 06 14:15:03 jaku systemd[1]: Started Jaku test worker.
jaku@jaku:/nfs/home/jaku/tmp$ ps aux | grep "sig.py"
jaku     31597 99.9  0.0  31884  9916 ?        Rs   14:00  15:10 /usr/bin/python3 /home/jaku/tmp/sig.py
jaku     32359  100  0.0  31884 10032 ?        Rs   14:15   0:43 /usr/bin/python3 /home/jaku/tmp/sig.py
jaku     32483  0.0  0.0  15968  1040 pts/7    S+   14:15   0:00 grep --color=auto sig.py

Решение выглядит так, как будто оно делает свое дело, но меня беспокоит это предложение:

Обычно это указывает на нечистое завершение предыдущего прогона или недостатки в реализации службы.

Я чего-то упускаю или это действительно лучшее решение?

Ссылка:

Идея остановки службы systemd заключается в том, что все процессы, связанные с контрольной группой этого модуля, завершаются. После запуска любого ExecStop= а затем отправив KillSignal=, и, наконец, при необходимости FinalKillSignal=. Мне кажется разумным.

Ваше программное обеспечение обрабатывает SIGTERM, оставляя активные процессы, тогда устройство настроено на то, чтобы не отправлять SIGKILL. systemd считает, что это сломано, предупреждение подразумевает "недостатки реализации службы". Это не остановило.

Я не хочу, чтобы команда systemctl дождалась завершения скрипта

Затем выключите через минуту или около того. Пользователи службы не хотят ждать, пока она отключится; DefaultTimeoutStopSec= наверное 90-е годы. Пока ваш сервисный блок может увеличиваться TimeoutStopSec=, Я бы счел час неразумным временем для ожидания остановки чего-либо в сценарии инициализации.

Если у вас есть (синхронный) сценарий остановки, реализуйте его как ExecStop=. Если нет, немедленно обработайте SIGTERM как корректное завершение работы. Оставьте SIGKILL включенным в качестве последнего средства его остановки.


Существуют и другие способы остановить работу службы, кроме как убить ее процессы. Например, удаление его из балансировщика нагрузки и слив нагрузки.

Похоже, выхода нет, вот некоторые Связанный потоки.
Но ... Мое предположение, что Я не хочу systemctl команда дождаться завершения скрипта был неправ.

Я хотел, чтобы эта команда была короткой, потому что она должна была быть частью развертывания jenkins, и я не хотел, чтобы процесс развертывания занимал больше нескольких минут.
Чего я не знал, так это того, что мешает systemctl команда не останавливает процесс отключения службы, поэтому возможное решение:

Бег systemctl команда с ограничением по времени, например timeout 60 systemctl restart services-preifx-* || echo "processes will be restart in background"

Сейчас TimeoutStopSec можно установить какое-то высокое значение (например, 10h), чтобы предотвратить перезапуск службы навсегда.

Дополнительно KillMode=process должен быть установлен, чтобы не прерывать дочерние процессы.