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.



Comments

comments powered by Disqus