Semana 9 -_standard_io_and_pipes

30
Standard IO and Pipe 1 Capítulo 1 Entrada estándar y salida estándar Conceptos clave Los programas basados en la terminal tienden a leer información desde una fuente y a escribir la información en un destino. La fuente desde donde se leen los programas se conoce como una entrada estándar (stdin, del inglés standard in) y suele estar conectada al teclado de la terminal. El destino al que los programas escriben se conoce como una salida estándar (stdout, del inglés standard out) y suele estar conectada a la pantalla de la terminal. Cuando se utiliza la shell bash, la stdout puede redirigirse mediante > o >> y la stdin puede redirigirse mediante <. Muchos comandos de Linux leen la entrada desde el teclado y muestran la salida en la terminal. En este cuaderno, aprenderá cómo se puede redirigir desde dónde se lee la entrada y a dónde va la salida. La salida de un comando puede utilizarse como la entrada para otro comando, permitiendo que los comandos sencillos se utilicen conjuntamente para realizar tareas más complejas. Tres tipos de programas En Linux (y Unix), los programas se pueden agrupar en los siguientes tres diseños. Programas gráficos Los programas gráficos están diseñados para ejecutarse en el entorno gráfico X. Esperan que el usuario esté utilizando el ratón y los componentes gráficos comunes tales como menús emergentes y botones para la entrada de parte del usuario. El navegador de red mozilla es un ejemplo de un programa gráfico. Programas de pantalla Los programas de pantalla esperan utilizar una consola de texto. Hacen uso de toda la pantalla y manejan la presentación del texto y rediseño de pantalla en formas sofisticadas. No necesitan ratón y son apropiados para terminales y consolas virtuales. Los editores de texto vi, nano y el navegador de red links son ejemplos de este tipo de programas. Programas de terminal Los programas de terminal reunen entradas y salidas de pantalla en un flujo, raras veces rediseña la pantalla como si escribiese directamente a la impresora lo cual no permite al cursor devolver la página. Debido a su sencillez, los programas basados en la terminal suelen llamarse simplemente comandos. Ejemplos de este tipo de programas son ls, grep y useradd.

Transcript of Semana 9 -_standard_io_and_pipes

Page 1: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

1

Capítulo 1 Entrada estándar y salida estándar

Conceptos clave

• Los programas basados en la terminal tienden a leer información desde una fuente y a escribir la información en un destino.

• La fuente desde donde se leen los programas se conoce como una entrada estándar (stdin, del inglés standard in) y suele estar conectada al teclado de la terminal.

• El destino al que los programas escriben se conoce como una salida estándar (stdout, del inglés standard out) y suele estar conectada a la pantalla de la terminal.

• Cuando se utiliza la shell bash, la stdout puede redirigirse mediante > o >> y la stdin puede redirigirse mediante <.

Muchos comandos de Linux leen la entrada desde el teclado y muestran la salida en la terminal. En este cuaderno, aprenderá cómo se puede redirigir desde dónde se lee la entrada y a dónde va la salida. La salida de un comando puede utilizarse como la entrada para otro comando, permitiendo que los comandos sencillos se utilicen conjuntamente para realizar tareas más complejas.

Tres tipos de programas

En Linux (y Unix), los programas se pueden agrupar en los siguientes tres diseños.

Programas gráficos

Los programas gráficos están diseñados para ejecutarse en el entorno gráfico X. Esperan que el usuario esté utilizando el ratón y los componentes gráficos comunes tales como menús emergentes y botones para la entrada de parte del usuario. El navegador de red mozilla es un ejemplo de un programa gráfico.

Programas de pantalla

Los programas de pantalla esperan utilizar una consola de texto. Hacen uso de toda la pantalla y manejan la presentación del texto y rediseño de pantalla en formas sofisticadas. No necesitan ratón y son apropiados para terminales y consolas virtuales. Los editores de texto vi, nano y el navegador de red links son ejemplos de este tipo de programas.

Programas de terminal

Los programas de terminal reunen entradas y salidas de pantalla en un flujo, raras veces rediseña la pantalla como si escribiese directamente a la impresora lo cual no permite al cursor devolver la página. Debido a su sencillez, los programas basados en la terminal suelen llamarse simplemente comandos. Ejemplos de este tipo de programas son ls, grep y useradd.

Page 2: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

2

Este capítulo se enfoca en este último tipo de programa. No permita que la simplicidad de estos comandos que reciben entradas y salidas lo engañen. Usted hallará que muchos de estos comandos son muy sofisticados y le permiten utilizar la interfaz de la línea de comandos de manera eficaz.

Entrada estándar (stdin) y salida estándar (stdout)

Los programas de terminal suelen leer información como un flujo desde una sola fuente tal como el teclado de una terminal. Igualmente, por lo general, escriben información como un flujo a un solo destino como por ejemplo una pantalla. En Linux (y Unix), el flujo de entrada se conoce como entrada estándar (suele abreviarse stdin) y el flujo de salida se conoce como salida estándar (o en forma abreviada stdout).

Por lo general, stdin y stdout están conectadas a la terminal que ejecuta el comando. Algunas veces para automatizar los comandos más repetidos, grabar la salida de un comando o incluirlo más tarde en un informe o correo se considera conveniente redirigir stdin desde stdout hacia los archivos.

Redirección de stdout

Escritura de una salida a un archivo

Cuando un programa de terminal genera salida, usualmente suele escribir esa salida a su flujo de stdout, sin saber qué está conectado al final receptor de ese flujo. Con frecuencia el flujo de stdout está conectado a la terminal que inició el proceso para que la salida sea escrita a la pantalla de la terminal. La shell bash usa > para redirigir un flujo de stdout de proceso a un archivo.

Por ejemplo, suponga que la máquina que elvis está utilizando se vuelve muy lenta y no responde. Con el fin de diagnosticar el problema, elvis desearía examinar los procesos que están ejecutándose. Sin embargo, dado que la máquina es tan lenta, recoge información ahora pero la analiza más tarde. Elvis puede redirigir la salida del comando ps aux al archivo sluggish.txt y regresar para examinar el archivo cuando la máquina esté respondiendo mejor.

[elvis@station elvis]$ ps aux > sluggish.txt [elvis@station elvis]$

Observe que no se ve ninguna salida en la terminal. El comando ps escribe en stdout, como siempre lo hace, pero stdout es redirigida por la shell bash al archivo sluggish.txt . El usuario elvis puede examinar el archivo más tarde en un momento más apropiado.

