Canalizadores (Pipes) desde el bash

jueves, 8 de mayo de 2008

Como es de común conocimiento y experiencia, a todas las almas que alguna vez han dado con GNU/Linux nos toca acceder a la terminal de texto... nuestro querido bash. Amado por muchos, esta pequeña ventanita (para los agraciados que disponen del X) suele ser la navaja suiza de todas las soluciones. Ya sea para tirar un listado de procesos, acceder a un archivo de configuración o iniciar/detener algún daemon, nuestra vieja terminal de texto es la solución "rústica" a la mayoría de los problemas. En mi caso, las primeras distribuciones de GNU/Linux que tuve instaladas carecían de una interfase gráfica, con lo cual el manejo de los comandos del bash fue siempre un menester.
Ahora bien: es casi mágico y hasta criptográfico intentar entender que son aquellas líneas jeroglíficas que vemos en docenas de guías, tutoriales y how-to's que rondan la red para resolver esos problemas desde la terminal. Para el usuario avanzado no es más que un lenguaje cotidiano, pero para gente nueva suele ser todo un desconcierto. Pero es bueno destacar que la potencia de la terminal (y un poco de tiempo de práctica de por medio) hacen que un comando bien tirado y parametrizado resuelva tareas que manualmente son tediosas y llevan mucho tiempo en realizarse. Por eso, tímidamente intentare explicar que es un canalizador (pipe) de una forma simple (espero que la gente avanzada no se enoje...) con ejemplos puramente prácticos.

Comandos, StdIn y StdOut

Para ejecutar algo desde la consola (de ahora en adelante el término consola y terminal se refieren a lo mismo) basta con tipear el nombre de un comando, posiblemente algun parámetro y darle un golpe a la tecla enter. Este comando procesará alguna tarea, y posiblemente retorne algun resultado. Por ejemplo, el comando "ls" da un listado de los archivos que se encuentren en el directorio actual. Se puede formatear la salida con algún parametro; vamos a ejecutarlo (el signo $ indica el prompt del bash):

$ ls -t -l


Un posible resultado:

total 88
drwxr-xr-x 2 kaleb kaleb 4096 2008-05-08 01:27 Imágenes
drwxr-xr-x 2 kaleb kaleb 4096 2008-05-08 01:21 Escritorio
-rw-r--r-- 1 kaleb kaleb 33476 2008-05-08 01:11 hs_err_pid6619.log
-rw-r--r-- 1 kaleb kaleb 23452 2008-05-06 23:24 template-6354707186372224906.xml
drwxr-xr-x 2 kaleb kaleb 4096 2008-04-29 22:00 Documentos
drwxr-xr-x 2 kaleb kaleb 4096 2008-04-29 22:00 Música
drwxr-xr-x 2 kaleb kaleb 4096 2008-04-29 22:00 Plantillas
drwxr-xr-x 2 kaleb kaleb 4096 2008-04-29 22:00 Público
drwxr-xr-x 2 kaleb kaleb 4096 2008-04-29 22:00 Videos
lrwxrwxrwx 1 kaleb kaleb 26 2008-04-29 18:41 Examples -> /usr/share/example-content

¿Simple, no? Aparte de ser algo bastante simple, hay dos mecanismos que entraron en juego de manera implícita: el StdIn y StdOut, abreviaturas de STAndard INput y STAndard OUTput, respectivamente. El StdIn representa la entrada estandar (por defecto) al comando; en este caso el teclado, dado que fue el periférico que utilizamos para tirar el comando a la terminal. Por otra parte, el StdOut es la salida estandar (por defecto) del comando; en este caso la pantalla, dado que el resultado del comando salió por la ventana donde estamos trabajando (en realidad no es tan así, pero vale como ejemplo). Expresado graficamente, el comando "ls" tiene una entrada y una salida, similar a esto:


El uso de los canalizadores (pipes)

El canalizador "pipe" es un caracter que permite encadenar varios comandos entre si, tomando la salida de uno para aplicarla como entrada de otro. Resulta un poco abstracto en principio, pero graficamente sería algo así:



Para verlo en un ejemplo, tomemos dos comandos al azar: "ps", el cual muestra un listado de procesos que corren en nuestro equipo, y "more", un curioso comando que recibe texto como entrada y realiza una pausa cada vez que la salida por pantalla supera una determinada cantidad de líneas evitando el "scroll" de las mismas. Si el comando "ps" se utiliza con el parámetro "-A" (mostrar todos los procesos), es posible que la salida sea tan grande que no nos alcance la pantalla para ver todo el resultado, así que la salida de este comando se la pasaremos como entrada al "more", para que este muchacho nos "pause" la salida y podamos leer con detenimiento. Para utilizar un pipe, se debe escribir el caracter "|" (sin las comillas :P, se escribe pulsando AltGr+1 en un teclado español) entre el primer y segundo comando, de esta forma:

$ ps -A | more


Si se realiza la prueba en una terminal, veremos felizmente como la salida se va pausando a medida que se "llena" la pantalla de texto. Otro ejemplo sería utilizar el comando "grep", el cual toma como entrada un texto y como parametro una cadena de texto y devuelve todas las lineas de la entrada que contienen la cadena especificada. Para el ejemplo con "ps", podriamos utilizar el combo de ambos para saber si hay en memoria algún proceso relacionado al gnome, por ejemplo, con lo siguiente:

$ ps -A | grep "gnome"


¿Y si la salida fuera muy extensa? ¿Muchos procesos con la palabra "gnome? No hay problema! Canalicemos!

$ ps -A | grep "gnome" | more


¿Ahora la cosa es interesante, no? Otros comandos para probar: cat, glxinfo (en este tutorial se utiliza), grep, more, ps, netstat, etc.

Finalmente invito al lector a probar el uso de pipes y descubirir el potencial que brinda el uso de la consola. ¡Hasta la próxima!

0 comentarios: