Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

martes, 22 de noviembre de 2016

Procesos zombie en Linux; qué son y cómo "matarlos"

Cualquiera que haya tratado con terminales Linux con cierta regularidad, se ha encontrado alguna vez en su vida con procesos "especiales" que no importa lo que hagan con ellos que no son capaz de "morir"; son procesos que están ahí "muertos" y que no consumen memoria RAM ni CPU, pero que el sistema todavía reconoce como existentes y que no importa lo que se haga con ellos que se resisten a desaparecer... Dichos procesos son llamados procesos zombie y si bien no tienen que causar problemas de rendimiento, su sola aparición hace que pensemos que dicho proceso está activo y pueden dar lugar a confusiones; es por eso que lo ideal es que ninguno de dichos zombies pululen por nuestro sistema operativo, por muy inofensivos que éstos sean.

Zombie_proceso

Los procesos zombie siempre son procesos dependientes de un proceso "padre" que no ha sido capaz de finalizar correctamente sus procesos "hijo", haciendo que estos sigan existiendo en el sistema aún cuando no consuman recursos... Este fenómeno es fácilmente comprobable en cualquier consola de Linux; pero antes, para asegurarnos que efectivamente va a existir un proceso zombie, crearemos varios "zombies" nosotros mismos a modo de prueba de concepto. Para ello tendríamos que crear un pequeño programa escrito en c llamado, por ejemplo, zombiegen.c cuyo contenido sería:

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. int main() {
  4.         pid_t pid;
  5.         int i=0;
  6.         while (1)  {
  7.                 pid = fork();
  8.                 if (pid > 0) {
  9.                         // Proceso padre
  10.                         printf("Padre %d\n",+ 1);
  11.                         sleep(1);
  12.                 } else {
  13.                         // Proceso hijo
  14.                         printf("Zombie %d\n",+ 1);
  15.                         exit(0);
  16.                 }
  17.         i++;
  18.         }
  19.         return 0;
  20. }

Después habría que compilar el programa mediante gcc tal que así:

gcc zombie.c -o zombie

Con esto haríamos que se creasen constantemente procesos zombie hasta que decidiésemos parar el programa. ¿Cómo podemos saber si el sistema tiene algún proceso zombie actualmente? Mediante el siguiente comando:

ps aux |grep defunct |grep -v grep

Al ser un bucle que crea procesos zombie constantemente podemos encontrarnos con algo como esto:

Lista_procesos_zombie

Si os fijáis bien en la línea en cuestión, veréis que una de sus columnas tiene una única letra; Z. Dicha Z significaría que dicho proceso tiene la etiqueta zombie, y que si bien no está operativo, dicho proceso en sí sigue existiendo en el sistema. Además veríamos también que todos los procesos finalizan con <defunct> que significaría que el proceso está parado, pero que todavía existe.

Ahora bien, ¿Cómo nos libramos de los zombies?  Tan simple como matando al padre de todos éstos, con lo que lo primero que tendríamos que ver es... ¿Quien es el padre de todos estos? Si conociésemos el PID (process ID) del padre, podríamos "matar" este para así automáticamente acabar con sus hijos... Esto puede parecer complejo pero es tan sencillo como hacer:

ps -eo pid,ppid,command | grep defunct |grep -v grep

Con esto listaríamos el numero de proceso de cada zombie, seguido del número de proceso de aquel que ha "creado" el zombie, junto con el comando.

En mi caso en particular me aparecería esto:

Padre_zombies

Si nos fijamos bien, veremos que todos comparten el mismo PPID (Parent Process ID) ... Es decir que todos dependen de dicho proceso para seguir existiendo así que únicamente tendríamos que acabar con éste proceso mediante un simple kill. En este caso tendríamos que detener el proceso con PID 4636.

kill -9 4636

Tras lo cual únicamente tendríamos que volver a ejecutar nuestro anterior comando para ver que efectivamente hemos acabado con todos ellos.

ps_sin_zombies

Como veis, el encontrar y acabar con estos procesos es muy sencillo; solamente hay que buscar procesos "defunct" y acabar con el proceso que los está generando... Obviamente para acabar con la raíz del problema habría que ver qué error de programación hay en el proceso padre, pero esto puede servirnos como una solución temporal para limpiar los procesos zombie hasta encontrar el verdadero origen de esta situación.

Espero que os haya resultado útil.

Saludos.

No hay comentarios :

Publicar un comentario