Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Semana 9 - Standard IO and Pipes
Semana 9 - Standard IO and Pipes
Semana 9 - Standard IO and Pipes
Conceptos clave
En Linux (y Unix), los programas se pueden agrupar en los siguientes tres diseños.
Programas gráficos
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
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.
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
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.
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.
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.
Hey sysadmin...
I'm sending a list of processes that were running when 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.
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]
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
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.
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 06:42 0 -> /dev/tty1
lrwx------ 1 elvis elvis 64 Sep 13 06:42 1 -> /dev/tty1
lrwx------ 1 elvis elvis 64 Sep 13 06:42 2 -> /dev/tty1
lr-x------ 1 elvis elvis 64 Sep 13 06: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.
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.
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.
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 07:05 0 ->
/dev/pts/1
l-wx------ 1 elvis elvis 64 Sep 13 07:05 1 -> /tmp/foo
¿Qué sucede cuando elvis redirige tanto la entrada como la salida estándar?
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.
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.
A continuación, blondie emplea el comando sort para ordenar los animales que se
encuentran en el archivo de texto zoo.
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.
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".
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.
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.
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.
• 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 blondie@example.com, 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.
11
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.
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.
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.
G N U P L O T
Version 3.7 patchlevel 3
...
Después de salir de gnuplot vuelve a la shell bash, donde utiliza el visor de pantalla
eog para ver su diagrama.
Ejercicios en línea
Lab Exercise
Objetivo: Usar la redirección de la shell bash para controlar de modo efectivo la
14
Especificaciones
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]$ 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 colormap, non-
interlaced
[student@station student]$ eog gnuplot.png
15
Deliverables
Question 1
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 ...
... 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.
Conceptos clave
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.
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.
17
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.
En el siguiente ejemplo tanto > como 2> se utilizan para redirigir stdout y stderr de
modo independiente.
Sin embargo, tras examinar el archivo rcsummary.both, elvis no halla lo que espera.
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.
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.
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.
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.
20
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
Intrigado usa el comando find para buscar todos los archivos dentro del directorio /var
que posee.
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.
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
Especificaciones
Deliverables
Question 1
22
Capítulo 3 Tuberías
Conceptos clave
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.
/etc/gconf/gconf.xml.defaults/schemas/apps/tasklist_applet/prefs/%gcon
f.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.
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.
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.
/usr/share/doc/libxslt-1.0.27/html/libxslt-templates.html
/usr/share/doc/libxslt-1.0.27/templates.gif
/usr/share/doc/docbook-style-xsl-1.58.1/docsrc/templates.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".
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
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".
25
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?
Ejemplos
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.
Ahora localiza la línea de comandos que quería y utiliza la sustitución del historial para
repetir el comando con facilidad.
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.
...
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]: session 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 times
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.
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.
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.
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.
Ejercicios en línea
Lab Exercise
30
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
Limpieza