[elvis@station elvis]$ head sluggish.txt USER PID %CPU %MEM VSZ RSS TTY STAT S TART TIME COMMAND root 1 0.0 0.0 1380 76 ? S J un02 0:04 init [ root 2 0.0 0.0 0 0 ? SW J un02 0:00 [keventd] root 3 0.0 0.0 0 0 ? SW J un02 0:00 [kapmd]

Page 3: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

3

root 4 0.0 0.0 0 0 ? SWN J un02 0:00 [ksoftirqd_CPU0] root 9 0.0 0.0 0 0 ? SW J un02 0:00 [bdflush] root 5 0.0 0.0 0 0 ? SW J un02 0:00 [kswapd] root 6 0.0 0.0 0 0 ? SW J un02 0:00 [kscand/DMA] root 7 0.0 0.0 0 0 ? SW J un02 0:37 [kscand/Normal] root 8 0.0 0.0 0 0 ? SW J un02 0:00 [kscand/HighMem]

Agregando una salida a un archivo

Si el archivo sluggish.txt ya existió, su contenido original se perdería. Esto suele conocerse como sobrescribir un archivo. Para agregar una salida de un comando a un archivo, en lugar de sobrescribirlo, bash usa >>.

Suponga que elvis quiso registrar un marcador de tiempo de cuando se estaba presentando la conducta lenta, como también una lista de los procesos actuales en ejecución. Primero podría crear (o sobrescribir ) el archivo con la salida del comandodate mediante > y luego agregarlo a la salida del comando ps aux mediante >>.

[elvis@station elvis]$ date > sluggish.txt [elvis@station elvis]$ ps aux >> sluggish.txt [elvis@station elvis]$ head sluggish.txt Tue Jun 3 16:57:23 EDT 2003 USER PID %CPU %MEM VSZ RSS TTY STAT S TART TIME COMMAND root 1 0.0 0.0 1380 76 ? S J un02 0:04 init [ root 2 0.0 0.0 0 0 ? SW J un02 0:00 [keventd] root 3 0.0 0.0 0 0 ? SW J un02 0:00 [kapmd] root 4 0.0 0.0 0 0 ? SWN J un02 0:00 [ksoftirqd_CPU0] root 9 0.0 0.0 0 0 ? SW J un02 0:00 [bdflush] root 5 0.0 0.0 0 0 ? SW J un02 0:00 [kswapd] root 6 0.0 0.0 0 0 ? SW J un02 0:00 [kscand/DMA] root 7 0.0 0.0 0 0 ? SW J un02 0:37 [kscand/Normal]

Redirección de stdin

Así como bash usa > para lograr que los comandos entreguen su salida en alguna otra parte que no sea la pantalla, bash usa < para hacer que lean entradas desde alguna parte diferente al teclado. El usuario elvis todavía está tratando de entender el porqué su máquina está lenta. Habla con su administrador local de sistemas , quien piensa que examinar la lista de los procesos en ejecución es una buena idea y le pide a elvis que le envíe una copia por correo.

Page 4: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

4

Por medio del comando mail basado en la terminal, elvis escribe "manualmente" desde el teclado un correo electrónico al administrador. El comando mail espera un destinatario como argumento y la línea de asunto se puede especificar con la opción -s. El cuerpo del texto del correo electronico se introduce luego desde el teclado. El final del texto se señala con un punto aparte en una línea.

[elvis@station elvis]$ mail -s "Computer is sluggi sh" [email protected] Hey sysadmin... I'm sending a list of processes that were running w hen the computer was running in a separate email. Thanks! --elvis . Cc:

Para su mensaje de seguimiento, elvis puede fácilmente enviar la salida del comando ps grabada en el archivo sluggish.txt . Sólo redirige el flujo de stdin del comando mail para leerlo desde el archivo.

[elvis@station elvis]$ mail -s "ps output" sysadmin @example.com < sluggish.txt

El administrador de sistemas recibirá un correo electrónico de elvis con "salida ps" como su línea de asunto y el contenido del archivo sluggish.txt como el cuerpo del texto.

En el primer caso, la stdin del proceso mail estaba conectada a la terminal y el cuerpo del mensaje lo proporcionó el teclado. En el segundo caso, bash arregló para que la stdin del proceso mail se conectara al archivo sluggish.txt y el cuerpo del mensaje fuera provisto por su contenido. El comando mail no cambia su conducta básica. Este lee el cuerpo del mensaje desde stdin. [1]

Dentro del cofre: archivos abiertos y descriptores de archivos

Archivos abiertos y descriptores de archivos

Para apreciar plenamente cómo administrar procesos de entrada y salida estándar y archivos debemos introducir el concepto de un descriptor de archivos. Con el fin de leer o escribir información en un archivo un proceso debe abrir el archivo. Los procesos de Linux (y Unix) mantienen el registro de los archivos que están abiertos mediante la asignación de un número entero a cada uno. El número entero se conoce como un descriptor de archivos.

El kernel de Linux ofrece una forma fácil de examinar los archivos abiertos y los descriptores de archivos de un proceso en ejecución mediante el sistema de archivos

Page 5: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

5

/proc . Cada proceso tiene un subdirectorio asociado bajo /proc llamado como su PID (ID del proceso). El subdirectorio del proceso a su vez tiene un subdirectorio llamado fd (del inglésfile descriptor). Dentro del subdirectorio /proc/ pid/fd , existe un enlace simbólico para cada archivo abierto por el proceso. El nombre del enlace simbólico es el número entero del descriptor de archivo abierto y el enlace simbólico apunta al archivo mismo.

A continuación, elvis ejecuta con cat el archivo /etc/termcap y luego casi de inmediato suspende el programa con CONTROL -Z.

[elvis@station elvis]$ cat /etc/termcap [1]+ Stopped cat /etc/termcap

Usando el comando ps busca el PID del proceso, luego elvis examina el directorio del proceso /proc/ pid/fd .

[elvis@station elvis]$ ps PID TTY TIME CMD 1368 pts/1 00:00:00 bash 1910 pts/1 00:00:00 cat 1911 pts/1 00:00:00 ps [elvis@station elvis]$ ls -l /proc/1910/fd total 0 lrwx------ 1 elvis elvis 64 Sep 13 0 6:42 0 -> /dev/tty1 lrwx------ 1 elvis elvis 64 Sep 13 0 6:42 1 -> /dev/tty1 lrwx------ 1 elvis elvis 64 Sep 13 0 6:42 2 -> /dev/tty1 lr-x------ 1 elvis elvis 64 Sep 13 0 6:42 3 -> /etc/termcap

elvis observa que el PID del proceso cat es 1910.

elvis ahora mira en el subdirectorio, el cual corresponde al PID observado.

No es de sorprender que el proceso cat tenga abierto el archivo /etc/termcap (debe poder leer el archivo para mostrar su contenido). Quizás un poco extraño es que éste no esté sólo o incluso que no sea el primer archivo abierto por el proceso. El comando cat tiene tres archivos abiertos antes que éste o más exactamente, el mismo archivo abierto tres veces: /dev/tty1 .

Como protocolo de Linux (y Unix), cada proceso hereda tres archivos abiertos tras el inicio. El primero, el descriptor de archivo 0, es la entrada estándar. El segundo, el archivo descriptor 1, es la salida estándar, y el tercero, el archivo descriptor 2, es el error estándar (será tratado en la siguiente lección). ¿Qué archivos abiertos heredó el comando cat de la shell bash que lo inició? El nodo del dispositivo /dev/tty1 para todos los tres.

Table 1. Entrada estándar, salida estándar y descriptores de archivos de error estándar

Flujo Descriptor Abbreviation

Page 6: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

6

Flujo Descriptor Abbreviation

Entrada estándar 0 stdin

Salida estándar 1 stdout

Error estándar 2 stderr

Recuerde que /dev/tty1 es el nodo del dispositivo conectado al controlador dentro del kernel. Cualquier cosa que elvis teclee se puede leer desde este archivo y cualquier cosa que se escriba en este archivo aparecerá en la terminal de elvis. ¿Qué sucede si el proceso cat lee desde stdin? Éste lee la entrada desde el teclado de elvis. ¿Qué sucede si éste escribe a stdout? Cualquier cosa que se escriba se verá en la terminal de elvis.

Redirección

En el siguiente ejemplo, elvis ejecuta con cat el archivo /etc/termcap pero esta vez redirige stdout al archivo /tmp/foo . Una vez más, elvis suspende el comando en la mitad del camino con las teclas CONTROL -Z.

[elvis@station elvis]$ cat /etc/termcap > /tmp/foo [1]+ Stopped cat /etc/termcap >/tm p/foo

Utilizando la misma técnica anterior, elvis examina los archivos que el comando cat ha abierto y los descriptores de archivo asociados con ellos.

[elvis@station elvis]$ ps PID TTY TIME CMD 1368 pts/1 00:00:00 bash 1976 pts/1 00:00:00 cat 1977 pts/1 00:00:00 ps [elvis@station elvis]$ ls -l /proc/1976/fd total 0 lrwx------ 1 elvis elvis 64 Sep 13 0 7:05 0 -> /dev/pts/1 l-wx------ 1 elvis elvis 64 Sep 13 0 7:05 1 -> /tmp/foo

lrwx------ 1 elvis elvis 64 Sep 13 0 7:05 2 -> /dev/pts/1 lr-x------ 1 elvis elvis 64 Sep 13 0 7:05 3 -> /etc/termcap

Observe que el descriptor de archivo 1 (en otras palabras, la salida estándar) no está conectado a la terminal sino al archivo /tmp/foo .

¿Qué sucede cuando elvis redirige tanto la entrada como la salida estándar?

[elvis@station elvis]$ cat < /etc/termcap > /tmp/fo o [1]+ Stopped cat </etc/termcap >/t mp/foo [elvis@station elvis]$ ps PID TTY TIME CMD 1368 pts/1 00:00:00 bash

Page 7: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

7

1980 pts/1 00:00:00 cat 1988 pts/1 00:00:00 ps [elvis@station elvis]$ ls -l /proc/1980/fd total 0 lr-x------ 1 elvis elvis 64 Sep 13 0 7:07 0 -> /etc/termcap l-wx------ 1 elvis elvis 64 Sep 13 0 7:07 1 -> /tmp/foo lrwx------ 1 elvis elvis 64 Sep 13 0 7:07 2 -> /dev/pts/1

El descriptor de archivo 0 (entrada estándar) no está conectado a la terminal sino al archivo /etc/termcap .

Cuando el comando cat se llama sin argumentos (por ejemplo, sin ningún nombre de archivo o archivos para mostrar), éste muestra la entrada estándar en su lugar. En lugar de abrir un archivo específico (mediante el descriptor de archivo 3, como el anterior), el comando cat lee desde stdin.

¿Cuál es la diferencia de eficiencia entre los siguientes tres comandos?

[elvis@station elvis]$ cat < /etc/termcap > /tmp/fo o [elvis@station elvis]$ cat /etc/termcap > /tmp/foo [elvis@station elvis]$ cp /etc/termcap /tmp/foo

No hay ninguna. Con el fin de apreciar el beneficio real del diseño de comandos para leer desde la entrada estándar en lugar de los archivos llamados debemos esperar hasta que veamos las tuberías en una próxima lección.

Ejemplos

Los siguientes ejemplos incluyen un ejemplo rápido de cómo los nuevos usuarios suelen confundirse con comandos que leen desde la entrada estándar y un par de ejemplos de "la vida real" que los programas ftp y gnuplot utilizan. Los programas ftp y gnuplot son complicados y estos ejemplos apenas introducen algunas de sus funciones que sirven para hacer énfasis en uno de los temas más importantes en este cuaderno: si el programa es conducido desde una interfaz de línea de comandos, puede automatizarse con un script sencillo de texto y redirección.

Salida del comando sort

A continuación, blondie emplea el comando sort para ordenar los animales que se encuentran en el archivo de texto zoo .

[blondie@station blondie]$ cat zoo elephant seal ape giraffe fish [blondie@station blondie]$ sort zoo ape

Page 8: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

8

elephant fish giraffe seal

Como el nombre en inglés lo indica, el comando sort (en su forma más simple) lee un archivo y escribe línea por línea en orden alfabético. Al igual que el comando cat, cuando el comando sort se ejecuta sin argumentos (por ejemplo, nombres de archivo para ordenar), esperará entradas desde stdin.

[blondie@station blondie]$ sort < zoo ape elephant fish giraffe seal

Aunque esta conducta parece (y es) perfectamente razonable, a menudo confunde a los nuevos usuarios quienes inocentemente teclean un nombre de comando, "sólo para ver qué hace". A continuación, asuma que blondie no sabe aún sobre la entrada estándar. Al explorar, invoca el comando sort. Sin entender que el comando sort está esperando para leer la entrada estándar, por ejemplo, su teclado, trata de alguna manera de salir del comando que ha iniciado. Por último, un amigo le dice en voz baja "CONTROL -D".

[blondie@station blondie]$ sort ls quit man sort exit get me out of this CTRL- D exit get me out of this ls man sort quit [blondie@station blondie]$

Tras teclear CONTROL -D, la secuencia de control convencional "Fin del archivo" (recuerde el cuaderno 1), el comando sort imprime una lista ordenada de todo lo que se lee en la entrada estándar.

Transferencias automáticas FTP

La usuaria blondie usualmente toma un archivo README desde el servidor ftp para el proyecto del kernel de Linux, ftp.kernel.org. El servidor kernel.org ftp permite usuarios anónimos, es decir, usuarios que entran con el nombre de usuario "anónimo". Cuándo se les pide una contraseña, los usuarios anónimos de ftp no necesitan entregar ninguna, pero por protocolo dan su dirección de correo electrónico en su lugar.

[blondie@station student]$ ftp ftp.kernel.org Connected to ftp.kernel.org (204.152.189.116).

Page 9: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

9

220 ProFTPD [ftp.kernel.org] Name (ftp.kernel.org:blondie): anonymous 331 Anonymous login ok, send your complete email ad dress as your password. Contraseña: (blondie teclea su dirección de correo- electrónico) 230 Anonymous access granted, restrictions apply. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 227 Entering Passive Mode (204,152,189,116,237,224) . 150 Opening ASCII mode data connection for file lis t drwxr-s--- 2 korg mirrors 4096 May 21 2 001 for_mirrors_only drwx------ 2 root root 16384 Mar 18 00 :27 lost+found drwxrwsr-x 8 korg korg 4096 Mar 24 17 :46 pub 226 Transfer complete. ftp> cd pub 250 CWD command successful. ftp> ls 227 Entering Passive Mode (204,152,189,116,237,229) . g150 Opening ASCII mode data connection for file li st drwxrws--- 2 korg korg 4096 Mar 18 04 :05 RCS -r--r--r-- 1 korg korg 1963 Oct 4 2 001 README -r--r--r-- 1 korg korg 578 Mar 18 04 :04 README_ABOUT_BZ2_FILES drwxrwsr-x 4 korg korg 4096 Oct 26 2 000 dist ... 226 Transfer complete. ftp> get README local: README remote: README 227 Entering Passive Mode (204,152,189,116,237,237) . 150 Opening BINARY mode data connection for README (1963 bytes). 226 Transfer complete. 1963 bytes received in 0.000564 secs (3.4e+03 Kbyte s/sec) ftp> quit 221 Goodbye.

Cuando el comando ftp hace una pausa con el intérprete de comandosftp> , blondie teclea comandos para navegar los directorios del servidor ftp. Si blondie descargara este archivo a menudo, podría sentirse tentada a escribir un archivo de texto sencillo, getreadme.ftp , el cual reproduciría los comandos tecleados por ella. Podría entonces ejecutar el mismo comando ftp ftp.kernel.org . Sin embargo, esta vez usaría < para hacer que bash redirija stdin desde el archivo getreadme.ftp . Cuando el comando ftp lee la entrada desde su flujo de stdin, la información es provista por el archivo en lugar del teclado.

Primero, blondie utiliza un editor de texto sencillo para crear el archivo getreadme.ftp , el cual contiene todos los comandos que ella escribió de modo interactivo en el teclado (incluyendo la contraseña que dio al servidor anónimo ftp, [email protected]).

[blondie@station blondie]$ cat getreadme.ftp anonymous [email protected]

Page 10: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

10

ls cd pub ls get README quit

Observe cómo el contenido del archivo coincide exactamente con lo que tecleó al utilizar el comando anterior ftp . Luego, vuelve a ejecutar ftp ftp.kernel.org pero redirige stdin desde el archivo recién creado.

[blondie@station blondie]$ ftp ftp.kernel.org < get readme.ftp Password:Name (ftp.kernel.org:blondie): ?Invalid command drwxr-s--- 2 korg mirrors 4096 May 21 2 001 for_mirrors_only drwx------ 2 root root 16384 Mar 18 00 :27 lost+found drwxrwsr-x 8 korg korg 4096 Mar 24 17 :46 pub drwxrws--- 2 korg korg 4096 Mar 18 04 :05 RCS -r--r--r-- 1 korg korg 1963 Oct 4 2 001 README -r--r--r-- 1 korg korg 578 Mar 18 04 :04 README_ABOUT_BZ2_FILES drwxrwsr-x 4 korg korg 4096 Oct 26 2 000 dist -r--r--r-- 1 korg korg 1507 Oct 11 2 001 index.html drwxrwsr-x 8 korg korg 4096 Jan 21 2 002 linux drwxrwsr-x 3 korg korg 4096 Mar 24 17 :46 scm drwxrwsr-x 3 korg korg 4096 Oct 11 2 001 site drwxrwsr-x 11 korg korg 4096 Jan 1 2 002 software [blondie@station blondie]$ ls -l README -rw-rw-r-- 1 blondie blondie 1963 Jun 3 1 7:37 README

Después de ejecutar el comando, blondie tiene un nuevo archivo README en su directorio, el cual fue descargado por el comando ftp . Sin embargo, blondie tuvo un par de contratiempos.

• Primero, el comando se detuvo y ella tuvo pulsar una vez ENTER para que continuara. Por razones de seguridad, muchos comandos, cuando leen contraseñas, no las leen desde stdin, sino desde la terminal directamente, (los comandos no tienen que depender de stdin como su único medio de entrada, aunque la mayoría lo hacen). Cuando ftp intentó leer la contraseña desde la terminal, el programa se suspendió hasta que blondie pulsó la tecla ENTER.

• Segundo, hay una línea rara que dice ?Invalid Input . Dado que la contraseña fue leída directamente desde la terminal, no se infirió desde el archivo getreadme.ftp . Cuando el comando ftp fue a leer la siguiente línea de la entrada decía [email protected] , lo que no reconoció como un comando.

• Por último, los listados de directorio fueron descargados en la terminal al ejecutar el comando. Cuando el comando ftp ejecutó los comandos ls desde getreadme.txt , escribió la salida en stdout, la cual está aún conectada a la terminal. Debido a que blondie sabe dónde esta localizado el archivo y ha incluido esa información dentro de un script, no necesita ver esos listados cada vez que ejecuta el comando.

Page 11: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

11

Para resolver estos problemas, primero hace uso de un archivo~/.netrc . El comando ftp está diseñado para buscar un archivo como ese en el directorio de inicio del usuario y si existe, éste provee el nombre de usuario del usuario y la contraseña. Después de estudiar la página del manual netrc(5), blondie usa un editor de texto sencillo para crear el siguiente archivo ~/.netrc .

[blondie@station blondie]$ cat .netrc default login anonymous password [email protected] m

Dado que el archivo ~/.netrc ahora provee su nombre de usuario y contraseña, blondie los suprime de su script getreadme.ftp . Luego, quita los comandos innecesarios ls también desde el script.

[blondie@station blondie]$ cat getreadme.ftp cd pub get README quit

Armada con su archivo ~/.netrc (para proveer su nombre de usuario y contraseña) y su archivo getreadme.txt modificado (para proveer los comandos del programa ftp ), vuelve a ejecutar el comando ftp y la operación se realiza sin problemas.

[blondie@station blondie]$ head .netrc getreadme.ft p ==> .netrc <== default login anonymous password user@site ==> getreadme.ftp <== cd pub get README quit [blondie@station blondie]$ ls getreadme.ftp [blondie@station blondie]$ ftp ftp.kernel.org < get readme.ftp [blondie@station blondie]$ ls getreadme.ftp README

Generación automática de gráficos con gnuplot

La usuaria madonna desearía generar fácilmente diagramas de la actividad de la CPU de su máquina. Está familiarizada con el comando vmstat, el cual hace muestreos y cuadros de varios parámetros relacionados con el funcionamiento del sistema. El comando puede tomar dos argumentos numéricos, el primero, especifica el periodo de muestreo en segundos y el último, el número de muestras para recopilar.

Ella está interesada en las tres últimas columnas, las cuales son el porcentaje de tiempo que está gastando la CPU en el sistema ("sy"), del usuario ("us") y en estado inactivo ("id"). Recopila 60 segundos de datos desde su máquina, la cual realiza muestreos cada segundo.

[madonna@station madonna]$ vmstat 1 60 > stats.txt [madonna@station madonna]$ head stats.txt

Page 12: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

12

procs memory swap io system cpu r b swpd free buff cache si so bi bo in cs us sy id wa 2 6 0 17348 65604 277768 0 0 15 16 126 221 1 0 97 1 1 5 0 15736 66008 277788 0 0 376 6269 314 725 5 2 0 93 1 6 0 11496 67224 277392 0 0 1216 8 422 1533 15 16 0 69 0 6 0 10492 67944 277676 0 0 940 28 338 1193 7 8 0 85 0 6 0 10168 68324 277644 0 0 576 0 261 992 6 1 0 93 3 3 0 8848 69424 277864 0 0 1252 64 429 1386 10 16 0 74 3 3 0 8056 70188 277892 0 0 1068 1148 422 1215 8 16 0 76 1 6 0 12248 71084 277636 0 0 940 28 341 1275 9 4 0 87

Un poco frustrada porque las dos líneas de los encabezados interferirán con la diagramación de los datos, madonna abre el archivo stats.txt en un editor de texto y los borra con facilidad.

Para diagramar los datos, utiliza gnuplot, un sofisticado paquete de diagramación, el cual usa comandos leídos desde una interfaz de terminal para generar diagramas de funciones matemáticas y datos numéricos. Después de navegar un poco a través de la ayuda en línea disponible dentro de gnuplot desarrolla los siguientes comandos para diagramar sus datos como un archivo de gráficos PNG llamado cpu.png .

[madonna@station madonna]$ gnuplot G N U P L O T Version 3.7 patchlevel 3 ... Terminal type set to 'x11' gnuplot> set term png Terminal type set to 'png' Options are ' small color' gnuplot> set output 'cpu.png' gnuplot> plot 'stats.txt' using 0:13 title "user" w ith lines, 'stats.txt' using 0:14 title "system" with lines, 'stats.txt' using 0 :15 title "idle" with lines gnuplot> quit

Después de salir de gnuplot vuelve a la shell bash, donde utiliza el visor de pantalla eog para ver su diagrama.

[madonna@station madonna]$ eog cpu.png

Page 13: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

13

Figure 1. Gráfico de madonna de la actividad de la CPU

Dado que madonna desearía a menudo generar un diagrama semejante, y no tener la angustia de teclear el comando gnuplot a cada instante, genera un script que se puede utilizar para automatizar gnuplot. Mediante un editor de texto, crea el archivo cpu_plot.gnuplot , el cual contiene todos comandos gnuplot que entró desde el teclado, teniendo el cuidado de poner un comando por línea.

[madonna@station madonna]$ cat cpu_plot.gnuplot set term png set output 'cpu.png' plot 'stats.txt' using 0:13 title "user" with lines , 'stats.txt' using 0:14 titl e "system" with lines, 'stats.txt' using 0:15 title "idle" with lines

Ahora puede diagramar con facilidad datos recopilados recientemente redirigiendo su script como la stadin de gnuplot.

[madonna@station madonna]$ gnuplot < cpu_plot.gnupl ot

Ejercicios en línea

Uso de la entrada estándar y la salida estándar

Lab Exercise Objetivo: Usar la redirección de la shell bash para controlar de modo efectivo la

Page 14: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

14

entrada estándar y la salida estándar.

Tiempo estimado: 20 minutos.

Especificaciones

1. El comando hostname informa su nombre de máquina asignado de la estación actual. Ejecute el comando (sin argumentos) y redirige la salida al archivo ~/stdoutlab.txt .

2. El comando uptime reporta cuánto tiempo ha pasado desde que arrancó su máquina y otra información de uso del sistema. Ejecute el comando uptime (sin argumentos) usando la redirección para agregar la salida al archivo ~/stdoutlab.txt .

3. El comando uname -a lista información sobre su versión actual de kernel. Ejecute el comando usando la redirección para agregar la salida al archivo ~/stdoutlab.txt .

Si ha completado con éxito los tres pasos anteriores, usted debería poder reproducir una salida semejante a la siguiente, (no se preocupe si la información difiere de la que se muestra a continuación).

[student@station student]$ cat stdoutlab.txt station 07:09:31 up 11:30, 5 users, load average: 0.19, 0.06, 0.01 Linux station 2.4.20-20.9 #1 Mon Aug 18 11:45:58 ED T 2003 i686 i686 i386 GNU/Linux

4. Genere un archivo de texto sencillo, ~/script.gnuplot , el cual sirva de script para controlar gnuplot. Cuando gnuplot lea su script desde stdin, debería generar un diagrama de una expresión matemática simple tal como el seno de x (sin(x) ) o x al cuadrado (x**2 ). El diagrama debería generarse como un gráfico PNG llamado "gnuplot.png".

Una vez completado su script debería poderse utilizar como en el próximo ejemplo.

[student@station student]$ ls script.gnuplot [student@station student]$ gnuplot < script.gnuplot [student@station student]$ ls gnuplot.png script.gnuplot [student@station student]$ file gnuplot.png gnuplot.png: PNG image data, 640 x 480, 8-bit color map, non-interlaced [student@station student]$ eog gnuplot.png

Page 15: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

15

Deliverables

Question 1

1. Un archivo llamado ~/stdoutlab.txt , el cual contiene la salida del comando

hostname, seguido por la salida del comando uptime, seguido por la salida del comando uname -a.

2. Un script ~/script.gnuplot , que cuando se utliliza como stdin para el comando gnuplot, genera un archivo de gráficos PNG titulado gnuplot.png conteniendo un diagrama de una función matemática simple.

Estrategia sugerida para la automatización de un gnuplot

Utilizando el ejemplo 3 como su guía, experimente de modo interactivo con gnuplot, hasta que pueda generar un diagrama sencillo. Si está utilizando una terminal de texto de un entorno gráfico X puede generar diagramas de texto al establecer su terminal de salida gnuplot como terminal "tonta":

gnuplot> set term dumb

Una vez que pueda producir gráficos, establezca su tipo de terminal a png (para gráficos PNG) y su archivo de salida en "gnuplot.png" mediante los siguientes comandos ...

gnuplot> set term png gnuplot> set output "gnuplot.png"

... y genere su diagrama una vez más. Cuando haya entendido la secuencia de comandos para generar un diagrama como un archivo PNG registre los comandos como su script gnuplot.

Capítulo 2 Error estándar

Conceptos clave

• Los programas Unix reportan condiciones de error a un destino llamado error estándar (stderr).

• Usualmente, stderr está conectado a una pantalla de terminal y los mensajes de error se encuentran entremezclados con las salidas estándar.

• Cuando se utiliza la shell bash, el flujo de stderr puede redirigirse a un archivo mediante 2>.

• Al utilizar bash, el flujo de stderr puede combinarse con el flujo de stdout mediante 2>&1 o >&

Error estándar (stderr)

Page 16: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

16

Hemos discutido los flujos de salida y de entrada estándar, stdin y stdout y cómo usar > y < en la línea de comandosbash para redirigirlos. Ahora estamos listos para complicar un poco las cosas introduciendo un segundo flujo de salida, muy usado para reportar condiciones de error, llamado error estándar (a menudo abreviado stderr).

En la siguiente secuencia, elvis está utilizando el comando head -1 para generar una lista de las primeras líneas de todos los archivos en el directorio /etc/rc.d .

[elvis@station elvis]$ ls -F /etc/rc.d/ init.d/ rc0.d/ rc2.d/ rc4.d/ rc6.d/ rc.sysi nit* rc* rc1.d/ rc3.d/ rc5.d/ rc.local* rc.sysi nit.rpmsave* [elvis@station elvis]$ head -1 /etc/rc.d/* ==> /etc/rc.d/init.d <== head: /etc/rc.d/init.d: Is a directory ==> /etc/rc.d/rc <== #! /bin/bash ==> /etc/rc.d/rc0.d <== head: /etc/rc.d/rc0.d: Is a directory ==> /etc/rc.d/rc1.d <== head: /etc/rc.d/rc1.d: Is a directory ==> /etc/rc.d/rc2.d <== head: /etc/rc.d/rc2.d: Is a directory ==> /etc/rc.d/rc3.d <== head: /etc/rc.d/rc3.d: Is a directory ==> /etc/rc.d/rc4.d <== head: /etc/rc.d/rc4.d: Is a directory ==> /etc/rc.d/rc5.d <== head: /etc/rc.d/rc5.d: Is a directory ==> /etc/rc.d/rc6.d <== head: /etc/rc.d/rc6.d: Is a directory ==> /etc/rc.d/rc.local <== #!/bin/sh ==> /etc/rc.d/rc.sysinit <== #!/bin/bash ==> /etc/rc.d/rc.sysinit.rpmsave <== #!/bin/bash

Cuando se alimenta el comando head con múltiples archivos como argumentos este representa de manera conveniente el nombre del archivo, seguido por el primer número especificado de las líneas (en este caso, uno). Sin embargo, cuando el comando head encuentra un directorio apenas se queja. Luego, elvis ejecuta el mismo comando, redirigiendo stdout al archivorcsummary.out .

Page 17: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

17

[elvis@station elvis]$ head -1 /etc/rc.d/* > rcsumm ary.out head: /etc/rc.d/init.d: Is a directory head: /etc/rc.d/rc0.d: Is a directory head: /etc/rc.d/rc1.d: Is a directory head: /etc/rc.d/rc2.d: Is a directory head: /etc/rc.d/rc3.d: Is a directory head: /etc/rc.d/rc4.d: Is a directory head: /etc/rc.d/rc5.d: Is a directory head: /etc/rc.d/rc6.d: Is a directory

La mayor parte de la salida es obedientemente redirigida al archivo rcsummary.out , pero las quejas del directorio aún se visualizan. Aunque no es obvio desde el principio, el comando head está realmente enviando salida a dos flujos independientes. La salida normal se escribe en la salida estándar, pero un mensaje de error se escribe en un flujo separado llamado error estándar (a menudo abreviado stderr). Ambos flujos suelen estar conectados a la terminal y por eso es difícil distinguirlos. No obstante, al redireccionar stdout, la información escrita a stderr es evidente.

Redirección de stderr

Así como bash usa > para redirigir lastdout, bash usa 2> para redirigir elstderr. Por ejemplo, elvis repite el comando head desde arriba, pero en vez de redirigir stdout a rcsummary.out , redirige el stderr al archivo rcsummary.err .

[elvis@station elvis]$ head -1 /etc/rc.d/* 2> rcsum mary.err ==> /etc/rc.d/init.d <== ==> /etc/rc.d/rc <== #! /bin/bash ==> /etc/rc.d/rc0.d <== ==> /etc/rc.d/rc1.d <== ==> /etc/rc.d/rc2.d <== ==> /etc/rc.d/rc3.d <== ==> /etc/rc.d/rc4.d <== ==> /etc/rc.d/rc5.d <== ==> /etc/rc.d/rc6.d <== ==> /etc/rc.d/rc.local <== #!/bin/sh ==> /etc/rc.d/rc.sysinit <== #!/bin/bash ==> /etc/rc.d/rc.sysinit.rpmsave <== #!/bin/bash

Page 18: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

18

La salida es el complemento al ejemplo anterior. Ahora vemos la salida normal visualizada en la pantalla, pero sin mensajes de error. ¿A dónde fueron a parar los mensajes de error? No costaría mucho trabajo adivinar.

[elvis@station elvis]$ cat rcsummary.err head: /etc/rc.d/init.d: Is a directory head: /etc/rc.d/rc0.d: Is a directory head: /etc/rc.d/rc1.d: Is a directory head: /etc/rc.d/rc2.d: Is a directory head: /etc/rc.d/rc3.d: Is a directory head: /etc/rc.d/rc4.d: Is a directory head: /etc/rc.d/rc5.d: Is a directory head: /etc/rc.d/rc6.d: Is a directory

En el siguiente ejemplo tanto > como 2> se utilizan para redirigir stdout y stderr de modo independiente.

[elvis@station elvis]$ head -1 /etc/rc.d/* > rcsumm ary.out 2> rcsummary.err [elvis@station elvis]$

En este caso, la salida estándar puede encontrarse en el archivo rcsummary.out , se pueden encontrar mensajes de error en rcsummary.err y no queda nada para mostrar en la pantalla.

Combinación de stdout y stderr: vieja escuela

Con frecuencia, desearíamos redirigir los flujos de stdout y stderr combinados en un sólo archivo. Como un primer intento, elvis ensaya el siguiente comando.

[elvis@station elvis]$ head -1 /etc/rc.d/* > rcsumm ary.both 2> rcsummary.both

Sin embargo, tras examinar el archivo rcsummary.both , elvis no halla lo que espera.

[elvis@station elvis]$ cat rcsummary.both head: /etc/rc.d/init.d: I ==> /etc/rc.dhead: /etc/rc.d/rc0.d: Is a directory head: /etc/rc.d/rc1.d: Is a direc ==> head: /etc/rc.d/rc2. ==> /etc/rc.d/rc3head: / ==> /etc/rc.d/rc4.d <== ==> /etc/rc.d/rc5.d <== ==> /etc/rc.d/rc6.d <== ==> /etc/rc.d/rc.local <== #!/bin/sh ==> /etc/rc.d/rc.sysinit <== #!/bin/bash

Page 19: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

19

==> /etc/rc.d/rc.sysinit.rpmsave <== #!/bin/bash

La shell bash abrió dos veces el archivo rcsummary.both , pero trató cada archivo abierto como un archivo independiente. Cuando stdout y stderr escribieron al archivo, sobrescribieron la información de cada cual. Lo que se necesitaba en su lugar es de alguna manera pedirle a bash combinar de modo eficaz stderr y stdout dentro de un sólo flujo y luego redirigir ese flujo a un archivo único. Como es de esperarse, esa forma existe.

[elvis@station elvis]$ head -1 /etc/rc.d/* > rcsumm ary.both 2>&1

Aunque un poco extraño, el último símbolo 2>&1 debería considerarse como si se dijera "tome al stderr, y envíelo a dónde stdout está actualmente". Ahora,rcsummary.both contiene la salida esperada.

[elvis@station elvis]$ cat rcsummary.both ==> /etc/rc.d/init.d <== head: /etc/rc.d/init.d: Is a directory ==> /etc/rc.d/rc <== #! /bin/bash ==> /etc/rc.d/rc0.d <== head: /etc/rc.d/rc0.d: Is a directory ==> /etc/rc.d/rc1.d <== head: /etc/rc.d/rc1.d: Is a directory ...

Mucha de esta salida fue truncada y remplazada por "...".

Combinación de stdout y stderr: nueva escuela

Al usar 2>&1 para combinar stdout y stderr se introdujo en la shell Unix original, la shell Bourne (sh). Dado que bash está diseñado para ser compatible con sintaxis anteriores sh también soporta esta sintaxis. Sin embargo, la sintaxis no es conveniente. Además de ser difícil de escribir, el orden de las redirecciones es importante. Al usar ">out.txt

2>&1" y "2>&1 >out.txt " ¡no produce el mismo efecto!

Para simplificar las cosas, bash usa >& para combinar stdin y stdout como en el siguiente ejemplo.

[elvis@station elvis]$ head -1 /etc/rc.d/* >& rcsum mary.both

Resumen

El siguiente cuadro resume la sintaxis empleada por la shell bash para redireccionar stdin, stdout, y stderr tratados en la lección anterior y en ésta.

Page 20: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

20

Table 1. Redirección de stdin, stdout y stderr en bash

sintaxis efecto

cmd < file Redirección stdin desde file

cmd > file Redirigir stdout a file, sobrescribir file si existe.

cmd >> file Redirigir stdout a file agregando file si existe.

cmd 2> file Redirigir stderr a file sobrescribir file si existe.

cmd 2>> file Redirigir stderr a file agregando file si éste existe.

cmd > file 2>&1 Combinar stdout y stderr, y redirigirlos a file. (sintaxis portátil)

cmd >& file Combinar stdout y stderr y redirigirlos a file.(sintaxis conveniente)

Ejemplos

Uso de /dev/null para filtrar stderr

El usuario elvis recientemente ha aprendido que aparte de los directorios /home/elvis y /tmp con los que está familiarizado, también puede tener archivos en el directorio /var . Estos archivos en espera suelen ser archivos para correos electrónicos recibidos, pero que no han sido vistos, o por ejemplo, también pueden ser trabajos de impresión en espera.

Intrigado usa el comando find para buscar todos los archivos dentro del directorio /var que posee.

[elvis@station elvis]$ find /var -user elvis find: /var/lib/slocate: Permission denied find: /var/lib/nfs/statd: Permission denied find: /var/lib/xdm/authdir: Permission denied ... find: /var/spool/lpd/three-west: Permission denied find: /var/spool/lpd/one-east-color: Permission den ied find: /var/spool/lpd/server1: Permission denied /var/spool/mail/elvis find: /var/spool/at: Permission denied ... find: /var/tux: Permission denied find: /var/tomcat4/webapps: Permission denied

(Mucha de la salida de ese comando ha sido truncada y remplazada por "...").

Aunque el comando find reportó correctamente el archivo /var/spool/mail/elvis , la salida es difícil de hallar dentro de todos los mensajes de error de "Permiso negado" reportados desde varios subdirectorios de /var . Con el fin de ayudar a apartar lo útil de lo inservible, elvis redirige stderr a algún archivo en el directorio /tmp.

[elvis@station elvis]$ find /var -user elvis 2> /tm p/foo /var/spool/mail/elvis

Page 21: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

21

Aunque esto funciona, elvis queda con un archivo llamado /tmp/foo que en realidad no quería. En situaciones como ésta, cuando un usuario quiere deshacerse de un flujo de información, los usuarios experimentados de Unix suelen redirigir la salida a un seudo dispositivo llamado /dev/null .

[elvis@station elvis]$ find /var -user elvis 2> /de v/null /var/spool/mail/elvis

Como lo muestra el siguiente listado largo, /dev/null es un nodo de dispositivo de caracter como aquellos de los controladores de dispositivo convencionales.

[elvis@station elvis]$ ls -l /dev/null crw-rw-rw- 1 root root 1, 3 Jan 30 0 5:24 /dev/null

Cuando un usuario escribe en /dev/null , la información es apenas descartada por el kernel. Cuando un usuario lee desde /dev/null encuentra inmediatamente un fin de archivo. Observe que /dev/null es uno de los pocos archivos en Red Hat Enterprise Linux que tiene permisos de escritura por defecto para todo el mundo.

Ejercicios en línea

Lab Exercise Objetivo: Administrar de modo efectivo los flujos de la entrada estándar, la salida estándar y el error estándar

Estimated Time: 10 mins.

Especificaciones

1. Utilice la siguiente línea de comandos para mostrar el contenido de todos los archivos dentro del directorio /etc/X11 .

2. [elvis@station elvis]$ cat /etc/X11/* 3. cat: /etc/X11/applnk: Is a directory 4. cat: /etc/X11/desktop-menus: Is a directory 5. cat: /etc/X11/fs: Is a directory 6. cat: /etc/X11/gdm: Is a directory 7. cat: /etc/X11/lbxproxy: Is a directory 8. #!/bin/sh 9. 10. PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin 11. ...

12. Repita la línea de comandos pero redirija stdout a un archivo llamado ~/stderrlab.out y stderr a un archivo llamado ~/stderrlab.err .

13. Repita el comando pero esta vez combine stdout y stderr en un sólo flujo y redirija el flujo al archivo ~/stderrlab.both .

Deliverables

Question 1

Page 22: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

22

1. Un archivo llamado ~/stderrlab.out que contenga el flujo de stdout desde el

comando cat /etc/X11/* . 2. Un archivo llamado ~/stderrlab.err que contenga el flujo de stderr desde el

comando cat /etc/X11/* . 3. Un archivo llamado ~/stderrlab.both que contenga los flujos stdout y stderr

combinados desde el comando cat /etc/X11/* .

Capítulo 3 Tuberías

Conceptos clave

• El flujo de stdout desde un proceso puede estar conectado al flujo de stdin de otro proceso mediante lo que Unix llama una "tubería".

• Varios de los comandos en Unix están diseñados para operar como un filtro, leer la entrada desde stdin y enviar la salida a stdout.

• bash usa "|" para crear una tubería entre dos comandos.

Tuberías

En las lecciones anteriores, hemos visto que una salida de un proceso se puede redirigir a cualquier parte con excepción de la pantalla de la terminal o que puede pedírsele a un proceso que lea desde alguna parte con excepción del teclado de la terminal. Una de las formas más comunes y eficaces para redirigir es una combinación de las dos, donde la salida (salida estándar) de un comando es "entubada" directamente dentro de la entrada (entrada estándar) de otro comando formando lo que Linux (y Unix) llaman tubería.

Cuando dos comandos se unen por medio de una tubería, el flujo de stdout del primer proceso es ligado directamente a la secuencia stdin del segundo proceso para que múltiples procesos puedan combinarse en una secuencia. Con el fin de crear unq tubería por medio de bash, los dos comandos se unen con una barra vertical |, (en la mayoría de los teclados este caracter está en la misma tecla de una barra invertida encima de ENTER). A todos los procesos unidos en una tubería se les llama un grupo de proceso.

A manera de ejemplo, piense que prince está tratando de hallar los archivos más grandes bajo el directorio /etc . Comienza por escribir el comando find para obtener un listado de archivos con un tamaño mayor a 100kbytes.

[prince@station prince]$ find /etc -size +100k 2>/d ev/null /etc/termcap /etc/gconf/gconf.xml.defaults/schemas/desktop/gnome /interface/%gconf.xml /etc/gconf/gconf.xml.defaults/schemas/apps/mailchec k_applet/prefs/%gconf.xml

Page 23: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

23

/etc/gconf/gconf.xml.defaults/schemas/apps/tasklist _applet/prefs/%gconf.xml ...

Al observar que el comando find no parece listar los archivos en ningún orden en particular, prince decide que sus archivos sean listados en orden alfabético. En lugar de redirigir la salida a un archivo y luego sort el archivo, aprovecha que el comando sortse invoca sin argumentos y espera los datos desde la entrada estándar para ordenarlos. Él entuba la salida de su comando de búsqueda hacia sort.

[prince@station prince]$ find /etc -size +100k 2>/d ev/null | sort /etc/aep/aeptarg.bin /etc/gconf/gconf.xml.defaults/schemas/apps/gedit-2/preferences/editor/save/%gconf.xml /etc/gconf/gconf.xml.defaults/schemas/apps/gnomemee ting/general/%gconf.xml ... /etc/makedev.d/cciss /etc/makedev.d/dac960 /etc/squid/squid.conf /etc/squid/squid.conf.default /etc/termcap

Ahora los archivos están listados en orden alfabético.

Filtro de salida con grep

El comando tradicional de Unix grep se utiliza en tuberías para reducir datos a sólo las partes "interesantes". El comando grep se analizará más tarde en un cuaderno. Aquí presentamos el comando grep en su forma más sencilla.

El comando grep se utiliza para buscar y extraer líneas que contengan una cadena de texto específico. Por ejemplo, a continuación, prince imprime todas las líneas que contienen el texto "root" desde el archivo /etc/passwd .

[prince@station prince]$ grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin

El primer argumento para el comando grep es la cadena de texto que va a ser buscada, y los argumentos restantes son archivos que van a ser buscados para el texto. Si el comando grep llamado con un solo argumento (una cadena de texto para ser buscada, pero no archivos), espera la entrada estándar como su fuente de información en la cual operar.

En el siguiente, prince tiene tantos archivos en su directorio de inicio que está teniendo problemas para seguirles el rastro. Trata de hallar un directorio llamadotemplates que él creó hace unos meses. Utiliza el comando locate para encontrarlo.

[prince@station prince]$ locate templates /etc/openldap/ldaptemplates.conf

Page 24: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

24

/usr/share/doc/libxslt-1.0.27/html/libxslt-template s.html /usr/share/doc/libxslt-1.0.27/templates.gif /usr/share/doc/docbook-style-xsl-1.58.1/docsrc/temp lates.xml /usr/share/man/man5/ldaptemplates.conf.5.gz /usr/share/man/man3/ldap_free_templates.3.gz /usr/share/man/man3/ldap_init_templates_buf.3.gz /usr/share/man/man3/ldap_init_templates.3.gz ...

Por desgracia para prince, hay muchos archivos en el sistema que contienen el textotemplates en su nombre y se confunde con líneas y líneas de salida. Con el fin de reducir la información a archivos más importantes, prince toma la stdout desde el comando locate y crea una tubería para la stdin del comandogrep, "buscando" la palabra "prince".

[prince@station 010_section_discussion]$ locate tem plates | grep prince /home/prince/.kde/share/apps/quanta/templates /home/prince/proj/templates

Dado que al comando grep no se le da un archivo para buscar, espera a la stdin, donde encuentra el flujo de stdout del comando locate. Al filtrar el flujo, grep sólo duplica a sus líneas stdout que coincidieron con el texto especificado, "prince". El resto fue descartado. El usuario prince encuentra fácilmente su directorio bajo ~/proj , como también otro directorio creado por la aplicación quanta.

Tuberías y stderr

En el próximo ejemplo, prince quiere ver dónde aparece en los archivos de configuración del sistema y utiliza la herramienta "grep" con su nombre en el directorio /etc .

[prince@station prince]$ grep prince /etc/* grep: /etc/aliases.db: Permission denied grep: /etc/at.deny: Permission denied grep: /etc/default: Permission denied /etc/group:music:x:205:elvis,blondie,prince,madonna ,student /etc/group:prince:x:502: grep: /etc/group-: Permission denied grep: /etc/group.lock: Permission denied ... grep: /etc/lvmtab: Permission denied /etc/passwd:prince:x:502:502::/home/prince:/bin/bas h grep: /etc/passwd-: Permission denied grep: /etc/passwd.lock: Permission denied ... grep: /etc/sudoers: Permission denied /etc/termcap:# From: John Doe <[email protected]> grep: /etc/vsftpd.conf.rpmsave: Permission denied

De nuevo, prince está abrumado con tanta salida desde este comando. Emplea el mismo truco de buscar con "grep" todas las líneas que contengan la palabra "passwd".

Page 25: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

25

[prince@station prince]$ grep prince /etc/* | grep passwd grep: /etc/aliases.db: Permission denied grep: /etc/at.deny: Permission denied grep: /etc/default: Permission denied grep: /etc/group-: Permission denied grep: /etc/group.lock: Permission denied ... grep: /etc/lvmtab: Permission denied /etc/passwd:prince:x:502:502::/home/prince:/bin/bas h grep: /etc/passwd-: Permission denied grep: /etc/passwd.lock: Permission denied ...

Aunque stdout desde el primer comando con grep fue filtrado correctamente, stderr no se afectó y aún se muestra en la pantalla. ¿Cómo le iría a prince si suprimiera también stderr?

Comandos como filtros

El concepto de tubería se extiende naturalmente para que múltiples comandos se puedan usar en conjunto, cada información de lectura desde stdin, de alguna manera modifica o filtra la información y pasa el resultado a stdout. En un próximo cuaderno, usted verá que hay muchos comandos estándar de Linux (y Unix) diseñados para este propósito, incluyendo algunos de los cuales usted ya conoce: grep, head, tail , cut, sort, sed, y awk por nombrar unos cuantos.

Ejemplos

Listado de procesos por nombre

A menudo, quisiéramos listar información acerca de procesos que están ejecutando un comando específico. Aunque ps aux presenta un montón de información sobre procesos actuales en ejecución, el número de procesos ejecutándose en la máquina puede resultar en una la salida abrumadora. El comando grep puede ayudar a simplificar la salida.

A continuación, prince quiere listar información sobre los procesos que están implementando su servidor de red, el comando httpd . Él lista todos los procesos pero luego reduce la salida a solo aquellas líneas que contengan el texto httpd.

[prince@station prince]$ ps aux | grep httpd root 889 0.0 0.0 18248 100 ? S S ep22 0:00 /usr/sbin/httpd apache 907 0.0 0.5 18436 1320 ? S S ep22 0:00 /usr/sbin/httpd apache 913 0.0 0.7 18436 1952 ? S S ep22 0:00 /usr/sbin/httpd apache 914 0.0 0.5 18436 1332 ? S S ep22 0:00 /usr/sbin/httpd apache 1979 0.0 0.5 18360 1524 ? S S ep22 0:00 /usr/sbin/httpd apache 1980 0.0 0.8 18388 2140 ? S S ep22 0:00 /usr/sbin/httpd

Page 26: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

26

apache 1981 0.0 0.5 18360 1524 ? S S ep22 0:00 /usr/sbin/httpd prince 4905 0.0 0.2 3572 640 pts/1 S 0 6:19 0:00 grep httpd

Búsqueda eficaz en el historial de comandos

Recientemente, el usuario prince tomó un buen tiempo construyendo una línea de comandos find , la cual listaba todos los archivos grandes bajo el directorio /etc , incluyendo el tamaño. En lugar de repetir su esfuerzo prefiere ver si el comando está aún en su historial. Dado que su historial contiene cientos de líneas, utiliza el comando grep para ayudar a reducir la salida.

[prince@station prince]$ history | grep find 102 find /var -user elvis 175 find -exec file {} \; 434 find /etc -name *.conf | head 675 find /etc -size +100k 680 find /etc -size +100k -exec ls -s {} \; 2>/d ev/null 682 find -size +100k /etc 683 find /etc -size +100k 690 history | grep find

Ahora localiza la línea de comandos que quería y utiliza la sustitución del historial para repetir el comando con facilidad.

[prince@station prince]$ !680 find /etc -size +100k -exec ls -s {} \; 2>/dev/null 728 /etc/termcap 132 /etc/gconf/gconf.xml.defaults/schemas/desktop/gnome /interface/%gconf.xml 304 /etc/gconf/schemas/gedit.schemas ...

Filosofía de Unix: Herramientas sencillas que funcionan bien juntas

Linux, al igual que Unix, se basa fundamentalmente en la filosofía de que los sistemas complejos deberían crearse de componentes simples y de componentes especializados que funcionen fácilmente entre sí. Siguiendo esta filosofía, muchos programas estándar de Linux están diseñados para operar como filtros, leyendo información desde una fuente estándar manipulando los datos y entregando el resultado a un destino estándar.

Esta filosofía es importante para ilustrar el uso de un ejemplo largo y detallado. El ejemplo utilizará comandos con los que usted aún no está familiarizado. No se preocupe de los detalles de cómo usar los comandos, en su lugar, enfóquese en cómo funcionan juntos, cada comando realiza un pequeña parte para producir el resultado deseado.

Suponga que un administrador de sistemas está examinando los mensajes de alquiler DHCP en un archivo de registro bien conocido, /var/log/messages . Si usted no está familiarizado con DHCP, es el protocolo por medio del cual las direcciones IP se

Page 27: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

27

pueden asignar a máquinas basadas en la dirección de hardware (MAC) construídas dentro de una tarjeta de Ethernet de la máquina. En las siguientes líneas de /var/log/messages enfóquese en la línea que contiene la palabra DHCPOFFER. Observe que la dirección IP 192.168.0.11 se está ofreciendo a la tarjeta de Ethernet con la dirección de hardware de 00:08:74:37:c5:c3.

... May 27 12:18:21 server1 dhcpd: DHCPACK on 192.168.0 .110 to 00:09:6b:d0:ce:8f via eth0 May 27 12:18:27 server1 login(pam_unix)[1981]: sess ion closed for user root May 27 12:19:15 server1 named[24350]: listening on IPv4 interface eth1, 192.168.22.20#53 May 27 12:19:21 server1 vsftpd: warning: can't get client address: Bad file descriptor May 27 12:19:21 server1 last message repeated 3 tim es May 27 12:20:27 server1 dhcpd: DHCPDISCOVER from 00 :08:74:37:c5:c3 via eth0 May 27 12:20:27 server1 dhcpd: DHCPOFFER on 192.168 .0.11 to 00:08:74:37:c5:c3 via eth0 May 27 12:20:27 server1 dhcpd: DHCPREQUEST for 192. 168.0.11 (192.168.0.254) from 00:08:74:37:c5:c3 via eth0 ...

Sin preocuparse por detalles del protocolo de DHCP, suponga que el administrador deseara extraer una lista de direcciones IP y las direcciones de hardware que se ofrecen en el archivo de registro. Un administrador experimentado podría emplear el siguiente método.

Dándose cuenta que el archivo /var/log/message es un archivo muy grande, en este caso más de 1000 líneas de longitud, el administrador primero utiliza el comando grep para reducir la información a las líneas pertinentes.

[root@station log]# grep DHCPOFFER messages May 27 11:46:22 server1 dhcpd: DHCPOFFER on 192.168 .0.1 to 00:08:74:d9:41:9e via eth0 May 27 11:46:22 server1 dhcpd: DHCPOFFER on 192.168 .0.1 to 00:08:74:d9:41:9e via eth0 May 27 11:46:30 server1 dhcpd: DHCPOFFER on 192.168 .0.1 to 00:08:74:d9:41:9e via eth0 May 27 11:46:30 server1 dhcpd: DHCPOFFER on 192.168 .0.1 to 00:08:74:d9:41:9e via eth0 May 27 11:48:40 server1 dhcpd: DHCPOFFER on 192.168 .0.2 to 00:08:74:d9:41:32 via eth0 ...

Este es un comienzo pero el administrador aún está manejando demasiada información (la toma de pantalla de arriba sólo lista las primeras 5 de 90 líneas producidas por este comando). Con el fin de extraer sólo la información pertinente, es decirla dirección IP y la dirección de hardware, el administrador toma la salida del comando grep y la entuba a un comando llamado sed, el cual quita las primeras palabras de cada línea.

[root@station log]# grep DHCPOFFER messages | sed " s/^.*on //"

Page 28: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

28

192.168.0.1 to 00:08:74:d9:41:9e via eth0 192.168.0.1 to 00:08:74:d9:41:9e via eth0 192.168.0.1 to 00:08:74:d9:41:9e via eth0 192.168.0.1 to 00:08:74:d9:41:9e via eth0 192.168.0.2 to 00:08:74:d9:41:32 via eth0 192.168.0.2 to 00:08:74:d9:41:32 via eth0 192.168.0.2 to 00:08:74:d9:41:32 via eth0 192.168.0.2 to 00:08:74:d9:41:32 via eth0 192.168.0.3 to 00:08:74:d9:40:a4 via eth0 ...

Si no está familiarizado con el comando sed (muy probablemente no lo está), no se preocupe por los detalles, sólo observe que el argumento de sed quitó el texto inicial de cada línea hasta la palabra "on". Como no queda mucho texto, el administrador toma la salida de esta combinación grep-sed y la entuba al comando llamado awk.

[root@station log]$ grep DHCPOFFER messages | sed " s/^.*on // " | awk '{print $1,$3}' ... 192.168.0.14 00:08:74:34:fe:bc 192.168.0.5 00:08:74:34:fd:36 192.168.0.15 00:08:74:37:c8:eb 192.168.0.15 00:08:74:37:c8:eb 192.168.0.6 00:08:74:d9:41:a3 192.168.0.16 00:08:74:d9:41:ac 192.168.0.7 00:08:74:d9:41:53 192.168.0.16 00:08:74:d9:41:ac 192.168.0.17 00:08:74:35:00:e3 ...

De nuevo, no se preocupe por los detalles del comando awk, observe que el resultado era extraer la primera y tercera columna de la salida anterior. Con el fin de ordenar la información, y quitar las líneas que se duplican, el administrador toma la salida desde la cadena y la entuba a través de los comandos sort y uniq.

[root@station log]$ grep DHCPOFFER messages | sed " s/^.*on // " | awk '{print $1,$3}' | sort | uniq 192.168.0.10 00:08:74:d9:40:95 192.168.0.1 00:08:74:d9:41:9e 192.168.0.110 00:09:6b:d0:ce:8f 192.168.0.11 00:08:74:37:c5:c3 192.168.0.12 00:08:74:d9:41:dd 192.168.0.13 00:08:74:35:00:d0 192.168.0.14 00:08:74:34:fe:bc 192.168.0.15 00:08:74:37:c8:eb 192.168.0.16 00:08:74:d9:41:ac 192.168.0.17 00:08:74:35:00:e3 192.168.0.2 00:08:74:d9:41:32 192.168.0.3 00:08:74:d9:40:a4 192.168.0.4 00:08:74:d9:3f:7f 192.168.0.5 00:08:74:34:fd:36 192.168.0.6 00:08:74:d9:41:a3 192.168.0.7 00:08:74:d9:41:53 192.168.0.8 00:08:74:d9:41:7b 192.168.0.9 00:08:74:35:00:1f

Page 29: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

29

Esta es casi la lista que el administrador quería pero el comando sort no funcionó bien. La información está ordenada, pero en orden alfabético, no por dirección IP. El administrador modifica el comando sort con un par de opciones para especificar el orden de modo numérico, pulsando en el cuarto campo, donde los campos están separados por un punto.

[root@station log]$ grep DHCPOFFER messages | sed " s/^.*on //" | awk '{print $1, $3}' | sort -n -k4 -t. | uniq 192.168.0.1 00:08:74:d9:41:9e 192.168.0.2 00:08:74:d9:41:32 192.168.0.3 00:08:74:d9:40:a4 192.168.0.4 00:08:74:d9:3f:7f 192.168.0.5 00:08:74:34:fd:36 192.168.0.6 00:08:74:d9:41:a3 192.168.0.7 00:08:74:d9:41:53 192.168.0.8 00:08:74:d9:41:7b 192.168.0.9 00:08:74:35:00:1f 192.168.0.10 00:08:74:d9:40:95 192.168.0.11 00:08:74:37:c5:c3 192.168.0.12 00:08:74:d9:41:dd 192.168.0.13 00:08:74:35:00:d0 192.168.0.14 00:08:74:34:fe:bc 192.168.0.15 00:08:74:37:c8:eb 192.168.0.16 00:08:74:d9:41:ac 192.168.0.17 00:08:74:35:00:e3 192.168.0.110 00:09:6b:d0:ce:8f

Esta es la lista que el administrador quería, en el orden deseado. Redirige todo esta salida a un archivo en su directorio de inicio.

[root@station log]$ grep DHCPOFFER messages | sed " s/^.*on //" | awk '{print $1 ,$3}' | sort -n -k4 -t. | uniq > ~/ip_dhcp.txt

En este ejemplo, un administrador (experimentado) que navega un archivo de registro pudo emplear unos pocos minutos y desarrollar una cadena de comandos que filtraran la información original a la información precisa deseada. Hizo esto mediante un puñado de herramientas que son para la mayoría de los administradores de Unix una caja de herramientas mentales: grep, sed, awk, sort, yuniq.

Si el administrador utilizara un sistema operativo que no estuviera diseñado en torno a esta filosofía de "pequeñas herramientas que trabajan juntas", habría necesitado depender de algún programador para desarrollar la utilidad ip_mac_extractor y posiblemente depender de ese programador para crear también una interfaz gráfica de usuario. En cambio, como pudo utilizar la flexibilidad de la línea de comando, pudo también manejar la información por sí mismo.

Ejercicios en línea

Lab Exercise

Page 30: Semana 9 -_standard_io_and_pipes

Standard IO and Pipe

30

Objetivo: Usar tuberías para filtrar información de modo efectivo.

Estimated Time: 10 mins.

Especificaciones

1. Usted desearía crear una lista ordenada de todos los servicios de TCP services que se encuentran en el archivo /etc/services . Entube la salida del comandogrep tcp /etc/services dentro del comando sort. Redirija la salida de esta tubería dentro del archivo ~/pipelab.txt .

2. Mediante el visualizador de página less desearía navegar la salida del comando ls -R /, viendo sólo archivos que contengan la letra s. Escriba un línea de comando con dos tuberías para encadenar los comandos ls -R /, grep s, y less. Abandone el visualizador de página less en el primer plano mientras califica su ejercicio.

Deliverables

A title

Question 1

1. Un archivo ~/pipelab.txt que contenga la salida del comando grep tcp

/etc/services entubado a través del comando sort. 2. Un visualizador de página activo less que está navegando la salida del comando

ls -R / entubado a través del comando grep s.

Limpieza

Después de calificar su ejercicio puede salir del paginador less.