El asesino de habitaciones generalmente tiene mala reputación entre los usuarios de Linux. Esto puede ser parte de la razón por la que Linux lo invoca sólo cuando no tiene otra opción. Cambiará el entorno de escritorio, eliminará toda la caché de la página y vaciará cada búfer antes de que finalmente finalice un proceso. Al menos eso es lo que creo que hará. Todavía tengo que tener la paciencia suficiente para esperarlo, sentado frente a un sistema que no responde.
Esto hizo que otras personas y yo nos preguntaramos si el oom-killer podría configurarse para intervenir antes: reddit r/linux, superuser.com, unix.stackexchange.com.
Resulta que no, no puede. Al menos usando el asesino del núcleo. En el espacio de usuario, sin embargo, podemos hacer lo que queramos.
earlyoom quiere ser simple y sólido. Está escrito en C puro sin dependencias. Un extenso conjunto de pruebas (pruebas unitarias y de integración) está escrito en Go.
earlyoom comprueba la cantidad de memoria disponible y el intercambio libre hasta 10 veces por segundo (con menos frecuencia si hay mucha memoria libre). De forma predeterminada, si ambos están por debajo del 10%, eliminará el proceso más grande ( oom_score
más alto). El valor porcentual se puede configurar mediante argumentos de la línea de comando.
En el resultado free -m
siguiente, la memoria disponible es 2170 MiB y el intercambio libre es 231 MiB.
total used free shared buff/cache available
Mem: 7842 4523 137 841 3182 2170
Swap: 1023 792 231
¿Por qué se comprueba la memoria "disponible" en lugar de la memoria "libre"? En un sistema Linux saludable, se supone que la memoria "libre" es cercana a cero, porque Linux utiliza toda la memoria física disponible para el acceso al disco en caché. Estos cachés se pueden eliminar cada vez que se necesite la memoria para otra cosa.
La memoria "disponible" se encarga de ello. Resume toda la memoria que no se utiliza o que se puede liberar inmediatamente.
Tenga en cuenta que necesita una versión reciente free
y el kernel de Linux 3.14+ para ver la columna "disponible". Si tiene un kernel reciente, pero una versión antigua de free
, puede obtener el valor de grep MemAvailable /proc/meminfo
.
Cuando tanto la memoria disponible como el intercambio libre caen por debajo del 10% de la memoria total disponible para los procesos del espacio de usuario (=total-compartido), enviará la señal SIGTERM
al proceso que utiliza la mayor cantidad de memoria en opinión del núcleo ( /proc/*/oom_score
).
earlyoom no usa echo f > /proc/sysrq-trigger
porque:
En algunas versiones del kernel (probadas en v4.0.5), activar manualmente el kernel oom killer no funciona en absoluto. Es decir, es posible que solo libere algo de memoria gráfica (que se asignará nuevamente inmediatamente) y no elimine ningún proceso. Aquí puede ver cómo se ve esto en mi máquina (gráficos integrados Intel).
Este problema se solucionó en Linux v5.17 (commit f530243a).
Al igual que lo haría el kernel de Linux, earlyoom encuentra a su víctima leyendo /proc/*/oom_score
.
Aproximadamente 2 MiB
( VmRSS
), aunque sólo 220 kiB
son memoria privada ( RssAnon
). El resto es la biblioteca libc ( RssFile
) que se comparte con otros procesos. Toda la memoria se bloquea usando mlockall()
para garantizar que earlyoom no se ralentice en situaciones de poca memoria.
Compilarse usted mismo es fácil:
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
Opcional: ejecute las autopruebas integradas:
make test
Inicie earlyoom automáticamente registrándolo como servicio:
sudo make install # systemd
sudo make install-initscript # non-systemd
Tenga en cuenta que para sistemas con SELinux deshabilitado (Ubuntu 19.04, Debian 9...) las advertencias de chcon que informan que no se pudo establecer el contexto se pueden ignorar de forma segura.
Para Debian 10+ y Ubuntu 18.04+, hay un paquete Debian:
sudo apt install earlyoom
Para Fedora y RHEL 8 con EPEL, existe un paquete Fedora:
sudo dnf install earlyoom
sudo systemctl enable --now earlyoom
Para Arch Linux, existe un paquete Arch Linux:
sudo pacman -S earlyoom
sudo systemctl enable --now earlyoom
Disponibilidad en otras distribuciones: ver página de repología.
Simplemente inicie el ejecutable que acaba de compilar:
./earlyoom
Le informará cuánta memoria y swap tiene, cuál es el mínimo, cuánta memoria está disponible y cuánto swap está libre.
./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%)
[...]
Si los valores caen por debajo del mínimo, los procesos se cancelan hasta que vuelven a estar por encima del mínimo. Cada acción se registra en stderr. Si está ejecutando earlyoom como un servicio systemd, puede ver las últimas 10 líneas usando
systemctl status earlyoom
Para ver earlyoom
en acción, cree/simule una pérdida de memoria y deje que earlyoom
haga lo que hace:
tail /dev/zero
Si necesita realizar más acciones después de que earlyoom
finalice un proceso (como enviar correos electrónicos), puede analizar los registros de la siguiente manera:
sudo journalctl -u earlyoom | grep sending
El resultado de ejemplo para el comando de prueba anterior ( tail /dev/zero
) se verá así:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
Para versiones anteriores de
earlyoom
, utilice:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
Desde la versión 1.6, earlyoom puede enviar notificaciones sobre procesos cancelados a través del sistema d-bus. Pase -n
para habilitarlos.
Para ver realmente las notificaciones en su sesión de GUI, necesita tener systembus-notify ejecutándose como su usuario.
Además, earlyoom puede ejecutar un script para cada proceso finalizado, proporcionando información sobre el proceso a través de las variables de entorno EARLYOOM_PID
, EARLYOOM_UID
y EARLYOOM_NAME
. Pase -N /path/to/script
para habilitar.
Advertencia: en el caso del modo de ejecución en seco, el script se ejecutará en rápida sucesión; asegúrese de tener implementado algún tipo de límite de velocidad.
La bandera de línea de comando --prefer
especifica los procesos que prefieren matar; Asimismo, --avoid
especifica procesos para evitar la muerte. Consulte https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex para obtener más detalles.
Si está ejecutando earlyoom como un servicio del sistema (a través de systemd o init.d), puede ajustar su configuración a través del archivo proporcionado en /etc/default/earlyoom
. El archivo ya contiene algunos ejemplos en los comentarios, que puede utilizar para crear su propio conjunto de configuración basado en las opciones de línea de comando admitidas, por ejemplo:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
Después de ajustar el archivo, simplemente reinicie el servicio para aplicar los cambios. Por ejemplo, para systemd:
systemctl restart earlyoom
Tenga en cuenta que este archivo de configuración no tiene ningún efecto en las instancias de earlyoom fuera de 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
Consulte la página de manual para obtener más detalles.
Los informes de errores y las solicitudes de extracción son bienvenidos a través de github. En particular, me alegro de aceptar
v1.8.2, 2024-05-07
earlyoom.service
process_mrelease
a las llamadas al sistema permitidas (compromiso)IPAddressDeny
(compromiso)-p
(confirmar)v1.8.1, 2024-04-17
v1.8, 2024-04-15
user mem total
/ meminfo_t.UserMemTotal
y calcule MemAvailablePercent en función de él (confirmar, más información en la página de manual)process_mrelease
(#266)NO_COLOR
(https://no-color.org/)--sort-by-rss
, ¡gracias @RanHuang! Esto seleccionará un proceso para eliminar ACC. al RSS más grande en lugar del oom_score más grande.v1.7, 2022-03-05
-N
para ejecutar un script cada vez que se finaliza un proceso (confirmación, sección de la página de manual)-g
para eliminar todo el grupo de procesos (#247)-i
(ignorado por compatibilidad), no funciona correctamente en los kernels de Linux 5.9+ (#234)v1.6.2, 2020-10-14
1.6.1, 2020-07-07
1.6, 2020-04-11
notify-send
con dbus-send
/ systembus-notify (#183)-n
/ -N
ahora habilita la nueva lógica/proc
montado con hidepid con gracia (problema #184)v1.5, 2020-03-22
-p
: establece oom_score_adj en -100
en lugar de -1000
(#170)-M
y -m
, y -S
y -s
. Se utilizará el valor más bajo (convertido a porcentajes).earlyoom.default
en 1 hora en lugar de 1 minuto (#177)v1.4, 2020-03-01
uid
de los procesos eliminados además del pid y el nombre.make test
)cppcheck
cuando esté disponiblemake bench
)earlyoom.service
v1.3.1, 2020-02-27
v1.3, 2019-05-26
v1.2, 2018-10-28
-k
, ahora ignorado por compatibilidad) (problema #80)v1.1, 2018-07-07
--help
además de -h
-S
(compromiso)v1.0, 2018-01-28
--prefer
y --avoid
(@TomJohnZ)-n
y -N
v0.12: Agregar opciones -M
y -S
(@nailgun); agregar página de manual, parametrizar Makefile (@yangfl)
v0.11: Se corrige el comportamiento indefinido en get_entry_fatal (falta retorno, confirmación)
v0.10: Permitir anular la variable VERSIÓN de Makefile para facilitar el empaquetado, agregar la opción de línea de comando -v
v0.9: si oom_score de todos los procesos es 0, use VmRss para encontrar una víctima
v0.8: Utilice una estimación si el kernel no proporciona MemAvailable
v0.7: seleccione la víctima mediante oom_score en lugar de VmRSS, agregue las opciones -i
y -d
v0.6: Agregar opciones de línea de comandos -m
, -s
, -k
v0.5: Agregar soporte de intercambio
v0.4: agregue el script de inicio SysV (gracias @joeytwiddle), use el nuevo MemAvailable
de /proc/meminfo
(necesita Linux 3.14+, confirmación)
v0.2: Agregar archivo de unidad systemd
v0.1: versión inicial