- ¿Cuál es la forma más rápida de recuperar el control de un sistema Linux que ha dejado de responder o extremadamente lento debido al intercambio excesivo?
Ya respondí anteriormente con Alt-SysRq-F
- ¿Existe una forma efectiva de evitar que ocurra tal intercambio en primer lugar, por ejemplo, limitando la cantidad de memoria que un proceso puede intentar asignar?
Estoy respondiendo esta segunda parte. Sí, ulimit
aún funciona lo suficientemente bien como para limitar un solo proceso. Usted puede:
- establecer un límite suave para un proceso que sabe que probablemente se saldrá de control
- establezca un límite estricto para todos los procesos si desea un seguro adicional
Además, como se menciona brevemente:
Puede usar CGroups para limitar el uso de recursos y prevenir tales problemas
De hecho, los cgroups ofrecen un control más avanzado, pero actualmente son más complicados de configurar en mi opinión.
Ulimit de la vieja escuela
Una vez fuera
Aquí hay un ejemplo simple:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
Eso:
- Establece un límite suave de uso de memoria total de 1GB (ulimit asume el límite en la unidad de KB)
- Ejecuta una llamada de función bash recursiva
r2(){ r2 $@$@;};r2 r2
que masticará exponencialmente la CPU y la RAM al duplicarse infinitamente mientras solicita memoria de pila.
Como puede ver, se detuvo al intentar solicitar más de 1 GB.
Tenga en cuenta que -v
funciona con asignación de memoria virtual (total, es decir, físico + intercambio).
Protección permanente
Para limitar la asignación de memoria virtual, as
es el equivalente de -v
para limits.conf
.
Hago lo siguiente para protegerme contra cualquier proceso de mala conducta:
- Establezca un límite de espacio de direcciones rígidas para todos los procesos.
address space limit = <physical memory> - 256MB
.
- Por lo tanto, ningún proceso único con uso codicioso de memoria o un bucle activo y pérdida de memoria puede consumir TODA la memoria física.
- El espacio libre de 256 MB está ahí para el procesamiento esencial con ssh o una consola.
Un trazador de líneas:
$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"
Para validar, esto da como resultado lo siguiente (por ejemplo, en un sistema de 16 GB):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Notas:
- Solo mitiga contra un solo proceso que se va por la borda con el uso de memoria.
- No evitará una carga de trabajo multiproceso con una fuerte presión de memoria que provoque golpes (entonces cgroups es la respuesta).
- No use la
rss
opción en limits.conf. No es respetado por los núcleos más nuevos.
- Es conservador
- En teoría, un proceso puede solicitar especulativamente una gran cantidad de memoria, pero solo usa activamente un subconjunto (un conjunto de trabajo más pequeño / uso de memoria residente).
- El límite duro anterior hará que dichos procesos se cancelen (incluso si de otro modo hubieran funcionado bien dado que Linux permite que el espacio de direcciones de la memoria virtual se sobrecompita).
Grupos CG más nuevos
Ofrece más control, pero actualmente es más complejo de usar:
- Mejora en la oferta de ulimit.
memory.max_usage_in_bytes
puede contabilizar y limitar la memoria física por separado.
- Mientras que
ulimit -m
y / o rss
en el limits.conf
que estaba destinado a ofrecer una funcionalidad similar, pero que no funciona desde el núcleo de Linux 2.4.30!
- Necesita habilitar algunas banderas del núcleo cgroup en gestor de arranque:
cgroup_enable=memory swapaccount=1
.
- Esto no sucedió por defecto con Ubuntu 16.04.
- Probablemente debido a algunas implicaciones de rendimiento de la sobrecarga contable adicional.
- El material cgroup / systemd es relativamente nuevo y está cambiando bastante, por lo que el flujo ascendente implica que los proveedores de distribución de Linux aún no lo han hecho fácil de usar. Entre 14.04LTS y 16.04LTS, las herramientas de espacio de usuario para usar cgroups han cambiado.
cgm
ahora parece ser la herramienta de espacio de usuario oficialmente compatible.
- Los archivos de la unidad systemd todavía no parecen tener valores predeterminados predefinidos de "proveedor / distribución" para priorizar servicios importantes como ssh.
Por ejemplo, para verificar la configuración actual:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Por ejemplo, para limitar la memoria de un solo proceso:
$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed
Para verlo en acción masticando RAM como un proceso en segundo plano y luego asesinado:
$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
0.0 0.0 2876
102 0.2 44056
103 0.5 85024
103 1.0 166944
...
98.9 5.6 920552
99.1 4.3 718196
[1]+ Killed bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'
Tenga en cuenta el crecimiento exponencial (potencia de 2) en las solicitudes de memoria.
En el futuro, esperemos ver "distro / vendors" preconfigurar las prioridades y límites de cgroup (a través de unidades systemd) para cosas importantes como SSH y la pila gráfica, de modo que nunca pierdan memoria.