signal=KILL (status=9/KILL) в systemd
Сигнал KILL нельзя перехватить: процесс исчезает мгновенно, без сохранения данных и без прощальных строк в журнале. Поэтому вопрос не «почему программа упала», а «кто её убил». Обычно это OOM-killer ядра, сам systemd по истечении таймаута остановки или человек с командой kill -9.
Что это значит
Разобраться помогает строка Result: в состоянии службы. oom-kill — убило ядро из-за нехватки памяти. timeout — systemd не дождался остановки и добил процесс. Просто signal без уточнения — сигнал пришёл извне.
В записях ядра при нехватке памяти всегда остаётся след: строка про «Out of memory: Killed process» с именем и объёмом. Если её нет, а служба убита KILL, ищите того, кто послал сигнал вручную или сценарием.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Процесс убит ядром из-за нехватки памяти
При исчерпании памяти в контрольной группе или на машине ядро выбирает процесс и убивает его сигналом KILL. Для служб с
MemoryMax=это происходит по достижении предела, даже когда на машине память есть. -
systemd добил процесс после таймаута остановки
При остановке systemd посылает TERM, ждёт
TimeoutStopSec=(по умолчанию 90 секунд) и затем посылает KILL. Программа, которая долго завершает работу или игнорирует TERM, всегда будет получать KILL. -
Сигнал послан вручную или сторонним средством
Команда
kill -9, сценарий обслуживания, сторожевой скрипт или средство мониторинга могли убить процесс. systemd об этом не знает и просто сообщает факт. -
Процесс убит вместе с группой при остановке другой службы
При
KillMode=control-groupостанавливаются все процессы контрольной группы. Если ваш процесс оказался в чужой группе (например запущен из чужого unit), он умрёт вместе с ней.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Строка Result: уточняет причину: oom-kill, timeout или просто signal.
systemctl status myapp.service -l --no-pagerСлед OOM-killer в записях ядра. Если строки нет, память тут не при чём.
journalctl -k -b --no-pager | grep -i "killed process"Полная картина событий: остановка по команде выглядит иначе, чем внезапная смерть.
journalctl -u myapp.service --since "30 min ago" --no-pagerТри числа, которые чаще всего объясняют KILL.
systemctl show myapp.service -p MemoryMax -p MemoryPeak -p TimeoutStopSecРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- При исчерпании памяти в контрольной группе или на машине ядро выбирает процесс и убивает его сигналом KILL. Для служб с
MemoryMax=это происходит по достижении предела, даже когда на машине память есть.
- Как проверить
-
Посмотрите записи ядра и предел памяти у службы.
journalctl -k -b --no-pager | grep -iE "out of memory|oom-kill" systemctl show myapp.service -p MemoryMax -p MemoryPeak
- Как исправить
-
Поднимите
MemoryMax=или уменьшите потребление программы. Разовое повышение предела без разбора роста потребления только отложит проблему.sudo systemctl edit myapp.service # MemoryMax=2G
- Почему происходит
- При остановке systemd посылает TERM, ждёт
TimeoutStopSec=(по умолчанию 90 секунд) и затем посылает KILL. Программа, которая долго завершает работу или игнорирует TERM, всегда будет получать KILL.
- Как проверить
-
Поищите в журнале строку про таймаут остановки.
journalctl -u myapp.service -n 40 --no-pager | grep -iE "stop|timeout|SIGKILL" systemctl show myapp.service -p TimeoutStopSec -p KillSignal
- Как исправить
-
Увеличьте
TimeoutStopSec=до времени, которое программе действительно нужно на корректное завершение, и убедитесь, что она реагирует на TERM. Если ей нужен другой сигнал, задайтеKillSignal=.TimeoutStopSec=300
- Почему происходит
- Команда
kill -9, сценарий обслуживания, сторожевой скрипт или средство мониторинга могли убить процесс. systemd об этом не знает и просто сообщает факт.
- Как проверить
-
Посмотрите записи вокруг момента смерти и активность администраторов.
journalctl --since "10 min ago" --no-pager | grep -iE "kill|stopped|session" last -n 10
- Как исправить
-
Найдите источник. Если это ваш сценарий обслуживания, замените
kill -9наsystemctl stop: systemd остановит службу по правилам unit-файла, а не оборвёт процесс.
- Почему происходит
- При
KillMode=control-groupостанавливаются все процессы контрольной группы. Если ваш процесс оказался в чужой группе (например запущен из чужого unit), он умрёт вместе с ней.
- Как проверить
-
Посмотрите, в какой группе живёт процесс.
systemd-cgls --no-pager | grep -B5 myapp systemctl show myapp.service -p KillMode
- Как исправить
- Запускайте программу собственным unit-файлом, а не из скрипта другой службы: тогда у неё будет своя контрольная группа.
Пример вывода
Служба убита ядром при достижении предела памяти. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× indexer.service - Search indexer
Loaded: loaded (/etc/systemd/system/indexer.service; enabled; preset: enabled)
Active: failed (Result: oom-kill) since Mon 2026-09-15 03:41:55 MSK; 1min ago
Main PID: 7781 (code=killed, signal=KILL)
Memory: 512.0M (max: 512.0M available: 0B)
kernel: Memory cgroup out of memory: Killed process 7781 (indexer) total-vm:2412480kB, anon-rss:519424kB
systemd[1]: indexer.service: A process of this unit has been killed by the OOM killer.
systemd[1]: indexer.service: Main process exited, code=killed, status=9/KILL
systemd[1]: indexer.service: Failed with result 'oom-kill'.
Частые вопросы
Почему в журнале нет ни одной строки от самой программы перед смертью?
Потому что KILL не перехватывается: программа не получает управления и не успевает ничего записать. Это нормальное поведение, а не потеря журнала.
Связанные ошибки
- Failed with result 'oom-kill' Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
- signal=TERM (status=15/TERM) в systemd Процесс службы завершён сигналом TERM. Когда это нормальная остановка, а когда признак проблемы.
- Failed with result 'timeout' Состояние timeout: служба не уложилась в отведённое время при запуске, остановке или перезагрузке настроек.
- status=204/MEMORY в systemd Код 204/MEMORY: systemd не смог выделить память при подготовке запуска службы. Что проверять на машине и в unit-файле.
- MySQL убит из-за памяти: буферный пул больше доступной памяти MySQL падает сразу после старта или через минуты: размер innodb_buffer_pool_size превышает память машины.
- signal=INT и signal=QUIT в systemd Процесс службы завершён сигналом INT или QUIT. Кто их посылает службам и почему это обычно не systemd.
- signal=SEGV (status=11/SEGV) в systemd Процесс службы завершён сигналом SEGV: обращение к недопустимой памяти. Как собрать дамп и что смотреть.
- status=206/OOM_ADJUST в systemd Код 206/OOM_ADJUST: не удалось изменить оценку OOM для процесса службы. Обычно мешают права или значение вне диапазона.
Где встречается чаще всего
Источники
-
systemd.kill(5)
KillSignal=, KillMode= и порядок посылки сигналов при остановке. -
systemd.resource-control(5)
MemoryMax= и поведение при достижении предела памяти. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на службе с MemoryMax=64M и на программе, игнорирующей TERM.