У oom-killer обычно плохая репутация среди пользователей Linux. Возможно, это одна из причин, по которой Linux вызывает его только тогда, когда у него нет другого выбора. Он заменит среду рабочего стола, удалит весь кэш страниц и очистит каждый буфер, прежде чем в конечном итоге убьет процесс. По крайней мере, я так думаю. Мне еще предстоит набраться терпения, чтобы дождаться этого, сидя перед неотвечающей системой.
Это заставило меня и других людей задуматься, можно ли настроить oom-killer для более раннего вмешательства: reddit r/linux, superuser.com, unix.stackexchange.com.
Как оказалось, нет, не может. По крайней мере, используя встроенный в ядро oom-killer. Однако в пользовательском пространстве мы можем делать все, что захотим.
Earlyoom хочет быть простым и надежным. Он написан на чистом C без каких-либо зависимостей. Обширный набор тестов (юнит- и интеграционные тесты) написан на Go.
Earlyoom проверяет объем доступной памяти и свободный своп до 10 раз в секунду (реже, если свободной памяти много). По умолчанию, если оба значения ниже 10%, будет уничтожен самый большой процесс (самый высокий oom_score
). Процентное значение настраивается с помощью аргументов командной строки.
В выводе free -m
ниже доступная память составляет 2170 МБ, а свободный своп — 231 МБ.
total used free shared buff/cache available Mem: 7842 4523 137 841 3182 2170 Swap: 1023 792 231
Почему проверяется «доступная» память, а не «свободная» память? В работоспособной системе Linux «свободная» память должна быть близка к нулю, поскольку Linux использует всю доступную физическую память для кэширования доступа к диску. Эти кэши можно удалить в любой момент, когда память понадобится для чего-то другого.
За это отвечает «доступная» память. Он суммирует всю память, которая не используется или может быть немедленно освобождена.
Обратите внимание, что вам нужна последняя free
версия и ядро Linux 3.14+, чтобы увидеть столбец «доступно». Если у вас недавнее ядро, но старая версия free
, вы можете получить значение из grep MemAvailable /proc/meminfo
.
Когда объем доступной памяти и свободной подкачки упадет ниже 10 % от общей памяти, доступной процессам пользовательского пространства (=total-shared), он отправит сигнал SIGTERM
процессу, который использует больше всего памяти, по мнению ядра ( /proc/*/oom_score
).
nohang — проект, аналогичный Earlyoom, написанный на Python и имеющий дополнительные функции и параметры конфигурации.
Исправления ядра Facebook с информацией о остановке давления (psi) и сопутствующий помощник пользовательского пространства oomd. Патчи объединены в Linux 4.20.
Earlyoom не использует echo f > /proc/sysrq-trigger
потому что:
В некоторых версиях ядра (проверено на v4.0.5) запуск ядра oom killer вручную вообще не работает. То есть он может освободить только некоторую часть графической памяти (которая будет немедленно снова выделена), но не завершить какой-либо процесс. Здесь вы можете увидеть, как это выглядит на моей машине (встроенная графика Intel).
Эта проблема исправлена в Linux v5.17 (коммит f530243a).
Как и ядро Linux, Earlyoom находит свою жертву, читая /proc/*/oom_score
.
Около 2 MiB
( VmRSS
), хотя только 220 kiB
— частная память ( RssAnon
). Остальное — это библиотека libc ( RssFile
), которая используется совместно с другими процессами. Вся память блокируется с помощью mlockall()
чтобы Earlyoom не замедлялся в ситуациях с нехваткой памяти.
Собрать самостоятельно легко:
git клон https://github.com/rfjakob/earlyoom.gitcd Earlyoom делать
Необязательно: Запустите встроенные самотестирования:
сделать тест
Запустите Earlyoom автоматически, зарегистрировав его как службу:
sudo make install # systemdsudo make install-initscript # не-systemd
Обратите внимание, что для систем с отключенным SELinux (Ubuntu 19.04, Debian 9...) предупреждения chcon, сообщающие о невозможности установки контекста, можно безопасно игнорировать.
Для Debian 10+ и Ubuntu 18.04+ есть пакет Debian:
sudo apt установить Earlyoom
Для Fedora и RHEL 8 с EPEL существует пакет Fedora:
sudo dnf установить раноум sudo systemctl Enable --now Earlyoom
Для Arch Linux есть пакет Arch Linux:
sudo pacman -S раноум sudo systemctl Enable --now Earlyoom
Доступность в других дистрибутивах: см. страницу релогии.
Просто запустите только что скомпилированный исполняемый файл:
./ранний
Он сообщит вам, сколько у вас памяти и подкачки, каков минимум, сколько памяти доступно и сколько подкачки свободно.
./earlyoom eearlyoom v1.8 mem total: 23890 MiB, user mem total: 21701 MiB, swap total: 8191 MiB sending SIGTERM when mem avail <= 10.00% and swap free <= 10.00%, SIGKILL when mem avail <= 5.00% and swap free <= 5.00% mem avail: 20012 of 21701 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20031 of 21721 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20033 of 21723 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) [...]
Если значения падают ниже минимума, процессы завершаются до тех пор, пока оно снова не превысит минимум. Каждое действие записывается в stderr. Если вы используете Earlyoom как службу systemd, вы можете просмотреть последние 10 строк, используя
Статус systemctl Earlyoom
Чтобы увидеть earlyoom
в действии, создайте/моделируйте утечку памяти и позвольте earlyoom
делать то, что он делает:
tail /dev/zero
Если вам нужны какие-либо дальнейшие действия после завершения процесса earlyoom
(например, отправка электронных писем), вы можете проанализировать журналы следующим образом:
sudo journalctl -u earlyoom | grep sending
Пример вывода приведенной выше тестовой команды ( tail /dev/zero
) будет выглядеть так:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
Для более старых версий
earlyoom
используйте:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
Начиная с версии 1.6, Earlyoom может отправлять уведомления об остановленных процессах через системную d-шину. Передайте -n
чтобы включить их.
Чтобы действительно видеть уведомления в сеансе графического интерфейса, вам необходимо запустить systembus-notify от имени вашего пользователя.
Кроме того, Earlyoom может выполнять сценарий для каждого убитого процесса, предоставляя информацию о процессе через переменные среды EARLYOOM_PID
, EARLYOOM_UID
и EARLYOOM_NAME
. Передайте -N /path/to/script
чтобы включить.
Предупреждение: в режиме сухого запуска сценарий будет выполняться в быстрой последовательности, убедитесь, что у вас установлено какое-то ограничение скорости.
Флаг командной строки --prefer
указывает процессы, которые предпочитают уничтожать; аналогично, --avoid
указывает процессы, которые следует избегать. Подробности см. на https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex.
Если вы используете Earlyoom как системную службу (через systemd или init.d), вы можете настроить его конфигурацию с помощью файла, предоставленного в /etc/default/earlyoom
. В комментариях файл уже содержит несколько примеров, которые вы можете использовать для создания собственного набора конфигурации на основе поддерживаемых параметров командной строки, например:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
После настройки файла просто перезапустите службу, чтобы изменения вступили в силу. Например, для systemd:
systemctl перезапустить раньше
Обратите внимание, что этот файл конфигурации не влияет на экземпляры Earlyoom за пределами systemd/init.d.
earlyoom v1.8 Usage: ./earlyoom [OPTION]... -m PERCENT[,KILL_PERCENT] set available memory minimum to PERCENT of total (default 10 %). earlyoom sends SIGTERM once below PERCENT, then SIGKILL once below KILL_PERCENT (default PERCENT/2). -s PERCENT[,KILL_PERCENT] set free swap minimum to PERCENT of total (default 10 %). Note: both memory and swap must be below minimum for earlyoom to act. -M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB -S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB -n enable d-bus notifications -N /PATH/TO/SCRIPT call script after oom kill -g kill all processes within a process group -d, --debug enable debugging messages -v print version information and exit -r INTERVAL memory report interval in seconds (default 1), set to 0 to disable completely -p set niceness of earlyoom to -20 and oom_score_adj to -100 --ignore-root-user do not kill processes owned by root --sort-by-rss find process with the largest rss (default oom_score) --prefer REGEX prefer to kill processes matching REGEX --avoid REGEX avoid killing processes matching REGEX --ignore REGEX ignore processes matching REGEX --dryrun dry run (do not kill any processes) --syslog use syslog instead of std streams -h, --help this help text
Подробности смотрите на странице руководства.
Сообщения об ошибках и запросы на включение приветствуются через github. В частности, я рад принять
Отчеты о вариантах использования и отзывы
Мы не используем procps/libproc2, потому что procps_pids_select() по какой-то причине всегда анализирует /proc/$pid/status. Это относительно дорого, и нам это не нужно.
v1.8.2, 7 мая 2024 г.
Добавить process_mrelease
в разрешенные системные вызовы (фиксация)
Исправление синтаксиса IPAddressDeny
(фиксация)
Разрешить -p
(фиксировать)
Исправления в файле системного модуля earlyoom.service
v1.8.1, 17 апреля 2024 г.
Исправление тривиальных ошибок тестирования, вызванных изменением формулировки сообщения (фиксация)
v1.8, 15 апреля 2024 г.
Введите user mem total
/ meminfo_t.UserMemTotal
и рассчитайте MemAvailablePercent на его основе (фиксация, дополнительная информация на странице руководства)
Используйтеprocess_mrelease (# process_mrelease
)
Поддержка NO_COLOR
(https://no-color.org/)
Не запутайтесь в процессах с основным потоком-зомби (коммит)
Добавьте --sort-by-rss
, спасибо @RanHuang! Это выберет процесс для уничтожения акк. к самому большому RSS вместо самого большого oom_score.
Набор тестов Gitlab CI теперь также работает на Amazon Linux 2 и Oracle Linux 7.
v1.7, 5 марта 2022 г.
Добавьте флаг -N
для запуска сценария каждый раз при завершении процесса (фиксация, раздел man-страницы)
Добавьте флаг -g
, чтобы уничтожить всю группу процессов (#247).
Удалите флаг -i
(игнорируется для совместимости), он не работает должным образом в ядрах Linux 5.9+ (#234).
Усиление защиты: отключите возможности окружения при запуске (# 234).
v1.6.2, 14 октября 2020 г.
Перепроверьте ситуацию с памятью перед убийством жертвы (фиксация)
Никогда не прекращайте себя (#205)
Дамп буфера при ошибке преобразования /proc/meminfo (#214)
1.6.1, 07.07.2020
Очистка зомби-процессов dbus-send (#200)
Пропустить процессы с oom_score_adj=-1000 (210)
1.6, 11.04.2020
-n
/ -N
теперь включает новую логику
Вам необходимо запустить systembus-notify в сеансе графического интерфейса для уведомлений о работе.
Замените старую логику уведомлений GUI notify-send
на dbus-send
/systembus-notify (#183).
Обработать /proc
, смонтированный с помощью Hidepid (проблема № 184).
v1.5, 22 марта 2020 г.
-p
: установить oom_score_adj на -100
вместо -1000
(#170)
Разрешить использование как -M
и -m
, так и -S
и -s
. Будет использовано меньшее значение (преобразованное в проценты).
Установите интервал отчета о памяти в earlyoom.default
на 1 час вместо 1 минуты (#177).
v1.4, 1 марта 2020 г.
Используйте блочные локальные переменные, где это возможно.
Введите PATH_LEN для замены нескольких жестко запрограммированных длин буфера.
Ускорьте логику выбора жертвы на 50 % за счет отложенной загрузки атрибутов процесса.
Зарегистрируйте идентификатор пользователя uid
завершенных процессов в дополнение к pid и имени.
Цвет журнала отладки светло-серый.
Очистка кода
Развернуть набор тестов ( make test
)
Запустите cppcheck
если он доступен.
Добавьте тесты модульного тестирования ( make bench
)
Откажитесь от root-прав в файле модуля systemd earlyoom.service
v1.3.1, 27 февраля 2020 г.
Исправление ложного сбоя набора тестов в системах с большим объемом оперативной памяти (проблема № 156).
v1.3, 26 мая 2019 г.
Не завершайте работу с фатальной ошибкой, если предел SIGTERM < предел SIGKILL.
Разрешить нулевой лимит SIGKILL
Это устраняет проблему, из-за которой Earlyoom иногда убивает более одного процесса, хотя одного было бы достаточно (проблема № 121).
Подождите, пока процессы завершатся при отправке сигнала.
Будьте более либеральны в отношении ограничений, принимаемых для SIGTERM и SIGKILL (выпуск № 97).
Переформатируйте выходные данные запуска, чтобы было ясно, что ОБА swap и mem должны быть <= limit.
Добавьте вспомогательный скрипт notify_all_users.py.
Добавить CODE_OF_CONDUCT.md (Соглашение участника 1.4) (#102)
Исправьте возможно усеченные имена приложений UTF8 в выводе журнала (# 110).
v1.2, 28 октября 2018 г.
Внедрите адаптивное время сна (= адаптивную частоту опроса), чтобы еще больше снизить загрузку ЦП (проблема № 61).
Удалить опцию использования ядра oom-killer ( -k
, теперь игнорируется для совместимости) (проблема № 80).
Грамотная обработка случаев добавления или удаления свопа после запуска Earlyoom (ошибка 62, фиксация)
Реализуйте поэтапное уничтожение: сначала SIGTERM, затем SIGKILL с настраиваемыми ограничениями (проблема № 67).
v1.1, 7 июля 2018 г.
Исправление возможного внедрения шелл-кода через уведомления графического интерфейса (фиксация)
Если не удалось завершить какой-либо процесс, сон длится только 1 секунду вместо 10 (проблема № 74).
Отправлять уведомление графического интерфейса после убийства, а не раньше (проблема № 73).
Примите --help
в дополнение к -h
Исправьте неправильное имя процесса в журнале и в уведомлении об уничтожении (фиксация 1, фиксация 2, проблема № 52, проблема № 65, проблема № 194).
Исправить возможное деление на ноль с помощью -S
(фиксация)
v1.0, 28 января 2018 г.
Добавьте опции --prefer
и --avoid
(@TomJohnZ)
Добавьте поддержку уведомлений графического интерфейса, добавьте параметры -n
и -N
v0.12: Добавлены опции -M
и -S
(@nailgun); добавить справочную страницу, параметризовать Makefile (@yangfl)
v0.11: Исправлено неопределенное поведение в get_entry_fatal (отсутствует возврат, фиксация)
v0.10: разрешено переопределять переменную VERSION в Makefile, чтобы упростить упаковку, добавьте параметр командной строки -v
v0.9: Если oom_score всех процессов равен 0, используйте VmRss для поиска жертвы.
v0.8: используйте приблизительную оценку, если ядро не предоставляет MemAvailable.
v0.7: Выберите жертву по oom_score вместо VmRSS, добавьте опции -i
и -d
v0.6: Добавлены параметры командной строки -m
, -s
, -k
v0.5: Добавлена поддержка свопа.
v0.4: Добавьте сценарий инициализации SysV (спасибо @joeytwiddle), используйте новый MemAvailable
из /proc/meminfo
(требуется Linux 3.14+, зафиксируйте)
v0.2: Добавить файл модуля systemd
v0.1: Начальная версия