Información blog

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

domingo, 3 de mayo de 2015

Los procesos y señales en sistemas Unix

Un proceso es un programa en ejecución que, por lo general, no desaparece hasta que dicho programa finaliza su cometido o es detenido. Cualquier programa que esté en ejecución tiene cómo mínimo un proceso activo

Un proceso puede estar en varios estados:
  • En ejecución en modo usuario.
  • En ejecución en modo núcleo.
  • En espera.
  • Dormido.
  • Listo para ser ejecutado(pero sin ejecutarse aún).
  • Dormido en el swap.
  • Zombie(finalizando).
El mero hecho de de arrancar el sistema operativo ya arranca una gran multitud de procesos sin que uno lo vea a primera vista, los cuales pueden ser consultados mediante el comando ps, el cual explicaré con más detalle después. Cada proceso posee varios datos identificativos que ayudan mucho a una administrador a la hora de realizar cualquier tipo de control y/o gestión. Estos datos serían:
  • El número de proceso, denominado cómo PID (Process ID): Este número es un número único no repetible. El primer proceso es el PID 1, y va aumentando progresivamente a medida que van generándose nuevos procesos. En caso de que un programa fuese ejecutado varias veces, cada ejecución tendría un PID correspondiente.
  • El número de proceso padre, denominado cómo PPID (Parent Process ID): Cuando un proceso inicia otro debido a las circunstancias que sean, a dicho proceso iniciado se le llamada proceso hijo; El PPID del proceso hijo sería el PID del proceso padre y TODOS los procesos poseen un PPID a excepción del primero de todos, aquel que posee el PID 1: el init; el cual tiene un PPID 0, que en realidad no existe.
  • El número de usuario y grupo, denominados cómo UID (User ID) y GID(Group ID): Cada proceso ha sido ejecutado por un usuario (ya sea de forma automática internamente o manualmente por un usuario). Cada usuario se encuentra dentro de un grupo, y ambos datos se ven plasmados dentro del proceso con el fin de determinar qué permisos tiene ese proceso para realizar determinadas acciones. No es lo mismo un proceso generado por el usuario root (el usuario todopoderoso) o un usuario normal.
  • Duración de un proceso: El tiempo pasado desde la iniciación del proceso.
  • Directorio de trabajo activo: El directorio desde el que se ejecuta el proceso
Una captura de ejemplo de la información comentada sería la siguiente:



Controlando los procesos


Si se está ejecutando un proceso en primer plano, es decir, se está ejecutando y se está viendo su ejecución, puede pararse temporalmente mediante la combinación de teclas ctrl + z. El proceso, aún estando detenido, sigue existiendo internamente; Es decir, ha sido pausado, pero no ha sido eliminado, con lo que sigue contando cómo un proceso en sí aún cuando en estos momentos no hace nada. Para reanudar el proceso parado simplemente hay que escribir fg y en caso de haber más de un proceso parado, se reanudaría el último que haya sido parado.


Hay ocasiones en las que se necesite que se reanude un proceso detenido en concreto; Para realizar dicha tarea se necesita la ayuda del comando jobs, el cual muestra todos los procesos detenidos. A modo de prueba he creado un script muy pequeño llamado bucle.sh:

  1. #!/bin/bash
  2. while true
  3. do
  4.         echo "test" 2>&1 >/dev/null
  5. done

Este script simplemente crea un bucle infinito con lo que para la siguiente prueba habría que:

  1. Ejecutar el script.
  2. pararlo con ctrl +z.
  3. ejecutar el script de nuevo.
  4. pararlo de nuevo con ctrl +z.
Si ejecutamos el comando jobs, observaríamos el siguiente resultado:


Al lado de cada proceso se encuentra un número entre corchetes [n]; Para reanudar un proceso en concreto habría que hacer bg número de proceso pausado.


Consultando los procesos:

Tal y cómo he comentado antes, la consulta de un proceso se realizar con el comando ps. El comando en cuestión no necesita parámetros de por sí, pero en caso de que se añadiesen parámetros, mostraría información más detallada. Primero veamos lo que muestra el comando ps "simple":


