Pipes en linux
Si eres usuario Linux/Unix es probablemente hayas oído hablar acerca de los pipes, inclusive, que los hayas utilizado sin darte cuenta.
En este post explicaremos, qué son, cómo funcionan y por que es importante que los conozcamos.
El pipe es la barra en vertical |
Entrada y salida de datos Unix
Antes de entrar de lleno con los Pipes, me gustaría mencionar que en Linux/Unix cada nuevo proceso generado, es decir, cada nueva aplicación ejecutada, es inicializada con tres canales de datos, canales conocidos cómo streams.
- Standar Input
- Standar Output
- Standar Error
El Standard input, es la entrada de datos de nuestro programa, los datos serán ingresados durante la ejecución del mismo y se harán mediante teclado.
Algo que debemos dejar en claro es que los argumentos que nosotros coloquemos al momento de ejecutar un programa, no corresponden al standar input.
go run main.go argumento1 argumento2
En este ejemplo, tanto argumento1 cómo argumento2 son valores que no se encuentran en el Standard input.
En el Standard output el programa colocará todos los mensajes que necesita que el usuario visualice. Estos mensajes no deben de considerarse advertencias o errores.
En el Standard error el programa colocará todos los mensajes de advertencias y errores que puedan sucitarse durante la ejecución del mismo.
Tanto el Standard output cómo Standard error mostrarán en pantalla los mensajes, sin embargo, no existe un color, una fuente o alguna característica entre estos dos streams cómo para que un usuario pueda conocer en primera instancia a que canal pertenece cada mensaje.
Conceptos bastante fáciles de comprender, quizás, un poco difíciles de implementar. Sin embargo, si hacemos el máximo esfuerzo en colocar los mensajes en su canal correcto, creeme, estaremos creando aplicaciones de alta calidad.
Trabajar con los inputs y outputs
Ahora, veamos un par de ejemplos de cómo podemos sacarle provecho a los stream. Para este post trabajaremos con un par de programas los cuales podemos utilizar los usuarios de sistemas operativos Unix/Linux.
El programa history nos permite conocer los últimos comandos ejecutados en nuestra sesión. Basta con ejecutar history en nuestra terminal (Te invito a hacerlo, prometo que no pasará nada malo).
history
Una vez ejecutado el programa estaremos visualizando en pantalla un listado de comandos. Todos el texto que visualizamos (los comandos) se encuentran en el stream de el Standard output.
Si nosotros así lo deseamos, podemos almacenar la salida de cualquier programa, en un archivo de texto plano. Basta con utilizar el signo mayor que, seguido del nombre del archivo (Podemos colocar un ruta en especial así así lo deseamos, así como una extensión al archivo ).
history > ~/output/ultimos_comandos.txt
Comunmente la extención para estos archivos será .tmp
Con el signo mayor que, crearemos el archivo si este no existe, y colocaremos el output del programa allí; En caso el archivo exista, y esté almacene algún tipo de contenido, el contenido será reemplazado por el output del programa. Si nosotros no queremos perder la contenido que posee un archivo, lo que podemos hacer es utilizar el doble signo igual.
history >> ~/output/ultimos_comandos.txt
Esto hará que el output sea agregado al final del archivo, sin reemplazar nada.
Una vez con el output almacenado, nosotros podemos trabajar con él mediante otros programas. Por ejemplo, utilicemos el programa grep para conocer qué archivos o folders se han eliminado recientemente.
grep < ~/output/ultimos_comandos.txt "rm"
Al ejecutar esta sentencia estaremos visualizando los últimos comandos los cuales cuentan con rm en su ejecución.
Con el signo menor que, estamos colocando todo el contenido del archivo cómo Standar Input del programa grep. A partir de estos inputs, el programa grep ya puede buscar rm.
Pipes
Bien, ya sabemos que nuestro programa tiene tres tipos de canales, pero, ¿Qué papel juega el pipe en todo esto?.
Existe programas para muchas cosas, sin embargo, no existe un programa en la actualidad que lo haga todo. Si queremos hacer tareas complejas, es probable que tengamos que apoyarnos de más de un programa.
Regresemos al ejemplo anterior, donde nosotros necesitábamos conocer los archivos o folders eliminados recientemente. Para solucionar la problemática tuvimos que ejecutar el programa history y su output almacenarlo en un archivo, el cual nos sirvió cómo input del programa grep. Obtuvimos el resultado deseado, pero, somos programadores, siempre podemos mejorarlo. Es Aquí donde entran los pipes a salvar el día, y hacer nuestro trabajo cómo administrador de servidores más sencillo.
Ejecutemos la siguiente sentencia.
history | grep "rm"
Si, obtenemos el mismo resultado, solo que ahora con una sentencia mucho más corta, legible y sin tener que crear nuevos archivos en nuestro disco duro, bastante cool.
El pipe nos permitirá encadenar la ejecución de programas, pasando el output de uno cómo el input de otro. En este caso estamos colocando el output de history cómo el input de grep. El orden en el que se ejecutarán los programas es de izquierda a derecha y desa misma manera es cómo se estarán pasados los outputs.
y Así cómo encadenamos la ejecución de dos programas podemos hacerlo con tres, cinco, o con la n cantidad que necesitemos. Nosotros no estamos limitados únicamente a encadenar programas Unix/Linux, también podemos encadenar nuestros propios programas, no importa si están escritos en Java, Python, PHP etc... claro, siempre y cuando hayamos tomado en cuentos los streams en su codificación.
Conclusión
EL conocimiento y uso de pipes es algo indispensable para cualquier usuario Unix/Linux. Con este simple operador nosotros podemos resolver tareas sumamente complejas a través de programas "sencillos", sin la necesidad de tener que instalar nuevos programas y claro aprovechando al máximo nuestro procesador.