Unix provee una serie de mecanismos para poder intercomunicar procesos
Se denomina proceso a un programa en ejecución, como parte de la estrategia de combinar el uso de herramientas simples para poder resolver problemas complejos.
La mayoría de los programas de Unix toman (leen) sus datos de entrada de la llamada “entrada estándar” y envían sus resultados (escriben) a la “salida estándar” (a menudo abreviadas como “stdin
” y “stdout
” respectivamente). Usualmente el sistema está configurado de forma que la entrada estándar es el teclado y la salida estándar la pantalla (recordemos que al teclado y la pantalla se los denomina comunmente “consola”).
Veamos un ejemplo con el comando cat
. Normalmente cat
lee datos de los archivos cuyos nombres se pasan como argumentos en la línea de comandos y envía estos datos directamente a la salida estándar. Luego, al ejecutar la orden:
/home/diego/articulos$ cat historia tesis
se mostrará por pantalla el contenido del archivo historia
seguido por el contenido del archivo tesis
.
Si cat
no recibe nombres de archivos como parámetros, leerá datos de stdin
y los enviará a stdout
. Veamos un ejemplo:
/home/diego/articulos$ cat
Hola !!!
Hola !!!
Adiós.
Adiós.
[Ctrl]+[D]
/home/diego/articulos$
Como puede verse, cada línea que el usuario teclea (en letra itálica) es inmediatamente reenviada al monitor por cat
. Cuando están leyendo datos, los procesos reconocen el fin de la entrada al recibir el carácter EOT
(“end-of-text”, fin de texto). Normalmente es generado con la combinación de teclas [Ctrl]+[D]
.
Veamos otro ejemplo. El comando sort
toma como entrada líneas de texto (al igual que cat
, leerá desde stdin
si no se le proporcionan nombres de archivos en la línea de comandos), y devuelve la salida ordenada por stdout
. Probemos lo siguiente:
/home/diego/articulos$ sort
bananas
manzanas
duraznos
[Ctrl]+[D]
bananas
duraznos
manzanas
/home/diego/articulos$
Ahora, supongamos que queremos que la salida de sort
vaya a un archivo llamado compras
en vez de a la pantalla. El intérprete de comandos nos permite redirigir la salida estándar a un archivo usando el símbolo “>
”. Veamos como funciona:
/home/diego/articulos$ sort > compras
bananas
manzanas
duraznos
[Ctrl]+[D]
/home/diego/articulos$
Como podemos ver, el resultado de sort
no se muestra por pantalla, en su lugar es escrito en el archivo compras
. Veamos ahora su contenido:
/home/diego/articulos$ cat compras
bananas
duraznos
manzanas
/home/diego/articulos$
Supongamos ahora que tenemos nuestra lista desordenada original en el archivo cosas
. Una forma de ordenar la información y escribirla en un archivo podría ser darle a sort
el nombre del archivo a leer en lugar de la entrada estándar y redirigir la salida estándar como acabamos de hacer:
/home/diego/articulos$ sort cosas > compras
/home/diego/articulos$ cat compras
bananas
duraznos
manzanas
/home/diego/articulos$
Hay otra forma de hacer esto. No sólo puede ser redirigida la salida estándar, también puede ser redirigida la entrada estándar usando el símbolo “<
”.
/home/diego/articulos$ sort < cosas
bananas
duraznos
manzanas
/home/diego/articulos$
Las órdenes “sort < cosas
” y “sort cosas
” tienen el mismo efecto, pero esto nos permite ver que el intérprete de comandos es quien maneja las redirecciones. sort
no recibe el nombre del archivo a leer, desde su punto de vista, está leyendo datos de la entrada estándar como si fueran ingresados desde el teclado.
Esto introduce el concepto de “filtro”. Un filtro es un programa que lee datos de la entrada estándar, los procesa de alguna forma y devuelve el resultado por la salida estándar. Usando la redirección, tanto la entrada estándar como la salida estándar pueden ser radirigidas a archivos. sort
es un filtro simple: ordena los datos de entrada y envía el resultado a la salida estándar. cat
es incluso más simple, no hace nada con los datos de entrada, simplemente los envía a la salida tal como los recibe.
El uso de “>
” para redirigir la salida a un archivo es destructivo. En otras palabras, la orden:
/home/diego/articulos$ ls > listado
sobreescribe el contenido del archivo listado
. Si en su lugar, usamos los símbolos “>>
”, la salida será añadida al final del archivo nombrado, en lugar de ser sobrescrito (creándolo, si este no existiera). El comando:
/home/diego/articulos$ ls >> listado
añadirá la salida de ls
al final de listado
.
Ya hemos visto como usar sort
como un filtro, pero estos ejemplos suponen que tenemos los datos en un archivo o que los introducimos manualmente por la entrada estándar.
¿Qué pasa si los datos que queremos ordenar provienen de la salida de otro comando, como ls
? Por ejemplo, si el contenido de nuestro directorio actual fuese:
/home/diego/articulos$ ls
historia
ingles
notas
tesis
/home/diego/articulos$
Usando la opción “-r
” con sort
ordenaremos los datos en orden inverso. Una forma de hacer esto sería:
/home/diego/articulos$ ls > listado
/home/diego/articulos$ sort -r listado
tesis
notas
ingles
historia
/home/diego/articulos$
Aquí, escribimos la salida de ls
en un archivo y luego ejecutamos “sort -r
” sobre él. Pero de esta forma hemos creado un archivo solamente para que los datos generados por ls
luego puedan ser leídos por sort
. No parece tener demasiado sentido hacer esto.
La solución a este problema es usar los “pipes” (o “tuberías”). Los pipes son una poderosa herramienta provista por el sistema para conectar dos procesos, de manera que la stdout
del primero es enviada directamente a la stdin
del segundo (esto puede generalizarse para formar una cadena de procesos). Para crear un pipe se usa el símbolo “|
”. En nuestro ejemplo, queremos conectar la salida de ls
con la entrada de sort
:
/home/diego/articulos$ ls | sort -r
tesis
notas
ingles
historia
/home/diego/articulos$
Esta forma es más corta, más eficiente y hasta más fácil de escribir.
Veamos otro ejemplo útil. Al usar el comando:
/home/diego/articulos$ ls /usr/bin
se mostrará una lista de archivos demasiado extensa, parte de la cual pasará rápidamente por la pantalla ante nuestros ojos, sin que podamos leerla. En lugar de esto, usemos less
para detener el listado cada vez que se complete la pantalla:
Recordemos que para salir deless
hay que presionar[Q]
.
/home/diego/articulos$ ls /usr/bin | less
Ahora podemos ir avanzando o retrocediendo línea por línea o pantalla por pantalla, cómodamente.
Como dijimos anteriormente, podemos “entubar” más de dos procesos a la vez. head
es un filtro que muestra las primeras líneas de la entrada. Si queremos ver el último archivo del directorio actual en orden alfabético, usaremos:
/home/diego/articulos$ ls | sort -r | head -1
tesis
/home/diego/articulos$
Donde “head -1
” muestra la primera línea de la entrada que recibe (en este caso, el flujo de datos ordenados inversamente, proveniente de “sort -r
”, que es el listado que éste recibió de “ls
”).