En este caso aparece muy poca información. Simplemente muestra los procesos generados por el usuario que ha escrito el comando. En cambio si se quiere ver algo más extenso se necesita el parámetro -e, el cual mostraría todos los procesos.


Aquí la lista se extiende considerablemente, ya que muestra TODOS los procesos en curso. Aún así la información mostrada no es tan amplia cómo a uno le gustaría, para obtener más información existen dos parámetros -f y -l. El primero muestra información más detallada, y el segundo muestra información más técnica. Al ser parámetros combinables entre sí, se puede poner por ejemplo ps -efl (el cual he puesto en la captura del principio), aunque por lo general, con el comando ps -ef suele ser suficiente. La siguiente captura sería lo que muestra dicho comando:



Envío de señales a un proceso.

Hasta el momento se ha visto cómo se manipulan o se consultan procesos, ¿pero cómo se detienen? Es decir, se ha visto cómo se pausan, pero no cómo se detienen del todo. El comando que detiene los procesos se denomina kill, y mucha gente piensa que el comando en cuestión solo vale para "matar" procesos, cuando en verdad es un comando que envía señales a los procesos, entre otros, el de finalizar un proceso. Para "matar" el proceso es indispensable conocer su PID (Process ID) y la forma de matar el proceso en cuestión es:

kill -9 PID

Más allá de este comando que sirve para detener el proceso, kill es capaz de hacer más cosas. Cuando se pone kill -9 PID, lo que en verdad se hace es enviarle la señal número 9 al proceso, y dicho número de señal fuerza a un proceso a que se termine inmediatamente sin posibilidad de ignorar dicha orden. Kill puede enviar una gran multitud de señales que se pueden consultar mediante el parámetro -l, pero las más conocidas serían:

Señal 1, SIGHUP: La señal hace que todos los procesos "hijo" se detengan. Eso se hace de forma automática cuando se cierra una consola de shell que está ejecutando desde dicha consola. Al cerrar la consola, el proceso que se está ejecutando también se cerrara. Eso a veces puede suponer un problema, ya que a veces se quiere ejecutar un script que puede llevar bastante tiempo y no queremos que la terminal se quede abierta todo ese tiempo. Por suerte existe una forma de evadir esta señal: Basta con escribir nohup, antes del comando en cuestión y añadiendo un & al final de comando para que se quede en segundo plano. (Ejemplo: sudo nohup ls -R /* &)

Señal 2, SIGINT: Parada de un proceso; Lo equivalente a realizar un ctrl + c a un proceso en primer plano.

Señal 3 SIGQUIT: Lo mismo que SIGINT pero en este caso genera un fichero de depuración.

Señal 9 SIGKILL: Tal y cómo he comentado antes, fuerza a un proceso a que se termine inmediatamente sin posibilidad de ignorar dicha orden.

Señal 15 SIGTERM: Señal que manda kill por defecto, que pide que un proceso se termine con normalidad.


Tratamiento de un señal

Cuando se escribe un programa en bash, se puede hacer que cuando este se ejecuta ignore algunas señales enviadas por kill (o por una combinación de teclas cómo ctrl +c, que también envía una señal). La señal número 9, SIGKILL, no puede ser ignorada, pero hay otras que sí. Para ignorar éstas señales se usa el comando trap, el cual "atrapa" un señal y hace que el proceso no se vea afectado por ésta. Para realizar dicho trap, habría que escribir trap '' número de señal o señales. En caso de introducir más de una señal, éstas tendrían que ir separadas mediante un espacio en blanco. Por ejemplo:

Para "atrapar" una sola señal:
  1. trap '' 2

Para atrapar varias señales:
  1. trap '' 2 3

Por ejemplo, en base al programa de bucle anterior, vamos a hacer que no se a capaz de recibir un ctrl+c o una señal kill -2 número de proceso. Quedaría así:

  1. #!/bin/bash
  2. while true
  3. do
  4.         trap '' 2
  5.         echo "test" 2>&1 >/dev/null
  6. done


Espero que os sea útil.

Saludos

No hay comentarios :

Publicar un comentario