arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

Procesos en Unix

Eduardo Ismael Garcia

Full Stack Developer at Código Facilito.

av_timer 7 Min. de lectura

remove_red_eye 17373 visitas

calendar_today 26 Julio 2021

Hoy toca el turno de hablar sobre procesos en Unix. Un tema super interesante si te apasiona todo lo que relacionado con administrar servidores o te encuentras en el área de DevOps.

Para este post estaré trabajando con el sistema operativo Ubuntu, sin embargo toda la explicación aquí mencionada, así como los comandos ejecutados, son aplicables para cualquier sistema operativo basado un Unix, llámese Ubuntu, Fedora, Red Hat, MacOs, Debian etc.. 🤓

Así que, sin más introducción, comencemos con esta entrega.

procesos 🚀

Comencemos con la pregunta obligada ¿Qué es un proceso? Verás, en términos simples un proceso no es más que un entorno especial creado para la ejecución de un programa.

Por ejemplo, cuando ejecutamos un programa (ya sea con doble clic o directamente en terminal) un nuevo proceso es creado en nuestro sistema, y dentro de él (dentro del proceso) se encontrará todo lo necesario para que el programa funcione correctamente, me refiero a variables, rutinas, threads, funciones, ciclos etc... todo lo que los desarolladores hayan definido al momento de crear dicho programa. 😎

Por ejemplo, cuando ejecutamos el comando ls, para listar todo el contenido de un directorio , estaremos creando un nuevo proceso, ya que estaremos ejecutando un programa.

Una vez el programa finaliza el proceso lo hará de igual manera. 😃

Con esto en mente, podemos concluir que un proceso es la instancia de un programa. Y como instancia, podemos crear la n cantidad que deseemos. Podemos confirmar esto abriendo un par de veces nuestro navegador. Una nueva ventan, un nuevo proceso.🤠

Ahora, todos los procesos poseen 4 atributos que nos permitirán gestionarlos. Me refiero a:

  • PID (Process ID): Identificador único para cada uno de los procesos. Este identificador se conforma de hasta 5 números enteros. Si bien el ID de un proceso puede repetir en un cierto periodo de tiempo (Ya que los procesos finalizan y el sistema eventualmente re utilizará algún ID), nunca pueden existir 2 procesos con el mismo ID en el mismo periodo de tiempo.

  • PPID (Parent Process ID): En Unix, cada proceso es creado, asu vez, por otro proceso, por lo tanto se necesita una referencia al proceso padre. Si lo vemos desde una perspectiva de base de datos, podemos decir que una proceso padre puede poseer múltiples procesos hijos y un proceso hijo pertenece a un proceso padre.

  • TTY: Terminal a la cual se encuentra asociada un proceso. No todos los procesos pueden ser creados desde una terminal, por lo tanto podrán existir procesos sin este atributo.

  • UID (User ID): Usuario al que pertenece el proceso. Usuario propietario del proceso.

Para listar todos los procesos activos en nuestro sistema, ejecutaremos el comando ps.

$ ps
  PID TTY          TIME CMD
21918 pts/0    00:00:00 bash
22166 pts/0    00:00:00 ps

En mi caso encontramos 2 procesos: El proceso Bash, que sería la terminal, donde me encuentro ejecutando los comandos, y ps, el proceso que me permitió listar los procesos.

Si queremos conocer el PPID de cada proceso usamos la bandera -f.

 ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
eduardo    260   259  0 20:44 pts/0    00:00:00 /bin/bash --login
eduardo    531   260  0 20:49 pts/0    00:00:00 nano
eduardo    534   260  0 21:00 pts/0    00:00:00 ps -f

Antes de continuar quisiera hacer un pequeño paréntesis, ya que quizás te estés preguntando ¿si todos los procesos son creados por otros procesos, esto quiere decir que existe un proceso principal? ¿Un padre de padres? Y la respuesta es sí. Y el proceso tiene por nombre Init process.

