02. Shell: Pipes

Publicado por

Un proceso es un programa en ejecución y estos contienen información indispensable para su interacción con el sistema. El encargado de la configuración de los canales para cada proceso es el núcleo del sistema operativo, por lo que el proceso puede que no tenga conocimiento sobre a qué canal se está comunicando.

Existen por lo menos 3 tipos de canales de comunicación para un proceso y cada uno de ellos cuenta con un identificador con el cual se puede referir siempre a ellos.

 STDIN standard input [id = 0] 

 STDOUT standard output [id = 1] 

 STDERR standard error [id = 2] 

En la terminal STDIN lee desde teclado, mientras que STDOUT y STDERR lanzan resultados en la pantalla. La gran mayoría de los comandos que se pueden utilizar en la terminal aceptan su entrada de STDIN, escriben su salida en STDOUT y envían los mensajes de error por STDERR. Esta convención ofrece la ventaja de poder crear/construir pipelines compuestos. Un pipeline es una serie o conjunto de instrucciones o procesos que se envían a través de un pipe. Un pipe es el medio por el cual se manda la información. En el siguiente diagrama se explica el funcionamiento general de un pipeline.

Pipeline
Funcionamiento general de un pipeline.

Los siguientes símbolos son interpretados por la terminal para redirigir las entradas y salidas de los comandos desde o hacia archivos:

< Conecta el canal STDIN a un archivo que ya existe.

> Redirige el canal STDOUT y reemplaza el contenido que ya existe en el archivo.

>> Redirige el canal STDOUT y añade el contenido al archivo.

Acertijo: ¿Qué está ocurriendo en las siguientes terminales?

Abre un par de terminales. En una ejecuta los siguientes comandos:

$ mkfifo /tmp/mipipe
$ cal > /tmp/mipipe

Observa lo que pasa. En la otra terminal ejecuta:

$ cat /tmp/mipipe

¿Puedes deducir qué es lo que pasa?

Respuesta:

Un archivo FIFO First Input First Output (primero en entrar, primero en salir), es un pipe con nombre, este tipo de archivos son usados para comunicar procesos, un proceso escribe en el archivo mientras que otro se encarga de leer, cada proceso se bloquea hasta que el otro actúa. El archivo /tmp/mipipe es un archivo FIFO. Si se ejecuta:

$ file /tmp/mipipe

Se aprecia como aparece el tipo de archivo que es. Ese archivo no contiene nada, es un conducto para comunicar procesos, cuando un proceso escribe en ese archivo, se quedará bloqueado hasta que alguien más (otro proceso) lea lo que se escribe en él. Todo lo que se lee de ese archivo es eliminado del mismo. Si se ejecuta:

$ ls -l /tmp/mipipe

Se notará que el tamaño del archivo es cero. La razón es que el comandocal generó el texto del calendario del mes, y con >esa salida fue redirigida y escrita en el archivo /tmp/mipipe. En la otra terminal, se usó el comando cat para leer lo escrito previamente desde la primera terminal. Cuando se hace al revés pasa lo mismo: si se lee de un pipe que en ese momento no contiene nada, el proceso se quedará bloqueado hasta que alguien más escriba en el pipe.

 Por ejemplo, escribe en una terminal lo siguiente:

$ cat /tmp/mipipe

Y en otra terminal:

$ ls -lth / >/tmp/mipipe

Observa qué es lo que pasa.

Si se ejecutan los siguientes comandos:

$ echo "Este es un mensajito" > /tmp/mismensajitos

Se puede ver que almacena en el archivo /tmp/mismensajitos una sola línea, en caso de que el archivo no exista, lo crea.

$ mail -s "Mensaje" miriam < /tmp/mismensajitos

Este comando envía el contenido de ese archivo al usuario miriam.

Hay más formas de redirigir la salida y el error estándar; por ejemplo el comando >& permite redirigir los canales STDOUT y STDERR al mismo lugar. Si lo que se desea es solamente redirigir alguno de ellos entonces utiliza id>.

Observa lo que pasa al ejecutar el siguiente comando:

$ find / -name core

¿Qué notaste?

El comando find produce una salida en los canales STDOUT y STDERR, sobre todo cuando se ejecuta como usuario sin privilegios. Este comando es un claro ejemplo de por qué es necesario conocer el manejo de los canales, ya que lanza bastantes mensajes de «Error: permiso denegado», resulta tedioso encontrar los casos con éxito que realmente son los que se necesita saber. Para resolver esta situación se puede modificar el comando de la siguiente manera:

$ find / -name core 2> /dev/null

Si se desea conocer solo los archivos donde el usuario tiene permisos de lectura en el directorio raíz y además se quieren guardar en un archivo, entonces se puede utilizar el comando find de la siguiente manera:

$ find / -name core > /tmp/corefiles 2> /dev/null

Para conectar STDOUT de un comando con la STDIN de otro, se usa el símbolo | conocido como pipe.

Acertijo: ¿Qué sucede con el siguiente comando?

$ ps -ef | grep httpd

Respuesta:

El comando ps genera una lista de procesos y el pipe envía la salida al comando grep que busca las líneas que contengan el patrón httpd y las imprime.

También se pueden utilizar los símbolos:

&& Cuando el primer comando tiene éxito, este símbolo permite ejecutar el segundo comando.

|| Cuando el primer comando falla, este símbolo permite ejecutar el segundo comando.

Como se pudo ver en esta nota, es necesario tener conocimiento de los 3 principales canales de comunicación para un proceso, como se observó en algunos ejemplos facilitan el trabajo de cualquier administrador, redirigiendo la información relevante y ocultando la que no se necesita para alguna tarea en específico. Estas primeras notas tienen como finalidad demostrar que conociendo el uso de la terminal, se puede lograr ser un administrador de sistemas GNU/Linux eficiente.

En la siguiente nota continuaré explicando los fundamentos básicos del Shell, el tema principal será uso de variables. Hasta la próxima.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *