Вопрос или проблема
Недавно у меня отключился сервис из-за oom-kill
.
$ systemctl status my-server.service
● my-server.service - "General purposes load-independent HTTP server"
Loaded: loaded (/lib/systemd/system/my-server.service; enabled; vendor preset: enabled)
Active: failed (Result: oom-kill) since Thu 2025-02-27 12:47:44 CST; 17h ago
Process: 636 ExecStart=/usr/bin/my-server --listen-http :13668 --threads 10 (code=exited, status=0/SUCCESS)
Main PID: 636 (code=exited, status=0/SUCCESS)
CPU: 52min 57.893s
Feb 27 12:47:44 ios systemd[1]: my-server.service: A process of this unit has been killed by the OOM killer.
Feb 27 12:47:44 ios my-server[636]: Received signal to stop (15). Stopping...
Feb 27 12:47:44 ios systemd[1]: my-server.service: Failed with result 'oom-kill'.
Feb 27 12:47:44 ios systemd[1]: my-server.service: Consumed 52min 57.893s CPU time.
man systemd.exec
говорит, что $SERVICE_RESULT
устанавливается в oom-kill
, когда “Процесс службы был завершен из-за недостатка памяти (OOM killer).”
Это была утечка памяти в длительно работающем дочернем процессе /usr/bin/my-server
. Когда это происходит, я бы хотел использовать Restart=
для перезапуска сервиса.
Вопрос:
Вызывает ли $SERVICE_RESULT=oom-kill
неочищенный код завершения или неочищенный сигнал?
Я бы хотел как можно больше ограничить свой Restart=
. Поэтому я хочу выбрать первое условие, которое соответствует критериям oom-kill
из списка ниже:
Restart=on-abort
можно использовать, если это был неочищенный сигнал.Restart=on-abnormal
может быть использован для вышеуказанного случая, или если это вызывает тайм-аут или причину срабатывания watchdog (вероятно, неприменимо).Restart=on-failure
работает для всех вышеперечисленных случаев, плюс неочищенный код завершения.Restart=always
теоретически покрывает все случаи
Из man systemd.service
:
Table 2. Exit causes and the effect of the Restart= settings
┌──────────────────────┬────┬────────┬────────────┬────────────┬─────────────┬──────────┬─────────────┐
│Restart settings/Exit │ no │ always │ on-success │ on-failure │ on-abnormal │ on-abort │ on-watchdog │
│causes │ │ │ │ │ │ │ │
├──────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Clean exit code or │ │ X │ X │ │ │ │ │
│signal │ │ │ │ │ │ │ │
├──────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Unclean exit code │ │ X │ │ X │ │ │ │
├──────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Unclean signal │ │ X │ │ X │ X │ X │ │
├──────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Timeout │ │ X │ │ X │ X │ │ │
├──────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Watchdog │ │ X │ │ X │ X │ │ X │
└──────────────────────┴────┴────────┴────────────┴────────────┴─────────────┴──────────┴─────────────┘
Ответ или решение
Вопрос о том, является ли результат вызова Out-Of-Memory (OOM) Killer в systemd "нечистым сигналом" или "нечистым кодом завершения", требует рассмотрения некоторых технических подробностей, связанных с работой systemd и поведения процессов в операционной системе Linux.
Теория
Systemd выполняет роль системы инициализации в большинстве дистрибутивов Linux, управляя сервисами и сопутствующими процессами. Когда какая-либо программа потребляет слишком много памяти, Linux может активировать OOM Killer, чтобы освободить ресурсы убив проблемный процесс. В контексте systemd, если OOM Killer прекращает выполнение одного из процессов службы, соответствующий $SERVICE_RESULT будет равен "oom-kill".
Когда процесс погибает от OOM Killer, он получает сигнал SIGKILL (сигнал 9), который считается "нечистым" (или "unclean"), так как этот сигнал не может быть обработан самим процессом с целью корректного завершения текущих операций. Следовательно, убитый процесс не имеет возможности возвратить код завершения. Это подводит к выводу, что результат "oom-kill" отображает сценарий "нечистого сигнала", а не "нечистого кода завершения".
Пример
Рассматривая предоставленный сценарий, ваш сервис "my-server" был убит OOM Killer из-за утечки памяти в дочернем процессе. В результате команды systemctl status
показано:
my-server.service: A process of this unit has been killed by the OOM killer.
Здесь видно, что systemd однозначно идентифицировал причину остановки — процесс был убит OOM Killer. Это именно то, что понимается под "нечистым сигналом", поскольку был получен сигнал SIGKILL.
Применение
Теперь, если вы хотите правильно настроить поведение вашего сервиса в случае таких ситуаций, следует выбрать наиболее подходящее значение для параметра Restart=
в вашем unit-файле systemd.
-
Restart=on-abort: Это значение перезапустит сервис только если он завершился от "нечистого сигнала", что идеально подходит в случае использования OOM Killer.
-
Restart=on-abnormal: Это более широкая категория, включающая также сценарии тайм-аута и проблемы с watchdog. Хотя это значение перезагружается при нечистом завершении, оно добавляет возможности, которые вам могут быть не нужны.
-
Restart=on-failure: Это значение запускается при всех сценариях, когда служба аварийно завершилась, в том числе и по причинам "нечистого кода завершения". Будет избыточным, если ваш текущий запрос направлен только на обработку OOM Killer.
-
Restart=always: Самое широкое значение, которое перезапустит сервис в любых случаях. Оно может быть слишком большим охватом для вашего конкретного сценария.
На основании вышеизложенного, для вашей конкретной задачи "Restart=on-abort" кажется наиболее подходящим, чтобы минимизировать количество ненужных перезапусков и четко зарегистрировать и использовать именно тот сценарий, с которым вы столкнулись.
В дополнение к исправлению текущих настроек, рекомендуется также исследовать и устранить первичную причину проблем с памятью, чтобы снизить вероятность повторения проблем и зависимости исключительно от перезагрузок для поддержания доступности сервиса. Оптимизация потребления памяти приложением или установка предельных значений через cgroups может быть полезным в этой ситуации.