Este es el primer proceso que se ejecuta cuando el sistema inicia y posee por PID 1. A partir de él todos los demás procesos podrán crearse.

Si hacemos un árbol genealógico de todos los procesos en el sistema, sin duda terminaremos llegando al Init process. 🌳

Bien, continuemos con los comandos.

Si queremos conocer más información acerca de los procesos, un parámetro muy popular es aux.

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.5  0.0   1208   564 ?        Sl   12:20   1:21 /init
root         7  0.0  0.0    892    80 ?        S    12:20   0:01 /init
eduardo   2968  0.0  0.4 1256744 58664 pts/5   SLl+ 13:07   0:01 mongo
eduardo  21918  0.0  0.0  26364  8452 pts/0    Ss   15:49   0:00 /bin/bash --login
eduardo  22190  0.0  0.0  37800  3364 pts/0    R+   16:22   0:00 ps aux

El primer proceso es init con su PID 1. 👀

Este comando despliega una tabla mucho más detalla (e inclusive extensa) del los procesos en el sistema. Con esta tabla podemos conocer la siguiente información.

  • USER: usuario propietario del proceso.
  • PID: Identifucadoer del proceso.
  • %CPU: Porcentaje de tiempo que el proceso estuvo en ejecución desde que se inició.
  • %MEM: Porcentaje de memoria RAM utilizada.
  • VSZ: memoria virtual del proceso medida en KiB
  • RSS: Cantidad de memoria utilizada por el proceso (Expresada en Kilobytes).
  • TT: terminal que controla el proceso (tty)
  • STAT: Código de estado del proceso.
  • STARTED: Fecha de inicio del proceso.
  • TIME: tiempo de CPU utilizado.
  • COMMAND: comando con todos sus argumentos.

De igual forma, es importante detallar cada uno de los posibles estados para los procesos, que serían los siguientes (Esto para la columna STAT):

  • R: En ejecución o listo para ser ejecutado.
  • S: Suspendido. El proceso se encuentra a la espera de ser reanudado.
  • D: El proceso se encuentra a la espera de I/O. T: Detenido.
  • Z: Zombificado, un proceso difunto que aun no ha sido reclamado por el proceso padre.

Toda esta información, por supuesto, la podemos conocer en el manual del comando ps (man ps).

Monitorear procesos

Un comando que en lo particular me gusta mucho es top. Este comando nos permite visualizar, en tiempo real, el top de los procesos del sistema, actualizando la información de forma constante. Perfecto para todas aquellas ocasiones donde queremos conocer qué proceso esta causando un cuello de botella en nuestro servidor. 😵

 $ top
 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1 root      20   0    1208    564    520 S   0.0  0.0   1:21.33 init 
 7 root      20   0     892     80     20 S   0.0  0.0   0:01.62 init
 2968 eduardo   20   0 1256744  58664  33656 S   0.0  0.5   0:01.23 mongo 
 4684 eduardo   20   0   33672   8720   3040 S   0.0  0.1   0:04.40 tmux: server 
 4685 eduardo   20   0   26384   8516   3548 S   0.0  0.1   0:00.21 bash
 4899 eduardo   20   0   26404   8348   3376 S   0.0  0.1   0:00.04 bash
 5113 eduardo   20   0   26404   8400   3428 S   0.0  0.1   0:00.05 bash
 5335 eduardo   20   0 1638868 150048  53448 S   0.0  1.2   1:13.90 mongod
 5375 eduardo   20   0 1253672  52340  33048 S   0.0  0.4   0:00.80 mongo

Para salir, y regresar a la terminal, basta presionar la tecla q.

Control de procesos.

Listo, ya sabemos qué son los procesos y ya conocemos algunos atributos que nos permiten administrarlos, así que toca el turno de aprender a crearlos, y para ello tenemos 2 opciones:

  • Foreground Processes
  • Background Processes

