En estos días me toco recuperar mi VPS vía consola remota, al revisar el /var/log/messages me di cuenta de el Out of Memory Killer (OOM Killer)
había hecho de las suyas al quedarse sin memoria. Luego de analizar detenidamente los logs y me di cuenta que fue una combinación de
factores, Google, Yahoo y Yandex me estaban indexando tanto este blog
como unos foros de autos que alojo en este servidor al mismo tiempo.
El script para descargar torrents estaba corriendo al igual que el torrent tracker y alguien me estaba haciendo flood vía IRC en freenode puede
había dejado irssi conectado.
El OOM Killer tiene un algoritmo que decide que procesos son los mejores para aniquilar sin embargo es posible manipular estos valores y
dejarle saber al OOM Killer que procesos prefieres que mate primero.
Para automatizar esta tarea hice un script que nos ayudara con esta
tarea:
for programas in SCREEN irssi top
do for pid_of_oomk_candidate in `pidof -x $programas`
do echo 10 > /proc/$pid_of_oomk_candidate/oom_adj
done
done
Como ven el script anterior agrega 10 al OOMK score a los procesos que menos me interesan permanezcan vivos cuando me quede sin memoria
mientras que el siguiente hará exactamente lo contrario, mantendrá vivo
un poco mas estos procesos:
for programas in mysqld portsentry iptables
do for pid_of_oomk_candidate in `pidof -x $programas`
do echo -5 > /proc/$pid_of_oomk_candidate/oom_adj
done
done
echo -17 > /proc/`pidof -s sshd`/oom_adj
En este ultimo mysql portsentry y iptables tendrán cinco puntos de ventaja en relación con el resto de los candidatos y si se fijan en la
ultima linea estamos asegurándonos que sshd no sea candidato bajo
ninguna circunstancia.
Automatizar el ajuste del score para el OOM Killer
Ahora unifiquemos estos dos scripts y demosle un poco mas de
flexibilidad, estoy seguro que hay gente que prefiere asignarle a irssi
un valor distinto de screen. Lo primero que necesitaremos es un script
de configuración, vamos crearlo en /etc/candidatos_oomk.conf y el
contenido se debería de ver algo así:
# Programas que queremos sacrificar, entre mas alto el valor
# mas peso tienen en la lista de candidatos.
irssi 4
SCREEN 3
smtpd 2
apache2 1
# Programas que queremos salvar, estos tendrán valores negativos
portsentry -2
mysqld -5
sshd -17
El script al que le puse de nombre oomk_adj_candidatos.sh se veria algo asi:
#!/bin/bash
CONFIGURACION="/etc/candidatos_oomk.conf"
while read programas
do proceso=`echo $programas |grep -v \# | grep [0-9]$| awk '{print $1}'`
ajuste=`echo $programas |grep -v \# | grep [0-9]$| awk '{print $2}'`
if [ -z "$proceso" ] then
continue
else
echo $proceso
for pids_proceso in `/bin/pidof $proceso`
do echo " echo $ajuste > /proc/$pids_proceso/oom_adj"
done
fi done < $CONFIGURACION
El script es simple, leemos el archivo de configuracion linea por linea
separamos el nombre del proceso del ajuste que le vamos a hacer
guardando cada valor en las variables $proceso y $ajuste. Evaluamos si
la variable $proceso esta vacía, y de ser así seguimos con la próxima
linea, de lo contrario continuamos procesando esa misma linea. Obtenemos
el PID del proceso usando pidof y para cada PID vamos escribir el valor
de $ajuste en su archivo oom_adj dentro de /proc.
Pueden colocar este script en su /etc/rc.local o en un cronjob y
recuerden que si quieren consultar la lista de candidatos y ver como
están sus scrores o saber un poco mas del tema, pueden consultar este
articulo: El OOM Killer y manipulación de candidatos.