Expliquemos cada uno de ellos. Comencemos con Foreground Processes. Por default cada proceso que creemos en terminal se ejecuta de esta manera, en primer plano, pudiendo así ingresar datos vía teclado y esperar una posible salida en pantalla.

Un ejemplo de Foreground Processes ocurre cuando ejecutamos nuestros scripts en terminal, pudiendo interactuar con el programa.

 $ ruby saludar.rb
 Ingresa tu nombre: Eduardo Ismael
 Hola Eduardo Ismael, estamos en un proceso en primer plano.

Algo muy común ¿no lo crees? 😄 El único problema de ejecutar procesos en primer plano, es que mientras el programa se encuentre en ejecución, no podremos ejecutar ningún otro tipo de comando, debemos esperar a que el programa finalice. 😖

Ahora, para ejecutar procesos en segundo plano (Background Processes) basta con colocar el carácter ampersand (&) al final del comando.

La principal ventaja de ejecutar los procesos de esta forma, es la posibilidad de ejecutar otros comandos en terminal, independientemente si el programa en background ha finalizado o no.

Veamos un ejemplo. Ejecutemos en segundo plano el editor de texto nano.

nano &
[1]  529

Siempre que ejecutemos un proceso en background, inmediatamente se nos mostrará su PID en pantalla y retomaremos el control de la terminal. En mi caso se me indica que un nuevo job acaba de ser lanzado con el PID 22245.

Si listamos nuevamente, encontraremos nuestro proceso en background.

$ ps
  PID TTY          TIME CMD
  260 pts/0    00:00:00 bash
  529 pts/0    00:00:00 nano
  530 pts/0    00:00:00 ps

El inconveniente de mandar los procesos a un segundo plano, es la nula interacción que tendremos con el programa, lo cual en ciertos escenarios (principalmente en tareas automatizadas) no debiese ser un gran problema.

Regreso a primer plano.

Si queremos regresar el proceso a primer plano, haremos uso del programa fg.

Primero listamos todos los Jobs lanzados en segundo plano desde la terminal.

 $ jobs
[1]-  Stopped                 nano

Y después, simplemente seleccionamos el proceso que queremos que se ejecute ahora en primer plano.

 fg %1

Finalizar procesos.

Si queremos finalizar un proceso, podemos hacerlo de 2 formas diferentes. Si el proceso se encuentra en primer plano, basta con presionar control + c.

Por otro lado, si el proceso se encuentra en background haremos uso del programa kill. Basta con colocar la bandera -9 seguido por el PID del proceso.

kill -9 <PID>

Si te preguntas el por qué del -9, te lo explicaremos más adelante. 🤗

Deamons

Antes de continuar con los signals, debemos hablar sobre los Deamons, un tipo especial de proceso que se ejecuta segundo plano. 🎃

Los demonios son procesos que se ejecutan de forma automática en segundo plano y se caracterizan por no tener ninguna interacción con los usuarios. No poseen interfaz gráfica o textual y se encuentran en ejecución por siempre, como un servicio. Prácticamente pasan desapercibidos por la mayoría de nosotros.

Si intentamos matar aun procesos demonio, déjame decirte que esto no será posible, ya que regresarán a la vida. Claro, todo depende de las configuraciones y políticas del sistema. 🧟

SIGNALS.

Ya para finalizar el post hablemos sobre los signals. Los signals son la forma en la cual podemos comunicar procesos entre sí, mediante señales.

Para conocer que signals disponibles en nuestro sistema ejecutamos el siguiente comando.

$ kill -l

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

La señal que utilizamos anteriormente fue la número 9, una señal para finalizar un proceso.

Como podemos observar todos los signal posee un nombre, con sus primeros 3 caracteres SIG.

Sin bien existen una gran cantidad de signals disponibles, creo, desde mi poca o mucha experiencia administrando servidores, que el 99% de las veces haremos uso del signal SIGKILL para finalizar un proceso en segundo plano.

Si te interesa conocer más acerca de cada uno de lo signals, te comparto el un link que sin duda te será de mucha útilidad. ⚡