Você está na página 1de 571

Open Source University

RHEL4: Computing Essentials

Distribuye y comparte este libro


Copy/paste and edit by Maelwys

1
Quick Tour
Inicio de sesión

Conceptos clave

• En Linux, hay que comenzar las sesiones de usuario "iniciando la sesión" en la máquina.
• Para iniciar la sesión se debe contar de antemano con un nombre de usuario y una
contraseña.
• Si una máquina Linux se encuentra ejecutando en un servidor X, los usuarios pueden
iniciar la sesión utilizando la interfaz gráfica.
• Los usuarios pueden iniciar la sesión en cualquiera de las seis consolas virtuales.
• Las teclas CTRL-ALT-F1 hasta CTRL-ALT-F6 realizan el cambio entre las seis consolas
virtuales.
• Las teclas CTRL-ALT-F7 cambian al servidor X predeterminado.
• Si una máquina Linux lo soporta, los usuarios pueden iniciar la sesión en la red utilizando
una shell remota.
• El comando who enumera los usuarios que actualmente tienen una sesión activa y la
manera en que iniciaron la sesión.

Discusión

Inicio de Sesiones Linux

El sistema operativo Unix, desarrollado originalmente a principios de los años setenta, precede los
días de los computadores personales. Originalmente, muchos usuarios utilizarían Unix de manera
simultánea operando en un computador central. En vez de que cada usuario tuviese un
computador personal, utilizaban lo que se conoce comúnmente (hoy en día) como un"terminal
tonto" - apenas un teclado y un monitor de texto conectados al computador central con una
conexión serial. Para identificarse con el sistema operativo Unix, el usuario tenía que "iniciar
sesión" primero con un userid y su contraseña.

Aunque Linux (y otras versiones de Unix) han crecido para tomar ventaja de los computadores
personales al alcance de todos, no ha perdido los conceptos esenciales como los usuarios, las
contraseñas, el inicio de sesión y las terminales basadas en texto. Esta lección describirá muchas
de las formas para iniciar una sesión interactiva con un sistema Linux.

Consolas virtuales

Red Hat Enterprise Linux proporciona seis "consolas virtuales" disponibles para los usuarios que se
encuentran físicamente frente al computador. Las consolas virtuales actúan como "terminales
tontos". Para acceder a ellas se deben pulsar las teclas desde CTRL-ALT-F1 hasta CTRL-ALT-F6
con una consola virtual asociada a cada una de las primeras teclas de función (si se encuentra en
un entorno gráfico debe recordar que CTRL-ALT-F7, le llevará de regreso a esta consola antes de
intentar cambiar de consola virtual).

Al iniciar una sesión en una máquina Linux utilizando una consola virtual, la pantalla se verá así:

2
Red Hat Enterprise Linux ES release 4 (Nahant)
Kernel 2.6.9-5.EL on an i686

station login:

Para iniciar la sesión, el usuario digita su nombre de usuario sin espacios y pulsa la tecla INTRO.
Después se le pide que escriba la contraseña , la cual no aparece en la pantalla, y luego
pulsaINTRO. Iniciada la sesión, se recibe al usuario con un intérprete de comandos de la shell.

Red Hat Enterprise Linux ES release 4 (Nahant)


Kernel 2.6.9-5.EL on an i686

station login: elvis


Password:
[elvis@station elvis]$

La siguiente parte de este curso tratará de lo que se puede hacer desde el intérprete de comandos
o "prompt" . Por ahora sólo vamos a aprender a terminar una sesión escribiendo el comando "exit"
y pulsandoRETURN. La consola virtual debe regresar a la pantalla original de inicio de sesión.

¿Por qué los usuarios quieren utilizar una consola virtual en vez del entorno gráfico? Primero,
puede que la máquina no tenga suficiente memoria o hardware para soportar el entorno gráfico y
puede que todo lo que se encuentre disponible sean las consolas virtuales. Sin embargo, incluso
en las máquinas modernas, es muy frecuente que las consolas virtuales sean una interfaz más
rápida y más eficaz para los usuarios experimentados. Como son implementadas directamente por
el kernel de Linux, también son útiles en la reparación de sistemas en donde no estén funcionando
los gráficos. Por último, puesto que los servidores de red usualmente pasan la vida encerrados en
armarios, los administradores quieren a menudo evitar la complejidad que la interfaz gráfica le
añade al sistema.

El Entorno Gráfico X

Cuando Linux opera en computadores personales modernos, utiliza un programa de bajo nivel
conocido como el "servidor X" para proveer el entorno gráfico. Como usuario del sistema, usted no
interactúa directamente con el servidor X, sino que proporciona la base para todos los programas
gráficos que ejecuta.

Cuando el servidor X inicia, como parte de la secuencia de inicio del sistema, generalmente busca
la "primera" consola virtual disponible. Debido a que hay seis consolas virtuales para los terminales
de texto, el servidor X usualmente toma la séptima. Si se encuentra en una consola virtual y piensa
que hay un servidor X ejecutando en la máquina, usted puede cambiarse a ésta pulsando las teclas
CTRL-ALT-F7.

Si un sistema se encuentra configurado para arrancar en el entorno gráfico, entonces se le


presentará al usuario el Administrador de Inicio de Sesión, el cual se ve de la siguiente manera:

Figure 1. Administrador de Inicio de Sesión de Red Hat Enterprise Linux

3
De nuevo, un usuario inicia la sesión al escribir su nombre de usuario seguido de INTRO y su
contraseña seguida de INTRO.

Terminales en el entorno gráfico

El menú de aplicaciones en el entorno gráfico se encuentra en la esquina superior izquierda y sirve


como portal de entrada a una amplia variedad de aplicaciones gráficas, incluyendo navegadores,
editores de texto, editores de imágenes, juegos y mucho más. Aunque le alentamos a que explore
estas aplicaciones , comenzaremos este curso enfocándonos en los fundamentos de operación
dentro del entorno Linux tales como la administración de archivos y procesos. Por ahora, la
aplicación más importante para usted en el entorno gráfico es la terminal.

En Red Hat Enterprise Linux, la terminal comúnmente utilizada es la llamada gnome-terminal. Se


puede abrir una nueva ventana gnome-terminal haciendo click en el botón derecho del ratón
sobre el fondo del escritorio y seleccionando la primera opción del menú "Abrir una terminal".

Figure 1. Apertura de una gnome-terminal

Los usuarios experimentados de Linux con frecuencia prefieren la versatilidad y la potencia de la


interfaz de la línea de comandos en vez de las aplicaciones gráficas. De manera similar a una
consola virtual, el terminal proporciona una interfaz de línea de comandos de shell. Debido a que el
usuario ya ha iniciado sesión para poder arrancar en la sesión gráfica, no necesita iniciar otra vez
la sesión al abrir una nueva terminal.

Figure 2. gnome-terminal

Cuando termine puede cerrar la gnome-terminal escribiendo el comando exit (seguido de


INTRO), o haciendo click en el botón izquierdo de la "opción para cerrar" que se encuentra en la
esquina superior derecha de la terminal.

Salida del entorno gráfico

Cuando un usuario termina con el entorno gráfico, este puede salir seleccionando la última opción
del menú de Acciones que está justo a la derecha del menú de Aplicaciones. Esto cerrará todas las
ventanas y regresará el entorno gráfico a su pantalla de inicio original, listo para el siguiente
usuario.

Figure 1. Salida del entorno gráfico

Uso del comando who para determinar quién se encuentra en el sistema

Los usuarios pueden utilizar el comando who para determinar quién se encuentra en el sistema y
cómo iniciaron la sesión. Desde cualquier terminal los usuarios pueden escribir who y presionar la
tecla INTRO. Deben ver una salida similar a la siguiente:

[elvis@station elvis]$ who


elvis tty2 May 5 15:07
root tty1 May 3 07:50
blondie :0 May 5 08:48
blondie pts/0 May 5 09:03 (:0.0)

4
La primera columna lista los usuarios que han iniciado sesión y las últimas columnas establecen la
hora en que la iniciaron. Con un poco de experiencia, la segunda columna le dice el lugar en donde
el usuario inició la sesión. Para los primeros dos usuarios, elvis y root, tty1 y tty2 se refiere a las
consolas virtuales 1 y 2 respectivamente. La primera entrada para blondie, :0, se refiere al servidor
X mismo y pts/0 se refiere a la primera terminal abierta en el servidor X. Sin detenernos mucho en
los detalles, podemos ver que elvis ha iniciado sesión en la segunda consola virtual, root en la
primera y blondie ha iniciado sesión utilizando el entorno gráfico.

Inicio de sesión en una máquina a través de la red

Al utilizar la opción ssh ("secure shell"), los usuarios pueden iniciar una sesión fácilmente en
máquinas remotas ya sea en el mismo lugar o al otro lado del mundo. Asumiendo que la máquina
remota se encuentra configurada para permitir el inicio de sesión de manera remota y que el
usuario tiene una cuenta en la máquina, el iniciar una sesión en una máquina remota puede ser tan
fácil como iniciar una sesión en una consola virtual. En el siguiente ejemplo, elvis iniciará una
sesión en una consola virtual en la máquina local llamada station.redhat.com. Después utilizará
ssh para iniciar la sesión en una máquina remota nimbus.example.com, muy posiblemente al otro
lado del mundo.

Preste mucha atención al intérprete de comandos en el siguiente ejemplo. Como con frecuencia los
usuarios de Linux van "saltando" de máquina en máquina utilizando shells remotas, el intérprete de
comandos ha sido diseñado para ayudar al usuario a recordar en qué máquina está operando la
shell.

Red Hat Enterprise Linux ES release 4 (Nahant) (Taroon)


Kernel 2.4.21-4.0.1-EL on an i686

station login: elvis


Password:
Last login: Thu Apr 3 13:03:06 from hedwig
[elvis@station elvis]$ who
elvis tty2 May 3 07:48
[elvis@station elvis]$ ssh elvis@nimbus.example.com
elvis@nimbus.example.com's password:
Last login: Thu May 1 17:38:43 2003 from station.redhat.com
[elvis@nimbus elvis]$ who
elvis pts/1 May 3 11:59 (station.redhat.com)

[elvis@nimbus elvis]$ exit


Connection to nimbus.example.com closed.
[elvis@station elvis]$ exit

Observe que cuando elvis ejecutó el comando who en la máquina remota, ésta reportó la máquina
desde donde inició la sesión llamada station.redhat.com.

Hay clientes ssh para sistemas operativos diferentes de Linux. Por ejemplo, la aplicación Open
Source PuTTY se puede instalar en casi cualquier máquina windows y se puede utilizar para abrir
un intérprete de comandos en un servidor Linux remoto.

5
Ejemplos

Uso de consolas virtuales

En el siguiente ejemplo, un usuario inicia sesión en la primera consola virtual como el usuario elvis,
pero luego se da cuenta de que su sistema se encuentra mal configurado. Para poder arreglar
esto, va a cambiar a la segunda consola virtual e iniciará sesión como root y arreglará el problema.
Luego saldrá y regresará a la primera consola virtual listo para iniciar.

Red Hat Enterprise Linux ES release 4 (Nahant)


Kernel 2.6.9-5.EL on an i686
station login: elvis
Password:
Last login: Mon May 5 15:07:16 on tty2
[elvis@station elvis]$ cat /tmp/README
cat: /tmp/README: Permission denied
[elvis@station elvis]$ who
elvis tty1 May 5 15:54

En este momento, elvis ha tratado de leer el archivo /tmp/README, pero los permisos del archivo
no le permitieron hacerlo. Debido a que el usuario conoce la contraseña para la cuenta de root (del
administrador) en la máquina, puede arreglar el problema cambiándose a otra consola virtual
(utilizando las teclas CTRL-ALT-F2), iniciando sesión como root y cambiando los permisos del
archivo.

Red Hat Enterprise Linux ES release 4 (Nahant) (Taroon)


Kernel 2.4.21-4.0.1-EL on an i686
station login: root
Password:
Last login: Mon May 5 15:54:18 on tty6
[root@station root]# who
root tty2 May 5 15:55
elvis tty1 May 5 15:54
[root@station root]# chmod go+r /tmp/README
[root@station root]# exit

Observe que la salida del comando who muestra que el usuario inició sesión como elvis en la
primera consola virtual e inició sesión como root en la segunda. El usuario ahora cambia de vuelta
a la primera consola virtual utilizando CTRL-ALT-F1 y reanuda la sesión.

[elvis@station elvis]$ cat /tmp/README


Kudzu FAQ:
----------
1) So, what is kudzu?
kudzu is the hardware autodetection & configuration tool, originally
introduced in Red Hat Linux 6.1. It detects changes in the system's
hardware configuration, and gives the option of configuring
...

6
El kernel, los programas y los procesos

Conceptos clave

• El kernel de Linux es un sistema operativo que proporciona un entorno para la ejecución de


procesos.
• Los programas son archivos ejecutables (usualmente binarios) que se encuentran en un
sistema de archivos.
• Un proceso es una instancia de un programa en ejecución.
• Una shell es un proceso interactivo que permite al usuario specificar otros procesos a
ejecutar.
• Aunque Red Hat Enterprise Linux se entrega con diferentes versiones de shells, la shell
predeterminada es un programa llamado bash.
• El comando ps lista los procesos iniciados desde una terminal individual. El comando ps
aux le da una lista detallada de todos los procesos operando actualmente en una máquina.

Discussion

El kernel de Linux

El kernel de Linux es un sistema operativo así como Windows, MacOS y OS/2. El sistema
operativo es un entorno en el cual se ejecuta un programa. proporcionándole los mecanismos a los
programas para interactuar con el hardware del computador. El kernel le permite saber a un
programa cuándo se pulsa una tecla, cuándo se mueve el ratón o cuándo llegó un paquete
destinado para el programa a través de la red . El kernel le permite a los programas acceder al
disco duro, quizás para leer los archivos de configuración o almacenar datos.

Así como sería difícil explicar lo que es un lenguaje a una persona que ha crecido con el
conocimiento de un solo idioma, con frecuencia es difícil explicar lo que es un sistema operativo a
aquellas personas nuevas en el área de los computadores o a aquellos que solamente han
utilizado un sistema operativo. El sistema operativo funciona en un nivel tan bajo que los usuarios
no interactúan con éste directamente y a menudo no se dan cuenta de que los programas que se
encuentran ejecutando lo están utilizando.

Figure 1. El kernel y los procesos

Los programas

Los programas son archivos almacenados en el disco duro de un computador. Un programa es una
serie de instrucciones básicas que le indican al sistema operativo qué hacer y cuándo hacerlo de
una manera bastante detallada y específica. Las siguientes pueden ser las instrucciones escritas
en el archivo /usr/X11R6/bin/xcalc, un programa común de calculadora.

7
"Mientras que el usuario no esté haciendo nada, el cursor titila. Cuando el usuario pulsa una tecla,
si es un número, lo escribe en la pantalla. Si no es un número lo ignora, a menos que sea la tecla
intro. Si es la tecla intro, añade el número anterior al total y muestra el total."

Claro está que las instrucciones no se encuentran en inglés ni en ningún otro lenguaje humano. En
cambio, un computador en el nivel más bajo sólo sabe cómo realizar un pequeño número de
tareas, digamos 256 de ellas. Imagine que cada una de esas tareas estuviesen numeradas de 0 a
255. Los programas se ven en realidad más como las siguientes instrucciones:

"Realice la tarea 23. Si el resultado es mayor que 0, entonces haga la tarea 45. De otra forma,
complete la tarea 82. Tome el resultado y almacénelo en la memoria."

Debido a que las tareas que un computador puede llevar a cabo varían dependiendo del tipo de
CPU, y que diferentes sistemas operativos podrían listar las tareas de forma diferente, los
programas compilados para un tipo de sistema operativo, por lo general, no ejecutarán en otros
sistemas operativos.

Los procesos

Cuando un usuario le pide al kernel que ejecute un programa, el kernel lee las instrucciones que se
encuentran en el el archivo del programa y las carga en la memoria. Después empieza a llevar a
cabo las instrucciones . La copia del programa ejecutando en la memoria se denomina un proceso.
Observe que el mismo programa se puede cargar en la memoria y se puede ejecutar más de una
vez para que en cualquier momento el kernel pueda ejecutar varios procesos del mismo programa.

Linux, como la mayoría de sistemas operativos modernos, es un sistema operativo de funciones


múltiples. Esto significa que el kernel parece estar ejecutando múltiples procesos de manera
simultánea. En realidad, el kernel se encuentra ejecutando un sólo proceso por un breve periodo
de tiempo, usualmente alrededor de 50 milisegundos. Luego intercambia ese proceso por otro con
sus 50 milisegundos de acción. Finalmente, el kernel termina todos los procesos y comienza de
nuevo. El rápido cambio de proceso a proceso le da la impresión a los usuarios de la máquina de
que todos los procesos se están ejecutando simultáneamente.

Las shells

Los usuarios de Linux con frecuencia utilizan un tipo especial de programa llamado shell para
interactuar con el kernel. La shell ejecuta dentro de una terminal emitiendo un "prompt"y esperando
a que le digan qué hacer. Luego, el usuario le pide a la shell que ejecute un programa escribiendo
el nombre del programa. En el siguiente ejemplo, el usuario elvis le pide a la shell que ejecute un
programa sencillo de calendario llamado cal. La shell ejecuta obedientemente el programa y
reporta la salida del programa a la terminal:

[elvis@station elvis]$ cal


May 2003
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17

8
18 19 20 21 22 23 24
25 26 27 28 29 30 31

[elvis@station elvis]$

Debido a que los usuarios utilizan una shell para llevar a cabo casi todas las tareas en el sistema,
la shell es un programa importante y sofisticado. Gran parte de este curso se dedicará a aprender a
utilizar la shell para realizar tareas de manera efectiva.

Cuando el usuario le pide a la shell que ejecute un programa, se dice que el usuario está
especificando un comando para la shell. Con frecuencia la shell se conoce como la interfaz de
línea de comandos.

El comando ps

El comando ps se utiliza comúnmente para enumerar los procesos ejecutándose en un sistema. El


comando ps, sin ningún argumento, muestra todos los procesos que se iniciaron desde una sola
terminal (o una terminal en un entorno gráfico). En el siguiente ejemplo, elvis descubre que
actualmente su terminal tiene dos procesos en ejecución: su shell bash y el comando mismo ps.

[elvis@station elvis]$ ps
PID TTY TIME CMD
1378 pts/1 00:00:00 bash
1418 pts/1 00:00:00 ps

La primera columna muestra el id del proceso (PID del inglés Process ID). Todo proceso
ejecutándose en el sistema se identifica con un ID de proceso único. La segunda columna identifica
la terminal de elvis y la tercera reporta el tiempo de CPU que el proceso ha utilizado.

El comando ps aux muestra una lista detallada de todos los procesos ejecutándose en el sistema.
Por ahora no explicaremos lo que significa "aux", sólo piense que es como un acto de magia negra
que debe memorizar. Tampoco le explicaremos todos los campos, todo esto se discutirá en el
siguiente cuaderno. Simplemente observe que en cualquier momento hay, por lo general, un gran
número de procesos ejecutándose en un sistema Linux (note que en la siguiente salida se han
eliminado bastantes líneas y se han reemplazado con "...").

9
[elvis@station elvis]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 1388 460 ? S 18:52 0:04 init [
root 2 0.0 0.0 0 0 ? SW 18:52 0:00 [keventd]
...
root 548 0.0 0.2 1460 580 ? S 18:53 0:00 syslogd -m 0
root 552 0.0 0.1 1384 428 ? S 18:53 0:00 klogd -x
rpc 570 0.0 0.2 1560 552 ? S 18:53 0:00 portmap
root 622 0.0 0.2 1496 632 ? S 18:53 0:00 /sbin/cardmgr
root 628 0.0 0.0 0 0 ? SW 18:53 0:00 [kapmd]
root 633 0.0 0.1 1380 484 ? S 18:53 0:00 /usr/sbin/apmd -p
root 644 0.0 0.5 3524 1512 ? S 18:53 0:00 /usr/sbin/sshd
root 655 0.0 0.3 2040 860 ? S 18:53 0:00 xinetd -stayalive
root 674 0.0 0.9 6204 2504 ? S 18:53 0:00 sendmail: accepti
smmsp 683 0.0 0.8 6004 2256 ? S 18:53 0:00 sendmail: Queue r
root 693 0.0 0.1 1424 444 ? S 18:53 0:00 gpm -t ps/2 -m /d
root 702 0.0 0.2 1580 672 ? S 18:53 0:00 crond
xfs 781 0.0 1.5 5272 4004 ? S 18:53 0:00 xfs -droppriv -da
root 800 0.0 0.2 3416 544 ? S 18:53 0:00 rhnsd --interval
root 807 0.0 0.1 1364 396 tty1 S 18:53 0:00 /sbin/mingetty tt
...
root 1375 0.0 0.3 4120 968 pts/1 S 20:11 0:00 su - elvis
elvis 1378 0.0 0.5 4324 1404 pts/1 S 20:11 0:00 -bash
elvis 1438 0.0 0.2 2648 696 pts/1 R 20:30 0:00 ps aux

El sistema de archivos

Conceptos clave

• La base del árbol de directorios de Linux es un directorio llamado / y conocido como el"
directorio root".
• Las referencias absolutas de archivos, tales como /home/elvis/lsout.txt, se refieren a los
archivos relativos al directorio raíz.
• Las referencias relativas de archivo, tales como lsout.txt, hacen referencia a archivos
relativos al directorio de trabajo actual de un proceso.
• El comando ls se utiliza para enumerar el contenido de un directorio.
• El comando cat se utiliza para examinar el contenido de un archivo.
• Al utilizar el caracter > desde la línea de comandos de la shell, la salida de un comando
puede redireccionarse desde la terminal a un archivo.
• El directorio home es uno de los pocos lugares en donde los usuarios pueden crear
archivos nuevos.

Discusión

Dar nombres a archivos y directorios

En Linux,la información y los programas se encuentran almacenados en discos como archivos. Los
archivos se encuentran agrupados en los directorios, los cuales pueden contener archivos y otros
directorios (otros sistemas operativos con frecuencia se refieren a directorios como "carpetas").

10
Esta jerarquía de directorios que contienen directorios se conoce a menudo como el "árbol de
directorios".

La base del árbol de directorios es un directorio llamado simplemente / y se conoce como "el
directorio raíz". Los archivos dentro del directorio raíz se conocen como /nombre del archivo. En
Red Hat Enterprise Linux, el directorio raíz contiene principalmente otros directorios tales como
/etc. Los archivos dentro de estos subdirectorios se conocen como /etc/nombre del archivo y el
proceso continúa así para cada nuevo nivel de subdirectorios. Por ejemplo, el archivo network que
se encuentra en el directorio sysconfig, que a su vez se encuentra en el directorio etc, el cual está
en el directorio root /, puede conocerse como /etc/sysconfig/network.

Obviamente, el iniciar en el directorio raíz cada vez que se refiera a un archivo es bastante trabajo.
Afortunadamente, Linux proporciona una manera más fácil. Todo proceso, incluyendo la shell de un
usuario, utiliza un "directorio actual de trabajo" por contexto. Los archivos en un directorio actual de
trabajo se conocen simplemente como nombre de archivo, sin la barra oblicua inicial. Los archivos
en los subdirectorios del directorio actual de trabajo se conocen como nombre del
directorio/nombre del arhivo, de nuevo sin la barra oblicua inicial. Por ejemplo, si el directorio actual
de trabajo de un proceso fuese /etc, el archivo network mencionado anteriormente se conocería
como sysconfig/network. Si el directorio de trabajo fuese /etc/sysconfig entonces el archivo podría
ser simplemente network.

En resumen, siempre hay dos maneras de referirse a un archivo. Las referencias de archivo
relativas al directorio raíz, siempre comienzan con una barra oblicua inicial / y se llaman referencias
absolutas absolute. Las referencias de un archivo relativas al directorio de trabajo actual
comienzan con cualquier cosa que no sea una / y se conocen como referencias relativas.

Listado del contenido de un directorio con ls

Desde una shell los usuarios pueden utilizar el comando ls para hacer un listado del contenido de
un directorio (imagínese que ls es la forma corta para la palabra "lista"). En el siguiente ejemplo, el
usuario elvis quiere hacer una lista del contenido del directorio /etc/sysconfig/rhn.

[elvis@station elvis]$ ls /etc/sysconfig/rhn


rhn-applet systemid up2date-keyring.gpg up2date-uuid
rhnsd up2date up2date.rpmnew

El comando ls, cuando se emite sin ningún argumento (por ejemplo, sin especificar un directorio)
lista el contenido del directorio de trabajo actual de la shell. Si utiliza una terminal con colores,el
comando ls también le pone color a los nombres de los directorios para ayudar a distinguir el
contenido de los directorios que tienen archivos comunes (en blanco) y los que son directorios (en
azul).

El ls es un comando muy flexible que puede proporcionar mucha información. Este se estudiará en
más detalle en lecciones posteriores.

Ver el contenido de un archivo con cat

Mientras el comando ls lista los archivos que se encuentran en un directorio dado, éste no revela el
contenido de los archivos. Aunque hay varios comandos disponibles para ver los archivos, el
comando más sencillo es cat. Cuando se le da una lista de archivos al comando cat este
concatena los archivos a la salida del terminal. Si sólo se le da el nombre de un archivo entonces
mostrará el contenido de solo ese archivo.

11
En el siguiente ejemplo, el usuario elvis quiere ver el contenido del archivo de configuración
/etc/hosts.

[elvis@station elvis]$ cat /etc/hosts


# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost
192.168.0.254 server1.example.com server1
192.168.0.1 station1.example.com station1

Por ahora, no se preocupe de lo que significa el contenido, sólo tenga en cuenta que el comando
cat presenta todo el contenido de este archivo de cinco líneas.

Observe que si le pide a cat que presente un archivo muy largo o un archivo binario (no texto), cat
lo hará obedientemente. Hay comandos más sofisticados para ver archivos largos, una pantalla a
la vez, lo cual se verá más adelante.

Redireccionamiento de salidas de los comandos a archivos

Cuando los comandos ls y cat se ejecutan su salida se presenta en la terminal. En Linux, la


mayoría de los comandos que generan texto en la salida utilizan un concepto común de Unix
denominado "salida estándar". Por defecto se encuentra conectado a la terminal. La shell bash
permite a los usuarios "redireccionar" la salida estándar a otros lugares. Por ahora, vamos a
aprender el caso más fácil: la utilización del caracter > para redireccionar la salida estándar a un
archivo.

En el siguiente ejemplo, el usuario elvis de nuevo va a hacer una lista del contenido del directorio
/etc/sysconfig/rhn, pero quiere redireccionar la salida a un archivo recién creado.

[elvis@station elvis]$ ls /etc/sysconfig/rhn > lsout.txt


[elvis@station elvis]$ ls
lsout.txt
[elvis@station elvis]$ cat lsout.txt
rhn-applet
rhnsd
systemid
up2date
up2date-keyring.gpg
up2date.rpmnew
up2date-uuid

La salida del comando ls /etc/sysconfig/rhn no se mostró en la terminal sino que se introduce en


el archivo recién creado lsout.txt. Despúes elvis toma el comando ls de su directorio de trabajo
actual y ve el archivo recién creado. Después utiliza el comando cat para observar el contenido del
archivo. En "lenguage Unix" elvis "redireccionó la salida del comando ls al archivo lsout.txt".

Permisos y el directorio de inicio de un usuario

Observe lo que pasa cuando elvis trata de redireccionar la salida a un archivo que se encuentra en
un lugar diferente al directorio actual de trabajo de la shell.

12
[elvis@station elvis]$ ls /etc/sysconfig/rhn > /etc/lsout.txt
-bash: /etc/lsout.txt: No such file or directory

El usuario elvis se ha encontrado con otro concepto común en Linux: propiedad y permisos de un
archivo. El usuario elvis trató de crear el nuevo archivo /etc/lsout.txt, pero elvis no tiene el permiso
para crear archivos en el directorio /etc.

Por defecto, en Red Hat Enterprise Linux, los usuarios no pueden crear archivos en cualquier lugar.
De hecho, sólo hay unos pocos lugares en donde se pueden crear archivos. Todo usuario tiene un
directorio de inicio, en donde puede crear nuevos archivos (y nuevos subdirectorios).
Afortunadamente, cuando los usuarios inician una sesión en Linux, su shell utiliza su directorio
inicial como su directorio actual de trabajo. Por defecto en Red Hat Enterprise Linux, el directorio
inicial de un usuario se llama /home/username, dondeusername se reempla con el nombre del
nombre del usuario.

Otros cuaderno abordarán el sistema de archivos y los permisos en mucho más detalle. Por ahora,
sólo tenga en cuenta que a los usuarios, generalmente, sólo se les permite crear archivos en su
directorio de inicio.

Ejemplos

Redirección de la salida de un comando a un archivo

El usuario prince quiere utilizar el comando cal para almacenar un calendario del mes actual en el
archivo calendar.txt.

[prince@station prince]$ cal


May 2003
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

[prince@station prince]$ cal > calendar.txt

[prince@station prince]$ ls
calendar.txt

[prince@station prince]$ cat calendar.txt


May 2003
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

13
prince primero ve la salida del comando cal directamente.

prince ejecuta otra vez el comando cal redireccionando la salida al archivo calendar.txt

prince confirma que el nuevo archivo ha sido creado listando el contenido de su directorio de
trabajo actual (en este caso su directorio de inicio).

prince examina el contenido del nuevo archivo para confirmar que contiene la salida del comando
cal.

Ejecución de comandos

Conceptos clave

• Como cualquier otro idioma la shell bash utiliza una gramática específica.
• La primera palabra en cualquier línea de comandos es el nombre del programa que se va a
ejecutar.
• El comportamiento de los comandos se puede modificar con las opciones de la línea de
comandos (usualmente opcional), las cuales siempre empiezan con uno o dos guiones (- o
--).
• Las palabras u opciones que siguen después del comando se llaman argumentos del
comando arguments
• Algunas opciones de la línea de comandos también toman argumentos.
• Los comandos usualmente soportan las opciones --help, -h o -?, las cuales presentan un
resumen de cómo utilizar el comando.

Discussion

Gramática de la línea de comandos

Aunque la interfaz de la línea de comandos tiene muchas ventajas, incluyendo la eficiencia y la


flexibilidad, la simplicidad no es una de ellas. Afortunadamente, existen convenciones que (casi)
todos los programas siguen. Aprender nuevos programas será mucho más fácil si toma un poco de
tiempo para aprender estas convenciones.

Si los comandos que se introducen en la línea de comandos se comparan con las oraciones en
inglés entonces los comandos tienen verbos, adverbios y objetos directos. El verbo es el comando
a ejecutar, los adverbios son las diferentes opciones que se pueden utilizar para modificar el
comportamiento del comando (“calmadamente” o “con fluidez”) y las palabras que quedan son los
objetos directos (sobre lo que el comando debe actuar). Además, así como en los idiomas, hay
irregularidades y para casi toda regla mencionada habrá excepciones.

Comandos

La primera palabra en cualquier comando es generalmente el nombre de un programa que vive


como archivo en algún lugar del sistema de archivos. [1] Por ejemplo, la lección anterior utilizó los
comandos ps y who. Si queremos saber qué archivo contiene estos programas, hay un programa
llamado which que nos puede ayudar. El comando which seguido del nombre de otro comando le
dirá "qué" archivo se está ejecutando.

[elvis@station elvis]$ which ps


/bin/ps
[elvis@station elvis]$ which who

14
/usr/bin/who

Cuando se ejecuta un comando, el proceso de la shell le pide al kernel que ejecute el programa
especificado como un proceso separado y hace que la salida (o mejor, la salida estándar) del
proceso se escriba en la terminal. Entonces la shell realiza una pausa hasta que el proceso del
comando termina. Una vez el comando termina, la shell presenta otro intérprete de comandos y
espera a que se le diga que hacer.

Opciones de la línea de comandos

Se puede modificar el comportamiento de muchos de los comandos especificando las diferentes


opciones de la línea de comandos. Un ejemplo fácil es el comando ls utilizado para listar el
contenido de un directorio. Considere los siguientes tres usos del comando ls cada vez que lista
los archivos en el directorio /usr:

[elvis@station elvis]$ ls /usr


bin etc include lib local share tmp
dict games kerberos libexec sbin src X11R6
[elvis@station elvis]$ ls -s /usr
total 132
40 bin 4 games 40 lib 8 sbin 0 tmp
4 dict 8 include 4 libexec 8 share 4 X11R6
4 etc 4 kerberos 0 local 4 src
[elvis@station elvis]$ ls -l /usr
total 132
drwxr-xr-x 2 root root 40960 Apr 25 06:36 bin
drwxr-xr-x 2 root root 4096 Jan 24 18:52 dict
drwxr-xr-x 2 root root 4096 Jan 24 18:52 etc
drwxr-xr-x 4 root root 4096 Jan 24 18:52 games
drwxr-xr-x 100 root root 8192 Apr 11 05:55 include
drwxr-xr-x 8 root root 4096 Mar 31 21:52 kerberos
drwxr-xr-x 90 root root 40960 Apr 25 06:36 lib
drwxr-xr-x 10 root root 4096 Apr 11 05:51 libexec
lrwxrwxrwx 1 root root 14 Sep 13 2002 local -> ../home/local/
drwxr-xr-x 2 root root 8192 Apr 25 06:36 sbin
drwxr-xr-x 212 root root 8192 Apr 23 16:30 share
drwxrwxr-x 5 root pst 4096 Apr 25 08:12 src
lrwxrwxrwx 1 root root 10 Apr 1 11:07 tmp -> ../var/tmp
drwxr-xr-x 8 root root 4096 Jan 24 18:52 X11R6

El primer comando ls simplemente hace una lista del contenido del directorio. El segundo comando
ls -s, el cual incluye la opción -s, presenta también el tamaño del contenido también. El tercer
comando ls -l presenta una lista "larga", incluyendo todo tipo de detalles sobre los archivos tales
como los permisos, propiedad y la fecha de modificación. Por ahora, no se preocupe de los detalles
en la salida, ésto se abarcará en un cuaderno posterior sobre la utilización del sistema de archivos.
Sólo observe cómo se utilizan las opciones de la línea de comandos para modificar el
comportamiento básico del comando ls.

Opciones cortas de la línea de comandos

Observe que las dos opciones que se utilizaron anteriormente -s y -l son opciones de una sola
letra. Estas se conocen como opciones "cortas" de la línea de comandos. A veces estas opciones

15
cortas también pueden tener un argumento. Por ejemplo, el comando ls tiene la opción -w, la cual
especifica la "extensión", de la salida en caracteres. Considere el siguiente ejemplo:

[elvis@station elvis]$ ls -w 40 /usr/


bin games lib sbin tmp
dict include libexec share X11R6
etc kerberos local src

En este caso, la palabra 40 no se considera un argumento del comando ls sino que es un


argumento de la opción del comando -w (¿Qué tan extensa debe ser la salida? 40 caracteres). Los
argumentos de las opciones simplemente siguen la opción de la línea de comandos. ¿Cómo se
sabe cuales opciones tienen argumentos y cuales no? La respuesta corta es por experiencia, pero
pronto mencionaremos formas de encontrar ayuda también.

Múltiples opciones cortas de la línea de comandos

Se puede utilizar más de una opción de la línea de comandos a la vez. Las múltiples opciones
simplemente se ponen juntas entre el comando y el argumento. El siguiente ejemplo presenta una
nueva opción -r para el comando ls, el cual invierte el orden de búsqueda. Observe cómo se utiliza
junto con las opciones -s y -w.

[elvis@station elvis]$ ls -s -w 40 -r /usr/


total 132
4 X11R6 0 local 4 games
0 tmp 4 libexec 4 etc
4 src 40 lib 4 dict
8 share 4 kerberos 40 bin
8 sbin 8 include

Con frecuencia, cuando se utilizan múltiples opciones, los usuarios tomarán ventaja del atajo que
les permite poner todas las opciones juntas con un sólo guión (-), como en el siguiente ejemplo:

[elvis@station elvis]$ ls -srw 40 /usr/


total 132
4 X11R6 0 local 4 games
0 tmp 4 libexec 4 etc
4 src 40 lib 4 dict
8 share 4 kerberos 40 bin
8 sbin 8 include

Todas las opciones con letras individuales que no tienen argumento, en este caso -s y -r, se
pueden poner juntas compartiendo un solo -. Si una opción sí tiene argumento tal como -w 40, sólo
puede compartir un guión si está de última. De esta manera, se puede especificar el argumento
justo al lado de la línea de comandos.

Opciones largas de la línea de comandos

En los primeros días de Unix, todas las opciones de la línea de comandos compartían la sintaxis
mencionada anteriormente. Con la evolución de Unix, la gente empezó a necesitar lo que se
conoce como opciones "largas". A diferencia de las opciones con sólo una letra, las opciones
largas están compuestas de palabras. En vez de empezar con un guión inicial, las opciones largas

16
están precedidas de dos guiones (--). Algunos comandos utilizan sólo opciones cortas y algunos
comandos utilizan opciones largas. Muchos comandos, incluyendo ls, manejan ambos.

[elvis@station elvis]$ ls --size /usr/


total 132
40 bin 4 games 40 lib 8 sbin 0 tmp
4 dict 8 include 4 libexec 8 share 4 X11R6
4 etc 4 kerberos 0 local 4 src

Cuando las opciones largas tienen un argumento, la sintaxis también difiere un poco. En vez de
que el argumento siga la opción como una palabra separada, el argumento se pone junto con la
opción larga separada por un =, como en --width=40. Observe que las opciones tanto largas como
cortas, también se pueden mezclar.

[elvis@station elvis]$ ls --width=40 --size -r /usr/


total 132
4 X11R6 0 local 4 games
0 tmp 4 libexec 4 etc
4 src 40 lib 4 dict
8 share 4 kerberos 40 bin
8 sbin 8 include

Argumentos

Comparados con las opciones de la línea de comandos, los argumentos son fáciles. Cualquier
palabra que quede en la línea de comandos, después del nombre del comando y después de
cualquier opción de la línea de comandos se le denomina argumentos del comando. Lo que el
comando espera o no como argumento depende del comando. Por ejemplo, si se le da algún
argumento al comando ls el comando tratará los argumentos como archivos o directorios a
enumerar. El comando ps no espera ningún argumento. El comando cal toma de cero a dos, un
mes y un año posibles para poder generar el calendario. El aprender qué argumentos espera un
programa y lo que hace con estos es parte del aprender a utilizar ese comando.

Ayuda: uso

¿Cómo recordar todas estas opciones de la línea de comandos? No es necesario. No obstante, los
usuarios experimentados de Linux han aprendido a refrescar fácilmente su memoria ya que la
mayoría de los comandos soportan la opción --help o las opciones cortas -h o -?. Estas opciones
usualmente hacen que el comando emita un mensaje de "uso" en vez de realizar su operación
normal. Este mensaje de uso contiene un resumen de los argumentos que se esperan, las
opciones que se soportan y lo que hacen. Observe que el mensaje de uso generado por el
comando ls es bastante largo y ha sido abreviado en la siguiente salida.

[elvis@station elvis]$ ls --help

Usage: ls [OPTION]... [FILE]...


List information about the FILEs (the current directory by default).

Sort entries alphabetically if none of -cftuSUX nor --sort.

17
Mandatory arguments to long options are mandatory for short options too.
-a, --all do not hide entries starting with .
-A, --almost-all do not list implied . and ..
--author print the author of each file
-b, --escape print octal escapes for non-graphic characters

...

-k like --block-size=1K
-l use a long listing format

...

-r, --reverse reverse order while sorting


-R, --recursive list subdirectories recursively

-s, --size print size of each file, in blocks

...

-v sort by version

-w, --width=COLS assume screen width instead of current value


-x list entries by lines instead of by columns

...

Algunos detalles que se deben observar en el mensaje de uso:

Los elementos opcionales se encuentran entre corchetes ([ y ]).


Aquí, el mensaje de uso se refiere a las opciones cortas utilizando la forma abreviada.
Observe que ls soporta tanto las formas cortas (-s) como largas (--size) de esta opción.
Aquí está la opción -w o --width, las cuales requieren un argumento.

Los mensajes de uso no proporcionan una referencia completa para el comando, sino que
simplemente proporcionan información para refrescar la memoria. Más adelante en este cuaderno
se discutirán otras formas de encontrar ayuda.

18
Ejemplos

Aprender a utilizar el comando cat

Una amiga del usuario madonna le dijo que el comando cat se utiliza para mirar el contenido de los
archivos. Ella nunca ha utilizado este comando antes y está interesada en aprender a utilizarlo.
Entonces, empieza por examinar el mensaje de uso del comando.

[madonna@station madonna]$ cat --help


Usage: cat [OPTION] [FILE]...
Concatenate FILE(s), or standard input, to standard output.

-A, --show-all equivalent to -vET


-b, --number-nonblank number nonblank output lines
-e equivalent to -vE
-E, --show-ends display $ at end of each line
-n, --number number all output lines
-s, --squeeze-blank never more than one single blank line
-t equivalent to -vT
-T, --show-tabs display TAB characters as ^I
-u (ignored)
-v, --show-nonprinting use ^ and M- notation, except for LFD and TAB
--help display this help and exit
--version output version information and exit

With no FILE, or when FILE is -, read standard input.

Report bugs to <bug-coreutils@gnu.org>.

Todavía no entiende todo el mensaje de uso, como por ejemplo, las referencias a la entrada y a la
salida estándar, pero puede entender lo suficiente de la primera línea como para comprender que
el comando cat espera los nombres de archivo como su argumento. Intenta mostrar el contenido
del archivo /etc/anacrontab.

[madonna@station madonna]$ cat /etc/anacrontab


# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

1 65 cron.daily run-parts /etc/cron.daily


7 70 cron.weekly run-parts /etc/cron.weekly
30 75 cron.monthly run-parts /etc/cron.monthly

Al ver algunas de las opciones de los mensajes de uso observa que la opción -n numera las líneas
de salida y decide probar esta opción:

19
[madonna@station madonna]$ cat -n /etc/anacrontab
1 # /etc/anacrontab: configuration file for anacron
2
3 # See anacron(8) and anacrontab(5) for details.
4
5 SHELL=/bin/sh
6 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
7
8 1 65 cron.daily run-parts /etc/cron.daily
9 7 70 cron.weekly run-parts
/etc/cron.weekly
10 30 75 cron.monthly run-parts
/etc/cron.monthly
4 X11R6 0 local 4 games
0 tmp 4 libexec 4 etc
4 src 40 lib 4 dict
8 share 4 kerberos 40 bin
8 sbin 8 include

Desde la salida ahora es fácil ver que este archivo tiene 10 líneas y es fácil referirse a la línea 6.
Sospecha que el espacio que hay entre las palabras desde el renglón 8 hasta el 10 son efecto del
tabulador en vez del espaciador. Al observar del mensaje de uso que la opción -t reemplazará
cualquier espacio del tabulador con ^I, intenta confirmar su sospecha.

[madonna@station madonna]$ cat -t /etc/anacrontab


# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

1^I65^Icron.daily^I^Irun-parts /etc/cron.daily
7^I70^Icron.weekly^I^Irun-parts /etc/cron.weekly
30^I75^Icron.monthly^I^Irun-parts /etc/cron.monthly

Ahora observa que el uso de la opción -A es "equivalente a -vET", el cual ella asume que es el
atajo de la opción corta -v, -E y -T. Prueba ambos para ver si está en lo correcto.

[madonna@station madonna]$ cat -A /etc/anacrontab


# /etc/anacrontab: configuration file for anacron$
$
# See anacron(8) and anacrontab(5) for details.$
$
SHELL=/bin/sh$
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin$
$
1^I65^Icron.daily^I^Irun-parts /etc/cron.daily$
7^I70^Icron.weekly^I^Irun-parts /etc/cron.weekly$
30^I75^Icron.monthly^I^Irun-parts /etc/cron.monthly$
[madonna@station madonna]$ cat -vET /etc/anacrontab
# /etc/anacrontab: configuration file for anacron$
$

20
# See anacron(8) and anacrontab(5) for details.$
$
SHELL=/bin/sh$
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin$
$
1^I65^Icron.daily^I^Irun-parts /etc/cron.daily$
7^I70^Icron.weekly^I^Irun-parts /etc/cron.weekly$
30^I75^Icron.monthly^I^Irun-parts /etc/cron.monthly$

Al ver que las salidas son idénticas, decide que ha interpretado correctamente el mensaje de uso.

Administración de terminales

Conceptos clave

• Varias secuencias de control tales como CTRL-C, CTRL-D y CTRL-Z pueden ser útiles
para administrar procesos desde la terminal.
• La configuración de una terminal puede ser devuelta a su estado inicial con el comando
reset.
• La shell bash ofrece la oportunidad de completar con el tabulador, la cual le puede ahorrar
bastante tiempo al escribir especificando comandos o archivos.
• Se pueden distinguir varios tipos de terminales al saber cómo se refiere Linux a los
dispositivos.

Discussion

Control de terminales

La shell bash y el terminal en que ejecuta son las herramientas principales que los usuarios
experimentados de Linux utilizan. Más adelante en este curso se dedicará un cuaderno completo a
la manera de utilizar las potentes características de la shell de bash. Esta lección introduce
algunas carcterísticas que las terminales comparten en general y una de ellas que no debería
dejarse para más tarde: el completar con el tabulador.

Reinicio de terminales

Cuando las terminales presentan información, muestran un byte a la vez. Cuando los
computadores manejan texto humano, los caracteres usualmente se encuentran codificados como
un valor de bytes en números enteros utilizando el formato ASCII. Mientras que un byte puede
codificar hasta 256 valores diferentes, sólo se utiliza un pequeño número de éstos (alrededor de
100) para caracteres de texto y puntuación. Los otros se utilizan para codificar secuencias de
control (vea a continuación) y otras condiciones especiales.

A veces los usuarios accidentalmente (o intencionalmente) le piden a una terminal que presente
datos no codificados como texto ASCII, como por ejemplo, una imagen o un ejecutable. La terminal
hace lo mejor que puede, pero con frecuencia presenta lo que parecen ser simplemente garabatos.
Incluso la terminal puede terminar en un modo alterno de gráficos para que inclusive se vea mal lo
que se debe ver como texto ASCII normal.

En estas situaciones, el comando reset puede restablecer la terminal a una conducta cuerda.
Usualmente, cuando quiere utilizar este comando ni siquiera podrá ver al escribirlo. Sin embargo, si

21
tiene un intérprete de comandos bash con caracteres incomprensibles, al escribir reset seguido de
la tecla INTRO usualmente la terminal se restaurará a una conducta cuerda.

Secuencias de control de la terminal

Los terminales Linux comparten bastante con sus ancestros primitivos, los teletipos y las consolas
"tontas" o las similares a vt100. Estos dispositivos tenían mecanismos para enviar señales "fuera
de banda" o secuencias que señalaban un evento fuera del flujo normal de caracteres escritos
tales como un espacio, una campanilla audible o un final de transmisión. Las terminales de Linux,
como sus predecesores, utilizan la tecla CTRL para enviar esas señales "fuera de banda".

La siguiente tabla resume muchas de las secuencias de control utilizadas con frecuencia que todos
los terminales Linux comparten y su uso común en orden alfabético. Después de la tabla se
discuten estas secuencias de acuerdo con su utilidad en general.

Table 1. Secuencias de control de la terminal Linux

Combinación de Nombre Uso


teclas simbólico
CTRL-C SIGINT Interrupción anormal - termina el proceso en el primer plano
CTRL-D EOT Señalamiento normal del final de la entrada
CTRL-G BEL Hacer sonar una campana audible en la terminal
CTRL-H BS Tecla de retroceso- borra el caracter anterior
CTRL-J LF Introducir una línea - es una alternativa para la tecla
RETURN
CTRL-L FF Form feed-Hace que bash limpie la pantalla y que otros
programas basados en la pantalla "refresquen" la pantalla
actual.
CTRL-Q Descongelar la pantalla (vea CTRL-S)
CTRL-S Congelar la terminal (descongelar con CTRL-Q)
CTRL-U NAK Borrar la línea actual
CTRL-Z SIGSTOP Suspender el proceso en el primer plano

CTRL-C es probablemente una de las secuencias más útiles mencionadas anteriormente. Ésta
llega al rescate cada vez que un usuario siente que "SOLO QUIERO QUE SE DETENGA". Al
utilizar la shell bash, escribiendo CTRL-Cterminará el proceso que se está ejecutando en ese
momento y lo devolverá al intérprete de comandos bash.

El nodo de dispositivo /dev/zero es un pseudo dispositivo que cuando se lee devuelve un número
infinito de ceros (binarios). El nodo del dispositivo /dev/null es un pseudo dispositivo que bota
cualquier información escrita en él. Por lo tanto, el siguiente comando ejecutaría por siempre
leyendo y botando ceros. Alguien atascado en esta situación podría utilizar CTRL-C para cancelar
el comando.

[elvis@station elvis]$ cat /dev/zero > /dev/null


(... user types CTRL-C ...)
[elvis@station elvis]$

CTRL-D

22
Como lo verá en un cuaderno posterior muchos de los comandos Unix leen su entrada
directamente del teclado. Infortunadamente, para los nuevos usuarios Unix, no siempre es
obvio el cómo decirle al comando que pare de escuchar. La respuesta es CTRL-D. Esta
secuencia se utiliza para enviar un mensaje de "Fin de la Transmisión" (usualmente
interpretado como "Final del Archivo") al proceso de escucha.

El comando wc es un ejemplo de un comando que al no recibir el nombre de un archivo


como argumento entonces contará el número de líneas, palabras y caracteres digitadas
por el usuario. El usuario señala el final de la entrada con CTRL-D.

[elvis@station elvis]$ wc
polly wants a cracker
polly wants a cracker
polly wants a cracker
(... user types CTRL-D ...)
3 12 66
[elvis@station elvis]$

El comando wc reporta obedientemente que el usuario ha escrito 3 líneas, 12 palabras


utilizando 66 caracteres (aunque esto no parece útil por el momento, encontrará más usos
para wc en un cuaderno posterior). ¿Qué pasaría si el usuario hubiese escrito CTRL-C en
cambio?

CTRL-Z

CTRL-Z se utiliza para suspender un programa, el cual se puede restablecer


posteriormente con el comando fg ("foreground", primer plano en inglés). En la mitad de
una sesión ftp, elvis quiere determinar el directorio actual de trabajo de su shell. Suspende
la sesión ftp con CTRL-Z, ejecuta el comando pwd desde la shell y luego restablece la
sesión ftp con fg.

[elvis@station elvis]$ ftp ftp.redhat.com


Trying 66.187.232.51...
Connected to ftp.redhat.com (66.187.232.51).
220 Red Hat FTP server ready. All transfers are logged. (FTP)
Name (ftp.redhat.com:elvis): anónimo
331 Please specify the password.
Password:
230 Login successful. Have fun.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
(... el usuario escribe CTRL-Z ...)
[1]+ Stopped ftp ftp.redhat.com
[elvis@station elvis]$ pwd
/home/elvis
[elvis@station elvis]$ fg
ftp> ftp.redhat.com
ftp> ls
227 Entering Passive Mode (66,187,232,51,67,212)
150 Here comes the directory listing.
drwxr-xr-x 6 ftp ftp 4096 May 24 01:33 pub

23
226 Directory send OK.
...

La administración de procesos de esta manera es un tema bastante complicado que se


estudiará en detalle en un cuaderno posterior. Por ahora, es suficiente con que sepa que
CTRL-Z suspende y fg reanuda.

CTRL-U

CTRL-U usualmente se utiliza para "limpiar" la línea actual. Si ha cambiado tanto una línea
de comandos bash y sólo quiere volver a empezar en limpio pulse CTRL-U. También,
CTRL-U es muy útil cuando cometa errores al ingresar una contraseña. Como los
caracteres usualmente no aparecen en la pantalla, es difícil saber lo que ha escrito. Sólo
pulse CTRL-U e inicie de nuevo.

CTRL-H

CTRL-H tiene la misma función que la TECLA DE RETROCESO. Sin embargo, en algunas
terminales laTECLA DE RETROCESO se encuentra mapeada de manera incorrecta y por
lo tanto no funciona bien. CTRL-H casi siempre funcionará en estas situaciones.

CTRL-L

Tradicionalmente, CTRL-L se utilizaba para ordenarle a la impresora de línea que


expulsara la página actual y que iniciara en la próxima. En los terminales en línea, este
comando tiene la función de restablecer la pantalla. Para muchos programas de pantalla,
incluyendo los editores, el comando vi y nano, si la pantalla se torna alguna vez
inentendible debido a mensajes inesperados, CTRL-L hará que el programa refresque la
pantalla, restableciéndola correctamente.

La shell bash, CTRL-L hace que bash deje en limpio la pantalla, pero preserva la línea de
comandos actual.

CTRL-Q

CTRL-Q "descongela" una pantalla (haciendo que se active de nuevo) después de que se
ha "congelado" con CTRL-S. Aunque sólo es útil después de haber utilizado CTRL-S, se
introduce primero (como el comando más útil) ya que nadie utiliza intencionalmente CTRL-
S. Por el contrario, los nuevos usuarios de Unix a veces pulsarán por error CTRL-S y no
entenderán el porqué su terminal no responde. Si alguna vez su terminal parece muerta,
intente presionar CTRL-Q y vea si eso la arregla.

CTRL-S

Vea CTRL-Q arriba.

CTRL-J

Casi nunca se utiliza, (en su lugar, la gente utiliza la tecla ENTER).

CTRL-G

24
El único uso real es que hace pitar la terminal, impresionando a sus amigos con su basta
reserva de conocimiento inútil sobre Unix.

Identificación de terminales

Así como con la mayoría de los otros dispositivos, los programas interactúan con los terminales en
un nivel bajo por medio de nodos de dispositivos, que se encuentran dentro del directorio /dev. Por
ejemplo, la comunicación con la primera consola virtual utiliza el nodo de dispositivo /dev/tty1. La
mayoría de los procesos mantienen un registro de la terminal en donde empezaron y las sesiones
de inicio de los usuarios usualmente se encuentran asociadas con la terminal que se encuentran
utilizando. Al identificar las terminales en estas situaciones, la terminal se conoce por medio de su
nodo de dispositivo, por ejemplo, tty1.

En el siguiente extracto, elvis hace una lista de los usuarios actuales en una máquina con who y
enumera los procesos ejecutándose en ese momento desde su terminal con ps. En ambos casos
el terminal es especificado en la columna "TTY".

[elvis@station elvis]$ who


root tty2 Jun 21 10:12
elvis tty3 Jun 21 16:50
blondie :0 Jun 21 10:13
blondie pts/0 Jun 21 16:43 (:0.0)
blondie pts/1 Jun 21 10:14 (:0.0)
blondie pts/2 Jun 21 10:31 (:0.0)
blondie pts/3 Jun 21 10:39 (:0.0)
[elvis@station elvis]$ ps
PID TTY TIME CMD
4384 tty3 00:00:00 bash
4427 tty3 00:00:00 ps

Linux trata muchos dispositivos diferentes como una terminal, incluyendo las consolas virtuales,
una línea en serie conectada a terminales VT100, módems, etc. La siguiente tabla lista algunos de
los nombres comunes para terminales utilizados convencionalmente para algunos de los
dispositivos de terminal comúnes.

Table 1. Nombres de los Dispositivos de Terminal

Nombre Dispositivo ¿Cómo se utiliza?


ttyn Consola Se accede a esta con la combinación CTRL-ALT-Fn.
Virtual
ttySn Dispositivo de Un módem o un terminal similar a VT100 adjunto a un puerto en serie.
puerto serial La terminal ttyS0 en Unix se relaciona con COM1 en DOS, ttyS1 en
COM2, etc.
pts/n Pseudo- Una emulación de terminal, con frecuencia utilizado por terminales en
terminal el entorno gráfico X, o por shells originadas en la red tal como con
telnet o ssh. Las pseudo-terminales no pueden estar relacionadas
directamente a un dispositivo físico.
:0 Servidor X El servidor X no es realmente una terminal. Cuando un usuario inicia la
sesión utilizando el Administrador de Inicio de sesión en el entorno
gráfico X, con frecuencia su terminal es listada como el servidor X
mismo.

25
Completar con el tabulador

Completar con el tabulador no es una característica de las terminales sino de la shell bash que
usualmente ejecuta dentro de éstas. Se puede ahorrar bastante tiempo y esfuerzo aprendiendo a
hacer buen uso del tabulador al escribir los nombres de los comandos y archivos.

Al escribir el nombre de un comando como la primera palabra de una línea de comandos bash,
comience a escribir el comando que quiera ejecutar, pero en algún momento antes de que termine
la palabra, pare y pulse la tecla del TABULADOR. Puede pasar una de tres cosas:

1. El resto del comando que empezó a escribir aparecerá mágicamente.


2. Parte del comando que estaba escribiendo aparece mágicamente pero luego bash para y
le pita.
3. bash solo le pita.

La shell bash hace lo mejor que puede seleccionando el comando que usted empezó a escribir de
la lista de todos los comandos posibles. En el primer caso, sólo hay un comando que comienza con
las letras que usted escribió así que bash puede descubrir exactamente el comando que usted
había empezado y lo termina de escribir por usted. Ha terminado.

En el segundo y tercer caso, más de un comando inicia con las letras que usted escribió. bash
completó el comando tanto como pudo pero paró y le pitó para dejarle saber que usted aún tiene
que escoger. Para poder ver las opciones de los comandos que bash ha delimitado, oprima el
tabulador dos veces y bash hará una lista de todos los comandos que inician con las letras que
usted escribió inicialmente. Proporcione lo suficiente del comando para que sea único y oprima el
tabulador de nuevo. bash terminará de escribir el comando por usted.

Un ejemplo es en orden.

El usuario elvis quiere habilitar el modo Unicode para su terminal. Por ahora no se preocupe de lo
que es el modo Unicode o el por qué quiere tenerlo. Sólo necesita saber que el comando que
habilita este modo se llama unicode_start y el comando que lo desactiva es unicode_stop.
Empieza a escribir el comando y presiona el tabulador.

[elvis@station elvis]$ unic<TAB>

bash expande la palabra a unicode_st y pita. Para poder ver la lista de opciones disponibles para
completar, elvis teclea el tabulador dos veces.

[elvis@station elvis]$ unicode_st<TAB><TAB>


unicode_start unicode_stop

bash le devuelve una lista con dos opciones posibles que enmpiezan con unicode_st. Al ver que
el comando que elvis quiere ejecutar es el único que empieza con unicode_sta, elvis escribe una a
y presiona el tabulador.

26
[elvis@station elvis]$ unicode_sta<TAB>

bash completa el comando y pone el cursor para que esté listo para comenzar a escribir cualquier
argumento u opciones para el comando.

[elvis@station rha030]$ unicode_start

bash no sólo completa la primera palabra al compararla con los comandos disponibles sino que
también se pueden completar las otras palabras en la línea de comandos con base en el sistema
de archivos. Por ejemplo, suponga que madonna quiere examinar el archivo /etc/prelink.conf. En
vez de tener que escribir el nombre completo del archivo, ella puede escribir la primera parte y
después presionar el tabulador.

[madonna@station madonna]$ cat /etc/prel<TAB>

Debido a que /etc/prelink.conf es el único archivo que inica con /etc/prel, bash puede completar
todo el archivo.

[madonna@station madonna]$ cat /etc/prelink.conf


# This config file contains a list of directories both with binaries
# and libraries prelink should consider by default.
# If a directory name is prefixed with `-l ', the directory hierarchy
# will be walked as long as filesystem boundaries are not crossed.
# If a directory name is prefixed with `-h ', symbolic links in a
# directory hierarchy are followed.
-l /bin
-l /usr/bin
...

Al avanzar en el curso se dará cuenta de que el tomarse un poco de tiempo explorando la


característica de completar con el tabulador le ahorrará mucho tiempo en adelante. Después de un
tiempo, el utilizar el tabulador se convertirá en parte de su naturaleza. Al final de un día muy
ocupado, le llegará a doler el dedo meñique izquierdo de tanto presionar el tabulador.

Ejemplos

Reiniciar el terminal después de ver un archivo binario

El usuario blondie accidentalmente utiliza el comando cat para ver un archivo ejecutable, /bin/arch.
Como el archivo es un ejecutable compilado, contiene bytes que no se pueden mostrar en una
terminal y esto la descontrola.

[blondie@station blondie]$ cat /bin/arch


ELF??414 (44???4????/lib/ld-linux.so.2GNU???y??6,?????aaa????aac????-?????[???

27
Para restablecer la terminal, blondie escribe el comando reset a ciegas y su terminal se
restablece.

[blondie@station blondie]$

Cancelar un comando

El usuario prince piensa que puede ser interesante el listar recursivamente el contenido de su
sistema de archivos, iniciando con el directorio raíz /.

[prince@station prince]$ ls -R /
/:
bin data etc initrd lost+found mnt proc root sbin usr web
boot dev home lib misc opt rha RPMS tmp var

/bin:
arch cut gawk mail rm touch
ash date gettext mkdir rmdir true
ash.static dd grep mknod rpm umount
aumix-minimal df gtar mktemp rvi uname
awk dmesg gunzip more rview unicode_start
basename dnsdomainname gzip mount sed unicode_stop
bash doexec hostname mt setfont unlink
bash2 domainname igawk mv setserial usleep

Después de ver pasar los archivos por varios minutos, considera que ha visto lo suficiente. Cancela
el comando presionando CTRL-C. El comando termina y regresa al intérprete de comandos bash.

[prince@station prince]$

Suspender la salida de una terminal Lab Exercise Objetivo: Aprender a administrar la salida de la
terminal para aquellos comandos con una ejecución larga.Tiempo estimado: 5 minutos.

Especificaciones

1. Como en el ejemplo de prince, tome una lista recursiva del directorio root del sistema de
archivos utilizando el comando ls -R /.
2. Mientras que esté apareciendo la salida, congele su terminal utilizando la secuencia CTRL-
S.
3. Descongele la terminal utilizando la secuencia CTRL-Q. Debería poder alternar el
congelamiento y descongelamiento de la salida utilizando estas secuencias.
4. Mientras que la salida aún se encuentre fluyendo, suspenda el proceso con la secuencia
CTRL-Z.
5. Confirme que ha suspendido el proceso.

Deliverables A title Question

28
1 El comando suspendido ls -R /

Limpieza

Después de conseguir el resultado deseado, restablezca el proceso suspendido al primer plano


con el comando fg. Ahora cancélelo con la secuencia CTRL-C.

29
Getting Help

Conceptos clave

• La mayoría de los comandos proporcionan resúmenes cuando se invocan las opciones -h,
-? o --help.
• Puede encontrar información de referencia mucho más amplia en las "páginas del manual",
las cuales se pueden ver con el comando man.
• Las páginas man tienen capítulos y el contenido de un capítulo anterior puede llegar a
obscurecer el contenido de un capítulo en desarrollo.
• Los comandos más complicados se describen de manera más completa en las páginas
info.
• En Red Hat Enterprise Linux, cualquier documentación menos convencional asociada con
un paquete específico se puede encontrar en /usr/share/doc.
• El Proyecto de documentación de Linux brinda una gran cantidad de documentación
relacionada con Linux.
• Los manuales de Red Hat proporcionan documentación específica a la distribución de Red
Hat Enterprise Linux.

Discussion

Getting Help

Unix y Linux, en particular , tienen la tradición de que los manuales y la documentación no se


deben mantener en un estante, sino que se deben encontrar en el sistema de manera que sea de
fácil acceso para los usuarios. Nadie recuerda todas las opciones para el comando ls así que la
mayoría de los comandos proporcionan breves resúmenes llamados "usages" cuando se invocan
con las opciones apropiadas. La información de referencia más completa que se puede encontrar
para la mayoría de los comandos está en las páginas "man" pages e "info". En Red Hat Enterprise
Linux, el directorio /usr/share/doc contiene menos documentación estructurada específica para un
paquete en particular. Por último, también puede encontrar bastantes manuales y tutoriales en el
Proyecto de Documentación Linux o en los paquetes de documentación de Red Hat Enterprise
Linux.

Obtención de usos con -h, -? y --help

Al avanzar el curso probablemente se dará cuenta de que a menudo Unix toma decisiones de
diseño en favor de la brevedad y la eficiencia más que de la transparencia al nombrar los
comandos y las opciones. Esto es en particular cierto para los comandos más utilizados tales como
mv, ps y vi. Esto hace de Unix una opción muy efectiva para el usuario conocedor, pero con
frecuencia a expensas del aprendiz.

Nadie recuerda todas las funcionalidades de cada uno de los comandos, pero los usuarios
experimentados de Unix saben cómo encontrar la información en línea de manera rápida. La
primera capa de ayuda con frecuencia la proporcionan los comandos mismos, en la forma de
"usages" o breves resúmenes de sintaxis que se producen cuando se invoca el comando con las
opciones -h, -? o --help. Los usos se abordaron en la lección anterior pero se mencionan otra vez
aquí para que todo esté completo.

30
Las páginas man

Las páginas del manual, con frecuencia abreviado como "páginas man", son la fuente tradicional
de referencia e información de los sistemas Unix. Puede ver las páginas de documentación para la
mayoría de los comandos, los formatos de archivos, las llamadas de programación y temas en
general, utilizando el comando man. Por ejemplo, man ls genera la documentación para el
comando ls.

El paginador less

Red Hat Enterprise Linux usa less para ver las páginas del manual. Al ver archivos (incluyendo las
páginas man) en less, se puede navegar utilizando solo letras: space se utiliza para ver la
siguiente página, b se utiliza para ver la página anterior, q es para salir. less se abordará en más
detalle en una lección posterior; sin embargo, la siguiente tabla resume algunos de los comandos
de navegación más útiles al ver las páginas man con less.

Table 1. Navegación de less básica

Comando Acción
space Ver la próxima página
b Ver la página anterior
q Salir
/ text Busca la palabra text
RETURN
n Encuentra la siguiente ocurrencia de la palabra que se buscó anteriormente

Capítulos Man

Las páginas man están organizadas en ocho capítulos estándares como se muestra en las
siguientes tablas. Algunas de las páginas comparten nombres idénticos en diferentes capítulos. Por
ejemplo, existen páginas tanto para el comando passwd, que se encuentra en el capítulo uno
sobre los comandos del usuario, como para el archivo /etc/passwd, que se encuentra en el capítulo
cinco que cubre los formatos de archivos. Infortunadamente, para el usuario que está tratando de
encontrar documentación sobre el formato del archivo /etc/passwd, man passwd sólo presenta la
primera página que encuentra, en este caso la entrada del capítulo uno. Para poder ver la página
man del capítulo cinco, se debe especificar explícitamente el capítulo como en man 5 passwd.

Table 1. Capítulos Man

Capítulo Audiencia Tema


1 usuarios estándar Comandos
2 desarrolladores Llamadas del sistema
3 desarrolladores Llamadas de bibliotecas
4 administradores Archivos de dispositivos
5 usuarios estándar Formatos de archivos
6 usuarios estándar ??? (ver las preguntas)
7 usuarios estándar Información general
8 administradores Comandos del administrador

31
En Unix, las referencias a las páginas man usualmente incluyen el número del capítulo en
paréntesis despúes del número de la página, tal como passwd(1) o passwd(5). Cada capítulo tiene
una página de introducción llamada intro para que el comando man 5 intro presenta una
introducción al capítulo 5.

Búsquedas de palabras clave y la opción -a

Dos de las opciones más utilizadas con el comando man son -k, para realizar búsquedas de
palabras y -a, para ver todas las "páginas relevantes" para un argumento. La usuaria madonna
está tratando de hallar información sobre el formato para el archivo /etc/passwd. Ya descubrió que
man passwd sólo presenta la página man para el comando passwd, así que utiliza man -k para
realizar la búsqueda de la palabra clave en passwd.

[madonna@station madonna]$ man -k passwd


...
chpasswd (8) - update password file in batch
gpasswd (1) - administer the /etc/group file
hesiod_free_passwd [hesiod_getpwnam] (3) - Hesiod functions for retrieving passwd
information
hesiod_getpwnam (3) - Hesiod functions for retrieving passwd information
hesiod_getpwuid [hesiod_getpwnam] (3) - Hesiod functions for retrieving passwd
information
htpasswd (1) - Create and update user authentication files
ldappasswd (1) - change the password of an LDAP entry
lppasswd (1) - add, change, or delete digest passwords
pam_localuser (8) - require users to be listed in /etc/passwd
passwd (1) - update a user's authentication tokens(s)

passwd (5) - password file


passwd [sslpasswd] (1ssl) - compute password hashes
saslpasswd (8) - set a user's sasl password
smbpasswd (5) - The Samba encrypted password file
smbpasswd (8) - change a user's SMB password
...

madonna obtuvo mucho más de lo que estaba buscando, pero incluida en la salida se
encuentra la referencia al archivo de la contraseña,y el hecho de que la información se
encuentra en el capítulo 5 de las páginas man.

Ahora madonna sabe cuál es el capítulo que necesita así que saca la página con man 5 passwd.
Otra opción podriá haber sido utilizar la opción -a, la cual hace que manvea todas las páginas
relevantes en orden.

Las páginas info

Las páginas man usualmente están diseñadas para proporcionar información de referencia no
tutoriales o ayuda en un contexto en general. Los comandos mucho más complicados se
encuentran documentados en las páginas "info" con hipervínculos. Las páginas info preceden los
días de los navegadores y los enlaces. Dichas páginas se pueden ver ya sea utilizando el comando
info tradicional o Red Hat Enterprise Linux proporciona un comando similar con una interfaz más
fácil llamada pinfo. Las páginas info se utilizan principalmente para software desarrollador por the
GNU project.

32
El comando pinfo, sin argumentos, realizará una lista de la tabla de contenidos para todas las
páginas info instaladas. La navegación básica es similar al paginador less. Los enlaces entre las
páginas info se pueden cruzar utilizando las cuatro flechas como se señala en la siguiente tabla.

Table 1. Navegación con pinfo

Comando Acción
SPACE Página siguiente
b Página anterior
q Salir
/text RETURN Busca la palabra text
FLECHA DERECHA Seguir el vínculo
FLECHA IZQUIERDA Atrás
FLECHA ARRIBA Enlace anterior
FLECHA ABAJO Siguiente enlace

El directorio /usr/share/doc

Uno de los principios de diseño detrás del software de código abierto con frecuencia se resume en
la frase "lanzamiento temprano, lanzamiento frecuente". Al desarrollar software, este se distribuye
tan pronto como sea útil así no se haya pulido o esté bien documentado todavía. El permitir a los
usuarios utilizar pronto el software, brinda la ventaja de que ellos pueden ayudar a influir en su
diseño continuo.

Red Hat Enteprise Linux adopta esta filosofía e incluirá software estable y útil aún si éste no se
encuentra formalmente documentado en las páginas man o en la páginas info. Con frecuencia, la
documentación sobre cómo utilizar los productos recién desarrollados puede ser un simple archivo
de texto llamado README, agrupados de manera rápida por el desarrollador. Red Hat Enteprise
Linux incluye tal documentación poco estructurada, pero útil dentro del directorio /usr/share/doc,
organizado por el paquete de Red Hat propietario del software.

Su dimensión variará de acuerdo con el grado de utilidad que tenga la documentación para un
paquete dado. Por ejemplo, elvis descubrió que la documentación informal proporcionada por el
visor de archivos PostScript ggv es muy poca, ya que consta del ChangeLog poco estructurado de
los desarrolladores. Con un poco de suerte, la falta de NEWS es una buena noticia.

[elvis@station elvis]$ ls -s /usr/share/doc/ggv-1.99.97/


total 144
120 ChangeLog 20 COPYING 0 NEWS 4 TODO

En contraste, se puede encontrar mucha información sobre la configuración del complicado servicio
para compartir archivos, samba, bajo su directorio /usr/share/doc incluyendo los subdirectorios que
contienen documentación en una variedad de formatos.

[elvis@station elvis]$ ls /usr/share/doc/samba-2.2.7a/


autofs LDAP misc README Roadmap
COPYING libsmbclient printer-accounting README.vfs-recycle WHATSNEW.txt
docs Manifest printing recycle.conf

Manual de Documentación de Red Hat

33
Red Hat Enterprise Linux incluye manuales de documentación desarrollados como parte de un
servicio que Red Hat, Inc presta. Los siguientes manuales de documentación se encuentran
disponibles en online, en el CD de documentación en formato RPM o en los libros que vienen como
parte del paquete.

• Manual de Instalación de x86


• Manual de Inicio
• Manual para personalización
• Manual de referencia
• Manual de Seguridad
• Manual básico de administración del sistema

Estos manuales dan información específica sobre el sistema operativo de Red Hat Enterprise
Linux, incluyendo información básica e instrucciones paso a paso para varias tareas.

El proyecto de documentación de Linux

El proyecto de documentación de Linux ha asumido la poco envidiable tarea de documentar todos


los desarrollos rápidos asociados con el sistema operativo Linux. La documentación en este sitio
sigue los formatos desarrollados en los primeros días de desarrollo de Linux.

Preguntas más frecuentes

Las FAQs son una compilación de las Preguntas más frecuentes sobre un tema en
particular tal como FAQ sobre Linux-RAID.

HOWTOs

HOWTOs brinda instrucciones paso a paso sobre cómo configurar una faceta en particular
de Linux tal como el CD-Writing-HOWTO (como-grabar-CDs) o el ETHERNET-HOWTO
(como-eternet).

MANUALES

Los manuales proporcionan un cubrimiento más profundo sobre temas más amplios tales
como la administración de sistemas o incluso la programación del módulo del kernel de
Linux.

Aunque la documentación no es específica para la distribución Red Hat Enterprise Linux, gran
parte de la información es útil y relevante.

yelp: El navegador de ayuda de Gnome

Por último, presentamos yelp, el navegador de ayuda de Gnome, el cual se puede reiniciar
seleccionando "Ayuda" del menú de aplicaciones. yelp proporciona la documentación básica para
muchas de las aplicaciones gráficas especificas de GNOME, incluyendo Nautilus File Manager y
los applets de GNOME.

Figure 1. yelp: El navegador de ayuda de GNOME

34
Propiedades de Archivos regulares y Permisos

Conceptos clave

• Los archivos tienen usuario propietario, un grupo propietario, y una serie de permisos.
• Tres tipos de permisos: lectura (r), escritura (w) y ejecución (x)
• Tres clases de acceso: (u)suario, (g)rupo propietario, y (o)tro
• Ver la propiedad y los permisos de archivo: ls -l
• Modificar la propiedad y permisos:chmod, chgrp, y chown

Discusión

Usuarios propietarios, Grupos propietarios y Permisos

Linux es un entorno multiusuario y como tal, personas muy diferentes pueden estar trabajando al
mismo tiempo con una serie de archivos sencillos. Se espera que algunos de estos archivos sean
compartidos, de tal manera que muchas personas puedan verlos y modificarlos. Por ejemplo,
alguien puede estar haciendo la lista de regalos para un cumpleaños próximo. Entre más gente
pueda leer este archivo, mejor. Sin embargo, puede que haya otros archivos que se quieran
mantener en privado. Por ejemplo, muy poca gente querrá que alguien le lea su diario, otros
querrán tener un archivo de lectura para todos en el sistema, y permitirle a unos pocos modificarlo.

Cada archivo en Linux tiene tres propiedades que permiten a los usuarios controlar quién tiene
acceso al archivo y cómo: un usuario propietario, un grupo propietario y una serie de permisos
otorgados. Cuando un usuario crea un archivo, éste se convierte en el propietario del archivo del
usuario y por lo general, el grupo primario del usuario, se convierte en el propietario del archivo de
grupo. Un usuario no puede cambiar el archivo del usuario propietario, pero el usuario tiene
algunas habilidades para cambiar el grupo propietario. Los bits de permisos definen la forma como
las tres clases diferentes de usuarios pueden usar el archivo: el propietario del archivo, los
miembros del grupo que poseen el archivo y cualquier otro usuario.

Considere el siguiente listado largo del directorio /var/gigs.

Figure 1. Listado largo de directorio /var/gigs.

[student@station student]$ ls -l /var/gigs/


total 28
-rw-rw-r-- 1 elvis elvis 129 Jan 13 14:48 atlanta
-rw-r--r-- 1 blondie music 142 Jan 13 14:46 boston
-rw-rw-r-- 1 elvis music 143 Jan 13 14:48 chicago
-rwxr-x--- 1 root music 55 Jan 13 15:25 generate_report.sh
-rw-rw-r-- 1 root music 2057 Jan 13 14:47 los_angeles
-rw-rw-r-- 1 elvis music 142 Jan 13 14:47 san_francisco
-rw-rw-r-- 1 blondie blondie 135 Jan 13 14:47 springfield

La última columna es el nombre del archivo, mientras que la tercera y cuarta columnas, indican los
propietarios del archivo de usuario y grupo, respectivamente. En las siguientes secciones veremos
cómo utilizar la primera columna para determinar los permisos del archivo.

Los tres tipos de permisos: lectura (r), escritura (w), y ejecución(x)

35
Al decidir quién puede tener acceso al archivo, un usuario puede distinguir entre tres tipos de
permisos. Alguien puede ver un archivo si tiene permisos de lectura, pero deberá tener permisos
de escritura para modificarlo. Los permisos de ejecución, permiten que alguien utilice el archivo
como un comando. Para iniciar una aplicación o ejecutar un script, el archivo que contenga la
aplicación o el script deberá ser ejecutable. Los archivos normales de datos no usan el tipo de
permiso ejecutable.

Table 1. Permisos de Archivos Regulares

Lectura(r) escritura (w) ejecución (X)


Ver el archivo Modificar el archivo Usar el archivo como comando

Las tres clases de acceso: (u)suario, (g)rupo propietario, y (o)tro.

Cada archivo tiene una serie de permisos de lectura(r), escritura(w), y ejecución(X) para las tres
clases diferentes de acceso de archivo. El propietario del archivo utiliza el primer grupo. Los
miembros del grupo propietario del archivo utilizan el segundo y todos los demás que no estén
incluidos en las dos categorías anteriores utilizan el último. Los permisos de un archivo se
presentan, por lo general, con una serie de nueve caracteres, tales como rwxr-xr-x. Las primeras
tres letras representan los permisos del "usuario", las siguientes tres, los permisos del "grupo", y
las últimas tres el permiso del "otro". Una letra indica que el permiso correspondiente se ha
activado, mientras que si aparece un guión esto significa que no se tiene permiso.

Figure 1. Permisos para las tres clases de acceso de archivo

Cuando alguien trata de acceder a un archivo, Linux hace las siguientes preguntas en este orden:

1. ¿El usuario es propietario del archivo? Si lo es entoces utiliza los permisos de usuario.
2. ¿El usuario es miembro del grupo que dueño del archivo? Si lo es entonces se utilizan los
permisos de grupo.
3. De lo contrario, se utilizan los otros permisos.

Ejemplos

Archivos recién creados

Considere el siguiente verso que elvis está componiendo:

[elvis@station elvis]$ echo "Había una vez un hombre peruano" > /tmp/limerick
[elvis@station elvis]$ ls -l /tmp/limerick
-rw-rw-r-- 1 elvis elvis 32 Jan 14 13:42 /tmp/limerick

Observe que por defecto, elvis posee el archivo y como propietario de archivo tiene permisos de
escritura y de lectura. Los otros usuarios sólo pueden leer el archivo (debido a que Red Hat
Enterprise Linux utiliza el esquema del grupo privado de usuario, el usuario elvis es también el

36
único miembro del grupo elvis). Como elvis tiene permisos para escribir, puede modificar el archivo
añadiendo la próxima línea del verso:

[elvis@station elvis]$ echo "que todo le importaba un pepino" >> /tmp/lime


rick

Otros usuarios como blondie, sin embargo, solo pueden leer el archivo. Cuando blondie trata de
sobrescribir el archivo con su propio verso, se da cuenta que no tiene los permisos apropiados.

[blondie@station blondie]$ cat /tmp/limerick


Había una vez un peruano,
que todo le importaba un pepino.
[blondie@station blondie]$ echo "Había una vez un argentino " > /tmp/limerick
-bash: /tmp/limerick: Permission denied

Archivos compartidos por un grupo

Considere los siguientes usuarios, y sus respectivas membresías de grupo:

user grupos
blondie blondie,music
elvis elvis,music,wrestle,physics,emperors
hogan hogan,wrestle
bob bob

La siguiente es una lista de archivos en el directorio /tmp:

[elvis@station elvis]$ ls -l /tmp


total 28
-rw------- 1 bob bob 136 Jan 14 15:58 diary
-rw-rw-r-- 1 elvis music 142 Jan 14 15:58 gigs
-rw-rw-r-- 1 elvis elvis 70 Jan 14 13:42 limerick
-rw-rw---- 1 blondie blondie 134 Jan 14 15:59 lyrics
-rw------- 1 blondie blondie 29 Jan 14 16:00 lyrics.old
-rw-r----- 1 hogan wrestle 146 Jan 14 15:58 routines

El arhivo diary de bob sólo lo puede leer y escribir Bob.

Elvis es el propietario del archivo gigs, pero cualquiera que pertenezca al grupo music puede
leer o escribir en este archivo. Cualquier músico, puede añadir (o borrar) un evento en la
programación y cualquiera puede leer el archivo para saber cuándo tocan los músicos.
En contraste, blondie ha estado trabajando en el archivolyrics, el cual no está aún listo para
compartir. Aunque el archivo tiene permiso de escritura, es de propiedad del grupo de
blondie. Como Red Hat implementa el esquema de grupo privado de l usuario, la usuaria
blondie debería ser la única miembro del grupo blondie. Los permisos en lyrics tienen el
mismo efecto de aquellos en lyrics.old.
Hulk Hogan ha estado trabajando en routines para una función de lucha libre. Para no tomar
a otros luchadores (wrestlers en inglés) por sorpresa, ha dejado un archivo de sólo lectura
para todos los miembros del grupo wrestle. Observe que otros luchadores pueden leer el

37
archivo, pero no pueden cambiar ninguna de las rutinas. El que no sea miembro del grupo de
wrestlers no tiene acceso al archivo.

Archivos ejecutables

Los archivos que se deben interpretar como comandos necesitan tener permisos de ejecución.

[elvis@station elvis]$ ls -l /bin/ls /usr/bin/mozilla


-rwxr-xr-x 2 root root 67884 Sep 2 07:21 /bin/ls
-rwxr-xr-x 1 root root 5607 Oct 3 13:58 /usr/bin/mozilla

El comando ls es ejecutable por cualquiera. Observe que el permiso de lectura no se necesita para
ejecutar el comando, pero permite a los usuarios ver el contenido del archivo (a menudo binario).
Los permisos de lectura para mozilla, por ejemplo, permiten a los usuarios observadores darse
cuenta de que el comando es realmente un script de texto navegable.

Enlaces simbólicos

A pesar de que los enlaces simbólicos tienen permisos, los permisos son siempre rwxrwxrwx. Las
decisiones de acceso "fracasan" de a cuerdo al archivo al que se refiere el enlace simbólico.

[elvis@station elvis]$ ls -l /bin/view /bin/vi


-rwxr-xr-x 1 root root 451628 Aug 27 19:09 /bin/vi
lrwxrwxrwx 1 root root 2 Sep 11 11:32 /bin/view -> vi

El comando view, el cual es en realidad un enlace simbólico, tendría los mismos permisos que:
rwxr-xr-x.

Ejercicios en línea

Exploración de permisos en archivos recién creados Lab Exercise Objetivo:Examinar la conducta


predeterminada de los archivos recién creados Tiempo estimado:10 minutos

Cree un subdirectorio en el archivo/tmp con el mismo nombre de su nombre de usuario. Por


ejemplo, si su nombre de usuario es elvis, cree el directorio /tmp/elvis. A este directorio se le
llamará /tmp/nombre de usuario.

1. Haga una lista corta de propósitos para el año entrante en su editor de texto preferido o
simplemente desde la línea de comandos. Almacene el archivo en su directorio recién
creado como /tmp/nombredeusuario/resolutions.txt.

[student@station student]$ nano /tmp/student/resolutions.txt


... (compose and save your text) ...
[student@station student]$ cat /tmp/student/resolutions.txt
keep room clean
don't eat all of the pop tarts
use less proprietary software
[student@station student]$ ls -l /tmp/student/resolutions.txt
-rw-rw-r-- 1 student student 77 Jan 15 07:12
/tmp/student/resolutions.txt

38
2. Conviértase en uno de sus usuarios de cuenta alterna. Puede reiniciar desde otra consola
virtual, desde una conexión de red o sencillamente con ejecutar su - al usuario alterno.

[student@station student]$ su - student_a


Password:
[student_a@station student_a]$

3. Como el usuario alterno, confirme si puede ver el archivo. Trate de añadir un nuevo punto
a la lista. ¿Por qué no puede modificar el archivo como el usuario alterno?

[student_a@station student_a]$ cat /tmp/student/resolutions.txt


keep room clean
don't eat all of the pop tarts
use less proprietary software
[student_a@station student_a]$ echo "lose weight" >> /tmp/student/resolutions.txt
-bash: /tmp/student/resolutions.txt: Permission denied

content_view let_
Deliverables A title Question 1

1. Un archivo recién creado titulado /tmp/nombredeusuario/resolutions.txt, con permisos


predeterminados.

39
Cambio de permisos de archivos: chmod

Conceptos clave

• El comando chmod se utiliza para modificar los permisos de archivo


• El primer argumento para chmod usa una sintaxis [ugoa]+/-[rwx] para describir cómo
deberían cambiarse los permisos.

Discussion

En la lección anterior, aprendimos que los archivos tienen permisos de lectura (r), escritura(w) y
ejecución(x); y tres clases de acceso ((u)suario, (g)rupo, y (o)tro, los cuales definen la manera en
que se puede utilizar el archivo. Los permisos son administrados por el comando chmod.
Usualmente, en Linux, al permiso de archivo se le conoce como el "modo" del archivo. El nombre
chmod es un atajo para cambiarmodo.

Por ejemplo, cuando alguien crea un archivo, por defecto el archivo puede ser modificado por sólo
una persona, pero puede ser leíble por todos en el sistema. Supongamos que elvis estuviera
trabajando en la letra de una nueva canción y no quisiera que nadie la leyera antes de haberla
terminado. Primero crearía el archivo y para no permitir a otros la lectura de éste, necesitaría
utilizar el comando chmod.

[elvis@station elvis]$ echo "Well, it's one for the honey," > blue_suede
[elvis@station elvis]$ echo "Two for the snow," >> blue_suede
[elvis@station elvis]$ ls -l blue_suede
-rw-rw-r-- 1 elvis elvis 48 Jan 16 08:09 blue_suede
[elvis@station elvis]$ chmod o-r blue_suede
[elvis@station elvis]$ ls -l blue_suede

-rw-rw---- 1 elvis elvis 48 Jan 16 08:09 blue_suede

Observe que en el primer uso del comando ls -l, el archivo tenía permiso de lectura para todos. Sin
embargo, después del comando chmod, el comando ls -l muestra que otros ya no lo pueden leer.
Cuando elvis haya decidido la letra de la canción entonces puede restaurar la lectura del archivo
para otros, utilizando una vez más chmod.

[elvis@station elvis]$ echo "Well, it's one for the money," > blue_suede
[elvis@station elvis]$ echo "Two for the show," >> blue_suede
[elvis@station elvis]$ echo "Three to get ready," >> blue_suede
[elvis@station elvis]$ echo "Now go, cat, go." >> blue_suede
[elvis@station elvis]$ ls -l blue_suede
-rw-rw---- 1 elvis elvis 48 Jan 16 08:10 blue_suede
[elvis@station elvis]$ chmod o+r blue_suede
[elvis@station elvis]$ ls -l blue_suede
-rw-rw-r-- 1 elvis elvis 85 Jan 16 08:11 blue_suede

El comando chmod le permite al usuario cambiar cualquier permiso asociado con un archivo. El
primer argumento está compuesto por una secuencia de letras que especifican las clases de
acceso, seguidas por los signos: más, menos, o igual y por otra secuencia de letras que

40
especifican el tipo de permiso a cambiar. Cualquier argumento subsecuente especifica una lista de
archivos para aplicar los cambios. La sintaxis se resume en la siguiente tabla:

Figure 1. Uso del comando chmod

abreviación interpretación
u user
g grupo
o otro
a todos
+ agregar
- borrar
= set
r leer
w escribir
x ejecutar

Ejemplos

Uso del comando chmod en archivos

La siguiente tabla presenta varios ejemplos de cómo el comando chmod se puede utilizar para
modificar permisos de un archivo llamadofoo, con los permisos predeterminados de rw-rw-r--. La
primera columna es un ejemplo del uso del comando chmod y la última columna son los permisos
que el archivo tendría después de ejecutar el comando.

[elvis@station elvis]$ ls -l foo


-rw-rw-r-- 1 elvis elvis 42 Jan 16 08:09 foo

command efecto permisos


resultantes
chmod o-r foo suprime el permiso de lectura a otros rw-rw----
chmod g-w foo suprime el permiso de escritura para el grupo rw-r--r--
chmod ug+x agrega permiso de ejecución al usuario y grupo rwxrwxr--
foo
chmod o+w agrega permiso de escritura a otro rw-rw-rw-
foo
chmod go-rwx suprime el permiso de lectura, escritura y ejecución a rw-------
foo grupo y otro
chmod a-w foo suprime el permiso de escritura a todos r--r--r--
chmod uo-r foo suprime el permiso de lectura para el usuario y otro -w-rw----

41
chmod go=rx establece el permiso de lectura y ejecución pero no de rw-r-xr-x
foo escritura para el grupo y otro

A pesar de que las dos últimas entradas funcionarían, ¿por qué es difícil imaginar un uso para un
archivo con cualquiera de los dos permisos resultantes?

Ejercicios en línea

Hacer un Archivo Privado

Lab Exercise

Objetivo: Cambiar permisos en un archivo de tal manera que otros no puedan leerlo.

Tiempo esperado: 10 minutos

1. Cree el directorio /tmp/nombredeusuario, si no existe todavía. Por ejemplo, si su nombre de


usuario es elvis, cree el directorio /tmp/elvis.
2. Cree una lista sencilla de propósitos en el archivo /tmp/nombredeusuario/resolutions.txt.
Puede utilizar un editor de texto, su archivo del ejercicio anterior si todavía está disponible,
o simplemente cree uno nuevo como en el siguiente ejemplo.

[student@station student]$ cat > /tmp/student/resolutions.txt


keep room clean
don't eat all of the pop tarts
use less proprietary software
Ctrl-D
[student@station student]$ ls -l /tmp/student/resolutions.txt
-rw-rw-r-- 1 student student 77 Jan 16 17:52
/tmp/student/resolutions.txt

3. Observe que los permisos en un archivo creado recientemente, le permiten a todos los
usuarios en el sistema leer el archivo. Asuma que quiere mantener sus propósitos en
secreto. Modifique los permisos de archivos de tal forma que los otros no tengan acceso de
lectura.

[student@station student]$ chmod o-r /tmp/student/resolutions.txt


[student@station student]$ ls -l /tmp/student/resolutions.txt
-rw-rw---- 1 student student 77 Jan 16 17:52
/tmp/student/resolutions.txt

4. Al utilizar una de las cuentas alternas, confirme que otros usuarios en el sistema no
pueden leer sus propósitos.

[student@station student]$ su - student_a


Password:
[student_a@station student_a]$ cat /tmp/student/resolutions.txt
cat: /tmp/student/resolutions.txt: Permiso negado

5. ¿En qué difiere esto del ejercicio de la lección anterior?

Deliverables

42
A title

Question 1

content_view let_

1. Un archivo /tmp/resolutions.txt, recien creado es leíble únicamente por el propietario del


archivo.

43
Cambio de Propiedad de Archivos con el comandochgrp y chown

Conceptos clave

• El comando chgrp cambia el grupo de propietarios


• El comando chown cambia los usuarios propietarios

Discussion

Cambio de Propietarios de Grupo y Archivos con chgrp

En la lección anterior, aprendimos cómo modificar los permisos de un archivo y vimos un ejemplo
de cómo crear un archivo privado: el propietario del archivo podría leer el archivo, pero nadie más
lo puede hacer. ¿Qué sucedería si usted quisiera compartir el archivo con un grupo de personas
pero no con todos? o ¿qué pasaría si quisiera modificarlo? En estas situaciones, usted hace uso
del grupo propietario de archivo y de los permisos de grupo.

En el cuaderno anterior, vimos cómo los usuarios de Linux pertenecen a una colección de grupos.
Para repasar, cada usuario pertenece a un grupo primario y también a un número de grupos
secundarios. Cuando se crea un archivo nuevo, el propietario del archivo del grupo es establecido
como el grupo primario del creador. En Red Hat Enterprise Linux, éste sería usualmente el grupo
privado del creador. Debido a que usted es el único miembro, su grupo privado no es útil para
trabajar en colaboración. Para compartir el archivo, debe cambiar el propietario del archivo de
grupo. Esto se realiza con el comando llamadochgrp.

chgrp GROUP ARCHIVO...

Cambio de propietario de ARCHIVO(s) a GRUPO

El primer argumento especifica el nuevo grupo propietario de archivo, mientras que los argumentos
subsecuentes listan los archivos cuyo propietario de grupo se va a cambiar. El propietario del grupo
sólo lo puede cambiar el usuario dueño del archivo, y el usuario debe ser un miembro del nuevo
grupo de propietarios del archivo.

En el siguiente ejemplo, el usuario ventura es un miembro del grupo wrestler y del grupo governor
(aparte de su grupo privado, ventura). Primero, desea crear un plan de impuestos que otros
gobernadores deberían poder leer pero no modificar y al cual nadie más debería tener acceso.
Para este fin, debe realizar los siguientes pasos:

1. Crear el archivo.
2. Cambiar el propietario del archivo de grupo al grupo governor utilizando el comando chgrp.
3. Cambiar permisos en el archivo desde los permisos predeterminados rw-rw-r-- a rw-r-----
utilizando el comando chmod.

[ventura@station ventura]$ id
uid=2306(ventura) gid=2308(ventura)
groups=2308(ventura),302(wrestle),305(governor)

[ventura@station ventura]$ echo "Raise tax on oatmeal" > taxplan.txt


[ventura@station ventura]$ ls -l taxplan.txt

44
-rw-rw-r-- 1 ventura ventura 21 Jan 16 09:55 taxplan.txt

[ventura@station ventura]$ chgrp governor taxplan.txt


[ventura@station ventura]$ ls -l taxplan.txt
-rw-rw-r-- 1 ventura governor 21 Jan 16 09:55 taxplan.txt

¿Pueden intercambiarse los pasos dos y tres?

Cambio de los propietarios de archivos con el comando chown

En raras ocasiones, es necesario que el administrador cambie el usuario propietario del archivo.
Esto se puede hacer utilizando chown, cuya sintaxis es casi idéntica al del comando chgrp:

chown USER ARCHIVO...

Cambie el propietario del (los) archivo(s) a USUARIO.

El primer argumento es el nombre del nuevo usuario del archivo y los argumentos siguientes son
los nombres de los archivos a cambiar. Sólo el usuario administrativo, root, puede usar chown, si
algún usuario pudiera cambiar el archivo del propietario, los permisos de acceso no tendrían
sentido.

Como root es el único que puede ejecutar el comando chown éste no se estudiará a fondo.

¿Quién puede Modificar los Propietarios de archivos y los Permisos?

En general, sólo el propietario de un archivo puede cambiar los permisos o propiedades de archivo
de un archivo. Además, cuando se utiliza el comando chgrp, el archivo del nuevo propietario del
grupo, debe ser uno de los grupos subscritos del usuario. El usuario administrativo, root, puede
realizar cualquiera de estas operaciones. La tabla de abajo resume estas habilidades.

Table 1. ¿Quién puede Modificar las Propiedades de Archivos y los Permisos?

Operación Usuarios autorizados


chmod root y el propietario del archivo
chgrp root y el propietario de archivo (únicamente los grupos subscritos)
chown sólo root

Ejemplos

Manejo de Archivos de Grupos

Considere que al usuario ventura, quien es miembro de los grupos secundarios governor y wrestler
(aparte de su grupo privado, ventura) le gustaría compartir sus planes de lucha libre (wrestling) con
el usuario hogan y con otros miembros del grupo wrestle. Sin embargo, para impedir el acceso a
los que no son miembros del grupo wrestler, él ejecuta la siguiente secuencia de comandos.

[ventura@station ventura]$ echo "beat chest and scream." > /tmp/plans.txt


[ventura@station ventura]$ ls -l /tmp/plans.txt
-rw-rw-r-- 1 ventura ventura 23 Jan 20 07:16 /tmp/plans.txt

45
[ventura@station ventura]$ chmod o-rw /tmp/plans.txt
[ventura@station ventura]$ chgrp wrestle /tmp/plans.txt
[ventura@station ventura]$ ls -l /tmp/plans.txt
-rw-rw---- 1 ventura wrestle 23 Jan 20 07:16 /tmp/plans.txt

¿Pudo el usuario ventura haber usado el comando chmod o-r /tmp/plans.txt para lograr el mismo
efecto en la secuencia anterior?

Ahora al usuario hogan le gustaría agregarse a los planes de ventura. Como miembro del grupo
wrestle tiene permiso para hacerlo.

[hogan@station hogan]$ echo "throw large objects." >> /tmp/plans.txt


[hogan@station hogan]$ cat /tmp/plans.txt
beat chest and scream.
throw large objects.

Orgulloso de su contribución, a hogan le gustaría poner los planes a la vista de todos. Para ésto
hace el archivo disponible para sólo lectura para todod el mundo.

[hogan@station hogan]$ chmod o+r /tmp/plans.txt


chmod: changing permissions of `/tmp/plans.txt': Operation not permitted

Aunque hogan es miembro del grupo wrestle, él no es el dueño del archivo. ¿Quiénes son los
únicos dos usuarios en el sistema que pueden cambiar el propietario del grupo del archivo?

Ejercicios en línea

Compartir un archivo con un grupo Lab Exercise Objetivo: Crear un archivo compartido entre
miembros de un grupo determinado. Tiempo estimado:15 minutos

Especificaciones

1. Al remplazar el nombre de usuario con su nombre de usuario, cree el directorio


/tmp/nombre de usuario, si éste todavía no existe. Por ejemplo, si su nombre de usuario es
student cree el directorio /tmp/student.
2. Haga una lista de mercado en su editor de texto preferido, o simplemente desde la línea de
comandos. Grabe el archivo como /tmp/nombredeusuario/shopping.txt. Cambie el
propietario del grupo del archivo a wrestle.

[student@station student]$ nano /tmp/student/shopping.txt


... (compose and save your text) ...
[student@station student]$ chgrp wrestle /tmp/student/shopping.txt
[student@station student]$ cat /tmp/student/shopping.txt
eggs
bacon
milk
M and M's
[student@station student]$ ls -l /tmp/student/shopping.txt
-rw-rw-r-- 1 student wrestle 26 Jan 16 10:48
/tmp/student/shopping.txt

3. Recuerde que su primera cuenta alterna es también miembro del grupo wrestle.
Conviértase en su primer usuario alterno (i.e. estudiante_a). Usted puede reiniciar la sesión

46
desde la consola virtual, desde la conexión de red, o simplemente con el comando su - al
usuario alterno.

[student@station student]$ su - student_a


Password:
[student_a@station student_a]$ groups
student_a wrestle physics

4. Como el usuario alterno, confirme que puede ver el archivo. También, observe que puede
modificar el archivo agregando un artículo más a la lista de mercado.

[student_a@station student_a]$ cat /tmp/student/shopping.txt


eggs
bacon
milk
M and M's
[student_a@station student_a]$ echo "wheaties" >>
/tmp/student/shopping.txt
[student_a@station student_a]$ cat /tmp/student/shopping.txt
eggs
bacon
milk
M and M's
wheaties

5. Recuerde que su segunda cuenta alterna (i.e, estudiante_b) no es un miembro del grupo
wrestle. Trate de convertirse en segundo usuario alterno y repita los pasos anteriores.
Usted podrá ver el archivo pero no modificarlo.

[student@station student]$ su - student_b


Password:
[student_b@station student_b]$ groups
student_b emperors
[student_b@station student_b]$ cat /tmp/student/shopping.txt
eggs
bacon
milk
M and M's
wheaties
[student_b@station student_b]$ echo "chips" >> /tmp/student/shopping.txt
-bash: /tmp/student/shopping.txt: Permission denied

Deliverables A title Question 1

El archivo /tmp/nombre de usuario/mercado.txt, de propiedad de su usuario primario,


perteneciente al grupo propietario wrestle, es de escritura para los miembros del grupo wrestle y de
sólo lectura para los demás.

47
Propiedad de Directorios y Permisos

Conceptos clave

• Como los directorios también son archivos, tienen un usuario propietario de archivo, un
propietario de grupo y una serie de permisos.
• Los permisos de lectura permiten al usuario listar el contenido de un directorio.
• Los permisos de escritura le dan al usuario el derecho de agregar y borrar archivos.
• Los permisos de ejecución le dan derecho al usuario de acceder a un archivo dentro del
directorio.
• Los permisos de directorio se pueden modificar con el comando chmod.

Discussion

Permisos de Directorio

Cuando alguien está usando un archivo dentro de Linux, generalmente puede estar leyendo su
información, modificándola o tratando de ejecutar el archivo como un script o aplicación. Por lo
tanto, los tipos de permiso que ya hemos visto, a saber: lectura (r), escritura (w) y ejecución (x),
tienen muchas interpretaciones.

Para Linux, un directorio es solo un tipo especial de archivo, por lo tanto, tambien tiene las mismas
clases de permisos lectura (r), escritura (w) y ejecución (x), un usuario propietario, un grupo
propietario y las mismas clases de acceso ((u)suario, (g)rupo,y (o)tro). Sin embargo, es obvio que
los directorios se utilizan de una manera diferente. ¿Tendría sentido si abriéramos un directorio en
un editor tal como nano /home/elvis? Debido a que la gente usa directorios diferentes, los
permisos de directorio tienen diferentes interpretaciones.

¿Qué hace la gente con los directorios? Hacen la lista del contenido con el comando ls. Borran
archivos desde ahí, crean nuevos archivos dentro de ellos, y mueven archivos de un directorio a
otro. Los permisos de directorio deberían dar derecho al propietario del directorio de controlar quién
puede realizar estas operaciones.

Linux considera que hacer la lista del contenido de un directorio, (como con el comandols) es
análogo a "leer" un directorio, y por lo tanto, una persona debe tener permisos de lectura (r) para
listar su contenido. Agregar o suprimir un archivo desde un directorio se considera "escribir"el
directorio y por lo tanto alguien debe tener permisos de escritura (w) para barajar los archivos
dentro del directorio.

No hay una analogía razonable para "ejecutar" un directorio, por eso Linux no trata de definir una
conducta similar. En cambio, el permiso de ejecución (x) controla la conducta de los directorios, lo
que no tiene nada que ver con el comando de ejecución. Este permiso se conoce como el permiso
"buscar", pero como el tercer permiso ya ha sido llamado de "ejecución", para los archivos
regulares, se utiliza la misma palabra (y letra) para los directorios. Con el fin de referirse a cualquier
archivo dentro de un directorio, (incluyendo subdirectorios), un usuario debe tener permisos de
ejecución (x).

La primera fila de la siguiente tabla parece familiar. Esta repite cómo interpretar los permisos para
archivos regulares. Se ha agregado una fila para directorios para comparar y contrastar la
interpretación del permiso de ambos tipos de archivo.

48
Table 1. Permisos para archivos regulares y directorios

Lectura(r) escritura (w) ejecución (X)


archivo Ver el archivo Modificar el Usar el archivo como comando
regular archivo
directorio lista el contenido del añade o borra "busca" un archivo conocido dentro
directorio archivos del directorio

Ejemplos

Propiedades predeterminadas para los directorios nuevos

Los archivos normales recién creados son de lectura para todos, pero sólo el usuario y el grupo
propietario del archivo pueden modificarlos. ¿Cómo se manejan los directorios recién creados?
Estudie el caso de nero, quien está recolectando información del censo de varias provincias. El
decide crear un directorio llamado /tmp/censuspara guardar todos los datos.

[nero@station nero]$ mkdir /tmp/census


[nero@station nero]$ ls -ld /tmp/census/
drwxrwxr-x 2 nero nero 4096 Jan 16 15:33 /tmp/census/

(¿Por qué nero necesitó agregar la opción -d al comandols?)

Observe que los permisos predeterminados para los directorios recién creados son rwxrwxr-x.
Estos permisos tienen las siguientes implicaciones:

1. Cualquiera puede buscar archivos dentro del directorio.


2. Todos pueden listar los archivos dentro del directorio.
3. Solo el propietario de directorio (o miembros de un grupo propietario) puede añadir o borrar
archivos dentro del directorio.

Por ejemplo, julius decide que le gustaría hojear la información que tiene nero sobre el censo.
Observe que julius puede navegar los directorios y los archivos dentro de los directorios, pero
debido a los permisos por defecto de un directorio, él no puede agregar ni suprimir nuevos
archivos. A causa de los permisos predeterminados de archivo, él puede ver, pero no modificar el
contenido de los archivos.

[julius@station julius]$ ls -al /tmp/census/


total 20
drwxrwxr-x 2 nero nero 4096 Jan 16 15:48 .
drwxrwxrwt 23 root root 4096 Jan 16 15:45 ..
-rw-rw-r-- 1 nero nero 42 Jan 16 15:48 egypt.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 15:48 gaul.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 15:47 iberia.dat
[julius@station julius]$ rm /tmp/census/iberia.dat
rm: remove write-protected regular file `/tmp/census/iberia.dat'? y
rm: cannot remove `/tmp/census/iberia.dat': Permission denied

49
[julius@station julius]$ echo "110 CE 42" > /tmp/census/thrace.dat
-bash: /tmp/census/thrace.dat: No such file or directory

[julius@station julius]$ cat /tmp/census/gaul.dat


110 CE 45430
120 CE 53200
130 CE 55820
[julius@station julius]$ echo "140 CE 583420" >> /tmp/census/gaul.dat
-bash: /tmp/census/gaul.dat: Permission denied

Directorios de inicio

En Red Hat Enterprise Linux, un directorio de inicio no sigue los permisos predeterminados.

[nero@station nero]$ ls -ld ~


drwx------ 3 nero nero 4096 Jan 16 16:04 /home/nero
[nero@station nero]$ ls -l /home/
total 120
drwx------ 3 alice alice 4096 Jan 15 08:04 alice
drwx------ 3 augustus augustus 4096 Jan 14 15:22 augustus
drwx------ 3 austin austin 4096 Jan 14 15:22 austin
drwx------ 3 blondie blondie 4096 Jan 14 13:46 blondie
...

En Red Hat Enterprise Linux, los directorios de inicio están "protegidos". Por defecto, sólo el
usuario propietario de un directorio de inicio tiene permisos de buscar.

[nero@station nero]$ ls -l ~augustus


ls: /home/augustus: Permission denied

¿Ha notado que la mayoría de nuestros ejercicios que involucran a varios usuarios entrando a un
archivo han utilizado el directorio /tmp/nombredeusuario en lugar del directorio de inicio del
usuario? ¿Por qué razón no hemos utilizado el directorio de inicio del usuario?

Creación de un directorio ~/pub

Ahora a Nero le gustaría hacer pública su información sobre el censo. Usualmente, en Red Hat
Enterprise Linux, hay sólo dos lugares en donde los usuarios pueden crear archivos, el directorio
/tmp y ~ (el directorio de inicio del usuario). En el primer ejemplo, nero escoge crear un directorio
censusdentro de /tmp. Sin embargo, en Red HatEnterprise Linux, el directorio /tmp es "barrido.". Si
en 10 días no se ha tenido acceso a un archivo dentro de /tmp, éste se borra del sistema. Nero
necesita buscar un sitio mejor.

Con el fin de crear un sitio accesible al público permanente para sus datos del censo, nero escoge
crear un subdirectorio público dentro de su directorio de inicio. Convencionalmente, un
subdirectorio como tal en Linux, se llama pub. Como las siguientes secuencias lo mostrarán,
compartir archivos desde el directorio de inicio del usuario, no es tan fácil como crear un directorio
leible (r) o ejecutable (x) por todo el mundo.

Primero, nero crea el directorio ~/puby copia en él la información del censo desde /tmp/census.

[nero@station nero]$ mkdir pub


[nero@station nero]$ cp /tmp/census/* pub

50
[nero@station nero]$ ls -al /home/nero/pub/
total 20
drwxrwxr-x 2 nero nero 4096 Jan 16 16:13 .
drwx------ 4 nero nero 4096 Jan 16 16:12 ..
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 egypt.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 gaul.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 iberia.dat
Recuerde que "."siempre se refiere al directorio actual en este caso/home/nero/pub.

Recuerde que ".." siempre se refiere al directorio padre actual en este caso /home/nero.

Nero revisa concienzudamente los permisos en el directorio y los archivos recién creados. En
/home/nero/pub encuentra los permisos de rwxrwxr-x, lo que implica que otros pueden buscar una
lista de archivos desde el directorio. Los archivos mismos de datos tienen permisos de rw-rw-r--, es
decir que otros tienen acceso a los archivos. Como todo parece estar en orden, le dice a julius
dónde encontrar la información.

Interesado en los datos, julius trata de tener acceso a los archivos. Infortunadamente, no todo sale
bien:

[julius@station julius]$ cat /home/nero/pub/egypt.dat


cat: /home/nero/pub/egypt.dat: Permission denied

¿Qué ha olvidado nero? Recuerde que para tener acceso al archivo dentro de un directorio,
incluyendo los subdirectorios, un usuario debe haber buscado permisos para el directorio. Los
permisos en /home/nero/pub están correctos, pero observe los permisos en /home/nero (".." en la
lista de arriba o listados de nuevo a continuación):

[nero@station nero]$ ls -ld /home/nero/


drwx------ 4 nero nero 4096 Jan 20 14:05 /home/nero/

Si julius pudiera tener acceso al archivo /home/nero/pub, todo estaría bien. Pero como julius no
tiene los permisos de búsqueda para /home/nero, no puede tener acceso a /home/nero/pub. Para
crear un directorio accesible al público dentro de un directorio de inicio, el usuario debe permitir a la
gente buscar en su directorio de inicio. Nero arregla el problema en la siguiente secuencia de
comandos.

[nero@station nero]$ chmod o+x /home/nero/


[nero@station nero]$ ls -al /home/nero/pub
total 20
drwxrwxr-x 2 nero nero 4096 Jan 16 16:13 .
drwx-----x 4 nero nero 4096 Jan 16 16:14 ..
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 egypt.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 gaul.dat
-rw-rw-r-- 1 nero nero 42 Jan 16 16:13 iberia.d
Ahora, otros tienen permisos de ejecución (x) en /home/nero.

julius trata de nuevo de examinar el archivo. Como los permisos en /home/nero/pub le dan acceso
de lectura(r) y ejecución (x) a otros, julius busca archivos y obtiene un listado de directorio.

[julius@station julius]$ cat /home/nero/pub/egypt.dat

51
110 CE 45430
120 CE 53200
130 CE 55820
[julius@station julius]$ ls /home/nero/pub
egypt.dat gaul.dat iberia.dat

En contraste, el directorio de inicio de nero, /home/nero, tiene ahora permisos de rwx-----x,


permitiéndole a julius sólo permisos de ejecución(x). Por lo tanto, si julius ya sabe que un archivo
está en el directorio (porque, por ejemplo, nero le dijo que éste estaba allí), julius puede obtenerlo,
no obstante, julius no puede navegar el contenido de un directorio con el comando ls.

[julius@station julius]$ ls /home/nero


ls: /home/nero: Permiso negado

Protección de subdirectorios de inicio

Es frecuente que los usuarios permitan a otros usuarios el acceso a sus directorios de inicio
(considere, el ejemplo anterior). Al permitir a otros ejecutar (x), pero no lee(r) en su directorio de
inicio, otros usuarios deben saber que un directorio existe dentro del directorio de inicio para tener
acceso a éste. Debido a que otros usuarios no pueden usar el comando ls para descubrir el
contenido de su directorio de inicio, los directorios de inicio de los usuarios permanecen siendo
privados y sólo las partes que ellos quieran exponer estarán disponibles a otros usuarios.

Aunque el no añadir permisos de lectura (r) al directorio de inicio brinda alguna protección contra
otros usuarios que estén navegando, ésta no es infalible. Otros usuarios pueden aún "adivinar" el
contenido de un directorio del cuál tienen permisos para ejecutar (x) pero no de lectura (r). Por
ejemplo, los usuarios usualmente crean un directorio llamado ~/mail, para almacenar mensajes.
Suponga que nero le ha dado a otros permiso de ejecución (x) a su directorio de inicio (como en el
ejemplo anterior), y más tarde crea un directorio ~/mail. Si elvis fuera a adivinar si dicho directorio
existe, los permisos por defecto en ~nero/maille permitirían navegar sus contenidos. Esto se
muestra en la siguiente transcripción:

[nero@station nero]$ ls -ld ~


drwx-----x 3 nero nero 4096 Jan 20 16:41 /home/nero
[nero@station nero]$ mkdir mail
[nero@station nero]$ cal 2002 > mail/sent
[nero@station nero]$ ls -al mail
total 12
drwxrwxr-x 2 nero nero 4096 Jan 20 16:41 .
drwx-----x 4 nero nero 4096 Jan 20 16:41 ..
-rw-rw-r-- 1 nero nero 2027 Jan 20 16:41 sent

52
[elvis@station elvis]$ cat ~nero/mail/sent
2002

January February March


Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 1 2 1 2
6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9
13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16
20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23
27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30
31
...
¿Cuál es la lección que nero debe aprender? Si usted permite a otros el acceso a su directorio de
inicio como es frecuente el caso, debe considerar los permisos que hay en los subdirectorios recién
creados. Por defecto, si alguien puede adivinar el nombre del directorio, también será capaz de
navegar un subdirectorio.

La solución de nero sería cancelar su subdirectoriomail.

[nero@station nero]$ chmod o-rx mail

Ejercicios en línea

Creación de directorios públicos para grupos distintos Lab Exercise Objetivo: Crear directorios
accesibles a grupos dentro del directorio de inicio de un usuario

Especificaciones

Su cuenta debería ser miembro de dos grupos secundarios, music y wrestle. aparte de su grupo
privado. Además, su primera cuenta alterna debe ser un miembro de los grupos wrestle y physics,
mientras que su tercera cuenta alterna debería ser un miembro del grupo music.

[student@station student]$ groups student


student : student wrestle music
[student@station student]$ groups student_a
student_a : student_a wrestle physics
[student@station student]$ groups student_c
student_c : student_c music

Desde dentro de su directorio de inicio, usted quisiera compartir información con otros músicos y
luchadores, pero no le gustaría que los músicos vieran la información de los luchadores y vice
versa. Usted preferiría que un grupo ni siquiera se diera cuenta de la existencia de otro directorio
de grupo. Adopte el siguiente plan:

1. Permita que otros tengan acceso a archivos en su directorio de inicio otorgándoles


permisos de "búsqueda".
2. Cree un sudirectorio públicamente fácil de buscar, pero que no se pueda listar, en su
directorio de inicio, ~/pub.
3. Cree dos subdirectorios de ~/pub, que se puedan buscar y listar sólo para los miembros de
los grupos music ywrestle, respectivamente: ~/pub/music y ~/pub/wrestle. Observe que
usted necesitará tener en cuenta a los propietarios de grupo de los directorios como
también los permisos.

53
4. Cree los archivos ~/pub/music/lyricsy ~/pub/wrestle/plan. Los miembros de los grupos
music y wrestle deberían poder leer y escribir respectivamente.

Cuando haya terminado, usted debería poder confirmar la conducta apropiada utilizando sus
cuentas alternas (student_a y student_c).

[student_a@station student_a]$ ls /home/student/pub/wrestle


plan
[student_a@station student_a]$ cat /home/student/pub/wrestle/plan
pin the other guy
[student_a@station student_a]$ ls /home/student/pub
ls: /home/student/pub: Permission denied

[student_c@station student_c]$ ls ~student/pub/music


lyrics
[student_c@station student_c]$ cat ~student/pub/music/lyrics
row, row, row your goat
[student_c@station student_c]$ ls ~student/pub
ls: /home/student/pub: Permission denied

Deliverables A title Question

1. 1 Un directorio de inicio de búsqueda para todos y donde sólo usted puede listarlo.
2. ~/pub, un directorio de búsqueda para todos y de listado sólo para usted.
3. ~/pub/music, un directorio de búsqueda y que solo los miembros del grupo music pueden
listar.
4. ~/pub/music/lyrics, un archivo de lectura y escritura para todos los miembros del grupo
music.
5. ~/pub/wrestle, un directorio de búsqueda y que solo los miembros del grupo wrestle
pueden listar.

~/pub/wrestle/plan, un archivo de lectura y escritura para los miembros del grupo wrestle.
content_view let_

Ayudas

La siguiente serie de comandos demuestra una solución posible para hacer el directorio
~/pub/music.

[student@station student]$ ls -ld ~


drwx------ 3 student student 4096 Jan 20 15:17 /home/student

[student@station student]$ chmod o+x ~


[student@station student]$ mkdir ~/pub
[student@station student]$ chmod o-r ~/pub
[student@station student]$ ls -al ~/pub
total 8
drwxrwx--x 2 student student 4096 Jan 20 15:17 .
drwx-----x 4 student student 4096 Jan 20 15:17 ..

54
[student@station student]$ mkdir ~/pub/music
[student@station student]$ chmod o-rx ~/pub/music/
[student@station student]$ chgrp music ~/pub/music
[student@station student]$ ls -al ~/p
total 16

Protección de subdirectorios dentro del directorio de inicio Lab Exercise Objetivo: Proteger un
subdirectorio recién creado dentro de su directorio de inicio, de una navegación no intencionada.

Estos ejercicios asumen que otros ya tienen permisos de ejecución (x) en su directorio de inicio.
Cree un subdirectorio memos en su directorio de inicio y modifique sus permisos de tal manera que
otros en el sistema no tengan acceso al directorio. Cree un archivo dentro del directorio y use una
de las cuentas alternas para confirmar que otros usuarios no puedan acceder al archivo.

Solución:La siguiente serie de comandos demostró una solución posible para las especificaciones
anteriores (la salida asume que usted acaba de completar el ejercicio anterior).

[student@station student]$ ls -ld ~


drwx-----x 4 student student 4096 Jan 20 16:50 /home/student
[student@station student]$ mkdir memos
[student@station student]$ chmod o-rx memos/
[student@station student]$ ls -l
total 8
drwxrwx--- 2 student student 4096 Jan 20 16:50 memos
drwxrwx--x 4 student student 4096 Jan 20 15:18 pub
[student@station student]$ echo "feed cat" > memos/todo

[student_a@station student_a]$ ls ~student/memos


ls: /home/student/memos: Permission denied
[student_a@station student_a]$ cat ~student/memos/todo
cat: /home/student/memos/todo: Permission denied

Deliverables A title Question

1. Un directorio llamado~/memos, que sólo el propietario del directorio puede navegar.


content_view let_

chmod Revisitado: Notación octal

Conceptos clave

• El comando chmod puede usar un sintaxis octal alterna


• La sintaxis octal es a menudo más rápida y más motivante.

Discussion

¿Por qué una sintaxis diferente?

55
En las lecciones anteriores, el comandochmod se utilizó para modificar permisos de un archivo
utilizando una sintaxis simbólica como la siguiente:

[student@station student]$ chmod og-r diary

Esta sintaxis tiene algunas ventajas y desventajas. Como la sintaxis es muy legible, la intención de
un comando es bastante evidente: el estudiante no quiere que otros usuarios lean el archivo diary..
¿Cuáles son los permisos resultantes en diary? Un problema de sintaxis es que, al saber que sólo
este comando fue ejecutado, usted no puede decir si el archivo tiene permisos de escritura para los
miembros del grupo o para otros. Sin saber los permisos originales, usted no puede saber.

Esta lección ilustrará una sintaxis octal alterna para el comando chmod, la cual resuelve estos
problemas:

[student@station student]$ chmod 600 diary

Después de aprender la sintaxis, usted sabría que, al ejecutar el comando anterior, el archivo diary
tendría permiso de rw-------. Como un beneficio agregado, una vez aprendida, la sintaxis octal
tiende a ser más rápida para el usuario.

¿De dónde salió 600?

Recuerde que un archivo tiene tres tipos diferentes de permisos (lectura (r), escritura (w) y
ejecución (x), para las tres clases de usuario: usuario propietario (u), grupo propietario (g), y otro
(o)). Con la notación octal, cada clase de acceso obtiene un dígito, las "centenas" para el usuario
(u); las "decenas" para el grupo (g) y las "unidades" para otro (o) . A cada tipo de permiso se le
concede un valor: (r) tiene 4, (w) tiene 2, y (x) tiene 1. Los dígitos de una notación octal son la
suma de los permisos concedidos para cada clase de acceso. Los siguientes ejemplos demuestran
cómo se traducen los números octales a una sintaxis convencional de permisos.

755 = rwxr-xr-x

7 = 4 + 2 + 1 = rwx for (u)ser


5 = 4 + 0 + 1 = r-x for (g)roup
5 = 4 + 0 + 1 = r-x for (o)ther

640 = rw-r-----

6 = 4 + 2 + 0 = rw- for (u)ser


4 = 4 + 0 + 0 = r-- for (g)roup
0 = 0 + 0 + 0 = --- for (o)ther

701 = rwx-----x

7 = 4 + 2 + 1 = rwx for (u)ser


0 = 0 + 0 + 0 = --- for (g)roup
1 = 0 + 0 + 1 = --x for (o)ther

Esta notación se llama la notación "octal" debido a que cada dígito tiene 8 posibles valores(de 0 a
7).

Modos de archivos

56
Una vez aprendida, la notación octal brinda una forma rápida de referirse a los permisos de
archivo. Por ejemplo, los administradores experimentados de Linux a menudo se referirán a un
permiso de archivo de "644" o de un directorio de "755". En Unix, al estado de los permisos de
archivo se les conoce como el modo de un archivo. En particular, este término se utiliza para
referirse a los permisos de archivo de notación octal. Por ejemplo, un administrador de sistema
podría decir que los "Directorios se crean con un modo predeterminado de 755".

Ejemplos

Creación de un directorio ~/pub (utilizando la notación octal)

Al usuario elvis le gustaría establecer un directorio compartido ~/drafts. Quisiera que los miembros
del grupo music tuvieran libre acceso al directorio y que otros usuarios no. Al utilizar el comando
chmod, elvis utilizará la notación octal.

[elvis@station elvis]$ mkdir ~/drafts


[elvis@station elvis]$ chmod 701 ~
[elvis@station elvis]$ chmod 770 ~/

[elvis@station elvis]$ echo "One for the honey" > ~/drafts/lyrics


[elvis@station elvis]$ chgrp -R music drafts/
[elvis@station elvis]$ ls -al drafts/
total 12
drwxrwx--- 2 elvis music 4096 Feb 14 10:16 .
drwx------ 5 elvis elvis 4096 Feb 14 10:15 ..
-rw-rw-r-- 1 elvis music 18 Feb 14 10:16 lyrics
En este uso del
comandochmod, elvis
pudo ajustar los
permisos de grupo (g)y
de otro (o) con un
simple comando.
¿Cómo habría tenido
que hacer esto
utilizando una notación
simbólica?
Observe que el
comando chgrp -Rle
dice a chgrp que vaya
de modo recursivo por
un directorio (y todos
sus subdirectorios). Los
comandos chmod y
chown tienen esta
opción.
"." siempre se refiere al
directorio actual en este
caso /home/elvis/drafts.
Recuerde que ".."
siempre se refiere al
directorio padre actual
en este
caso/home/elvis.

57
Mal uso de la notación octal

El usuario einstein tiene la siguiente serie de artículos, algunos ya han sido publicados, otros no.
Todos los archivos y direcciones tienen permisos predeterminados.

papers/
|-- published/
| `-- relativity
`-- unpublished/
|-- eismcsquared
|-- photoelectric_effect
`-- unlikely/
`-- time_travel

El usuario einstein ahora decide cambiar los permisos en todos sus archivos dentro de su directorio
sin publicar, para que otros usuarios no puedan leerlos. Con el fin de ahorrar tiempo, einstein
decide utilizar la forma recursiva del comando chmod.

[einstein@station einstein]$ chmod -R 660 papers/unpublished/*


chmod: failed to get attributes of
`papers/unpublished/unlikely/time_travel': Permission denied
[einstein@station einstein]$ ls papers/unpublished/unlikely/
ls: papers/unpublished/unlikely/time_travel: Permission denied
¿En qué se ha equivocado einstein? ¿Por qué ni siquiera puede ver su propio directorio? Preste
atención a los permisos de los archivos en papers/unpublished:

[einstein@station einstein]$ ls -l papers/unpublished/


total 4
-rw-rw---- 1 einstein einstein 0 Feb 14 10:46 eismcsquared
-rw-rw---- 1 einstein einstein 0 Feb 14 10:45
photoelectric_effect
drw-rw---- 2 einstein einstein 4096 Feb 14 10:46 unlikely

Cuando einstein ejecutó el comando chmod -R 660 papers/unpublished/*, el comando chmod


hizo lo que debe hacer. Estableció el modo de cada archivo como 660 (incluyendo el directorio
unlikely). Luego trató de ir en forma recursiva al directorio unlikely, pero como el directorio ahora
tiene el modo 660, einstein ya no tiene permiso de acceso a su propio directorio y el comando
¡falla!

¿Qué lección nos deja este ejemplo? Los directorios y archivos regulares tienen diferentes
permisos "razonables". Por ejemplo, los directorios deben tener establecido el permiso de ejecutar
(x), mientras que, por lo general, los archivos regulares no. Infortunadamente, el comando chmod -
R no distingue entre archivos y directorios.

(Con el fin de obtener el resultado deseado, einstein podría utlilizar el comando find para buscar de
modo recursivo. Dicho comando find se presentará en la siguiente sección).

Ejercicios en línea

58
Administración de Permisos en Grupos de Archivos Lab Exercise Objetivo: Administrar permisos
en un grupo grande de archivos, utilizando la notación octal.

Configuración

Su segunda cuenta alterna (student_b) debe ser miembro del grupo emperors. Inicie la sesión bajo
esa cuenta y cree un directorio ~/reports y ejecute el comando cd en ese directorio.

[student_b@station student_b]$ groups


student_b emperors
[student_b@station student_b]$ mkdir reports
[student_b@station student_b]$ cd reports

Use el siguiente comando "mágico" para crear un número grande de archivos en el directorio
actual. La sintaxis de paréntesis que está utilizando será presentada en un cuaderno posterior.

[student_b@station reports]$ touch {2001,2002,2003}.{q1,q2,q3,q4}.


{data,draft,final}
[student_b@station reports]$ ls
2001.q1.data 2001.q3.final 2002.q2.draft 2003.q1.data 2003.q3.final
2001.q1.draft 2001.q4.data 2002.q2.final 2003.q1.draft 2003.q4.data
2001.q1.final 2001.q4.draft 2002.q3.data 2003.q1.final 2003.q4.draft
2001.q2.data 2001.q4.final 2002.q3.draft 2003.q2.data 2003.q4.final
2001.q2.draft 2002.q1.data 2002.q3.final 2003.q2.draft
2001.q2.final 2002.q1.draft 2002.q4.data 2003.q2.final
2001.q3.data 2002.q1.final 2002.q4.draft 2003.q3.data
2001.q3.draft 2002.q2.data 2002.q4.final 2003.q3.draft

Observe que todos los archivos tienen permisos predeterminados.

Especificaciones

Desea implementar los siguientes principios

1. Todos los archivos (incluyendo directorios) deberían pertenecer al grupo emperors.


2. Todos los archivos que terminen en .data contienen datos crudos. Cualquiera pueda leer
los archivos, pero solo usted tiene derecho a modificarlos.
3. Todos los archivos que terminen en .draft contienen borradores de trabajo de sus informes,
en los cuales usted desea ayudar. Los miembros del grupo emperors deberían poder leer y
modificar los archivos, pero otros usuarios no deberían tener acceso a ellos.
4. Todos los archivos terminados en .finalson borradores finales. Usted desea moverlos a un
directorio dedicado ~/reports/final. Solo los miembros del grupo emperors deberían tener
accceso al subdirectorio, poder listar el contenido del directorio y poder leer los informes
(pero no modificarlos).

Use el comando chmod con una notación octal para obtener estos resultados.

Deliverables A title Question 1

59
El directorio ~/reports y todos sus archivos y directorios subyacentes, deberían pertenecer al grupo
propietario emperor.

1. Un directorio ~/reports de libre acceso y lectura.


2. Una colección de archivos ~/reports/*.data, de lectura para todos, pero sólo con permiso de
escritura para usted.
3. Una serie de archivos ~/reports/*.draft, de lectura y escritura sólo para miembros del grupo
emperor.
4. Un directorio ~/reports/final de acceso y lectura solo para miembros del grupo emperor.

Una colección de archivos ~/reports/final/*.final, de escritura y lectura para el propietario del


archivo, pero de lectura y de no escritura para los miembros del grupo emperor. Otros usuarios no
tendrían acceso.

Possible Solution

The following sequence of commands provides one possible solution to this exercise.

[student_b@station reports]$ chmod 644 *.data


[student_b@station reports]$ chmod 660 *.draft
[student_b@station reports]$ chmod 640 *.final
[student_b@station reports]$ mkdir final
[student_b@station reports]$ chmod 750 final/
[student_b@station reports]$ mv *.final final/
[student_b@station reports]$ chgrp -R emperors .

60
Control de permisos por defecto: umask

Conceptos clave

• A nivel de Kernel, Linux crea archivos con el modo por defecto de 666 (rw-rw-rw).
• En el nivel de kernel de Linux cree directorios con el modo por defecto de 777(rwxrwxrwx).
• Cada proceso posee un parámetro "umask", el cual desenmascará alguno de estos
permisos por defecto.
• En Red Hat Enterprise Linux, el umask por defecto para usuarios estándar es 002.
• La umask de la shell bash se puede modificar con el comando umask.

Discussion

Control de las permisos predeterminados con umask

En las lecciones anteriores vimos que los archivos recién creados tienen un modo por defecto de
664 (rw-rw-r--), lo que implica que todos pueden leer el archivo, pero únicamente el propietario de
archivo puede modificar un archivo recién creado. Igualmente, los directorios recién creados tienen
un modo por defecto de 775 (rwxrwxr-x), implicando que cualquier persona puede acceder o
navegar en el directorio, pero sólo el propietario del directorio puede añadir o borrar archivos.

Los permisos predetermiandos de los archivos recién creados se pueden alterar a través de un
concepto Unix estándar llamado umask. Cada proceso, incluyendo el comando de shell bash, tiene
un número octal de tres dígitos, el cual se utiliza para "desenmascarar". La umask está compuesta
justo como un modo octal, pero el significado es invertido. Como un modo octal, cada clase de
acceso es representado por un sólo dígito: (u)suario está en las "centenas", (g)rupo propietario en
las "decenas" y (o)tros en las "unidades". Como un modo octal, cada tipo de permiso tiene un valor,
4 para lectura (r), 2 para escritura (w), y 1 para ejecución(x). Sin embargo, a diferencia de los
modos octales, la umask está compuesta por valores de permisos no deseados.

Permisos predeterminados para archivos

Con el fin de determinar los permisos para archivos recién creados, el kernel de Linux comienza
con un modo global por defecto de 666, (rw-rw-rw). El kernel luego aplica la umask para el proceso
que creó el archivo. Todos los valores asignados en la umask son "revelados" de los permisos
predeterminado de 666. Por ejemplo, una umask de 002 resultaría en permisos por defecto de 664:

kernel default: 666 --> rw-rw-rw-


umask: 002 --> -------w-
-----------------------------------------
default permissions: 664 --> rw-rw-r--

Otro ejemplo, una umask de 077 resultaría en permisos por defecto de 600:

kernel default: 666 --> rw-rw-rw-


umask: 077 --> ---rwxrwx
-----------------------------------------
default permissions: 600 --> rw-------

61
Al determinar los permisos por defecto, cualquier permiso que sea asignado en la umask es
"desenmascarado" del kernel predeterminado.

Permisos predeterminados para directorios

Los permisos predeterminados para los directorios se crean utilizando la misma técnica, excepto
que el modo por defecto del kernel para directorio es 777 (rwxrwxrwx). Por ejemplo, una umask de
002 resultaría en permisos por defecto para directorios de 775:

kernel default: 777 --> rwxrwxrwx


umask: 002 --> -------w-
-----------------------------------------
default permissions: 775 --> rwxrwxr-x

Igualmente, una umask de 077 resultaría en permisos predeterminados de 700:

kernel default: 777 --> rwxrwxrwx


umask: 077 --> ---rwxrwx
-----------------------------------------
default permissions: 700 --> rwx------

Observe que, en ambos casos, una umask de 002 tiene el mismo efecto general para los archivos
y directorios. Cualquiera puede leer, pero sólo el propietario puede modificar. Igualmente, una
umask de 077 tiene el mismo efecto general tanto en archivos como en directorios: el usuario
propietario puede leer y modificar, pero nadie más tiene acceso.

Modificación de la umask de shell: el comando umask

La umask de shell bash se puede examinar y modificar con el comando umask. Cuando se llama
sin argumentos, el comando umask reporta la umask de shell actual. Cuando se llama con una
umask octal como un único argumento, se le asigna a la umask de shell el valor especificado.

[student@station student]$ umask


0002
[student@station student]$ umask 077
[student@station student]$ umask
0077

(Observe que, en la salida, la umask se reporta como un número octal de cuatro dígitos. Por ahora,
el "0" del comienzo se puede ignorar (su significado será más claro en la siguiente lección).

Ejemplos

Uso del comando umask para crear archivos compartidos por grupos

En la siguiente secuencia, blondie y otros músicos están colaborando con la letra de una canción.
A blondie le gustaría crear varios archivos que los miembros del grupo de music pueden ver y
modificar, pero que nadie más puede leer o escribir. Una posibilidad sería crear los archivos y

62
luego cambiar los permisos de archivo con chmod. En cambio, blondie va a utilizar el comando
umaskpara cambiar sus permisos por defecto de shell en los archivos recién creados.

[blondie@station blondie]$ umask


0002
[blondie@station blondie]$ umask 007
[blondie@station blondie]$ umask
0007

[blondie@station blondie]$ echo "Twinkle, twinkle, little star" >


song1.txt
[blondie@station blondie]$ echo "Bah, bah, black sheep" > song2.txt
[blondie@station blondie]$ echo "Mary had a little lamb" > song3.txt
[blondie@station blondie]$ chgrp music song*.txt
[blondie@station blondie]$ ls -l
total 12
-rw-rw---- 1 blondie music 30 Feb 20 14:20 song1.txt
-rw-rw---- 1 blondie music 22 Feb 20 14:20 song2.txt
-rw-rw---- 1 blondie music 23 Feb 20 14:20 song3.txt

Observe que la umask de shell de 007 "desenmascaró" los permisos que hubiesen podido ser
asignados por (o)tros.

Utilización de ~/.bashrc para cambiar automáticamente la umask de la shell bash

El emperador Nero, en un estado de paranoia está sospechando que los otros usuarios le están
mirando sus archivos. Quisiera configurar su shell bash de tal forma que cada vez que inicie, la
umask de la shell sea establecida automáticamente como 077. Hará esto editando el archivo
~/.bashrc, el cual por lo general, existe por defecto en el directorio de inicio del usuario.

Siempre que se inicia una nueva shell bash, los comandos listados en el archivo especialmente
nombrado ~/.bashrc se ejecutan como si fueran escritos desde la línea de comandos. Al anexar
"umask 077" al archivo ~/.bashrc de nero, él configurará su shell de tal forma que la umask de shell
automáticamente será configurada como 077 al iniciar.

En la siguiente secuencia, nero examina primero, luego agrega una nueva línea y después
reexamina su archivo ~/.bashrc. Por ahora, no se preocupe por el contenido original del archivo,
sólo observe que el archivo modificado ejecuta el umask como su último comando.

63
[nero@station nero]$ cat ~/.bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
[nero@station nero]$ echo "umask 077" >> ~/.bashrc
[nero@station nero]$ cat ~/.bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then

Ahora que nero ha modificado su archivo ~/.bashrc, su umask se establecerá automáticamente


como 077 cada vez que comience una nueva shell. Cuando nero sale y luego reinicia, los archivos
recién creados ahora tienen permisos por defecto de 600 (rw-------).

Red Hat Enterprise Linux release 3.0 (Taroon)


Kernel 2.4.20-4-ES on an i686

station login: nero


Password:
[nero@station nero]$ umask
0077
[nero@station nero]$ echo "All of Gaul is divided into three parts" >
notes.txt
[nero@station nero]$ ls -l
total 4
-rw------- 1 nero nero 40 Feb 20 14:44 notes.txt

Ejercicios en línea

Cambio de los permisos predeterminados de la shell bash.

Lab Exercise

Objetivo: Uso del archivo ~/.bashrc para cambiar los permisos por defecto de la shell bash.

Estimated Time: 10 mins.

Especificaciones

Cada vez que inicie una shell bash, el contenido del archivo ~/.bashrcse ejecutará como si los
hubiera escrito en la línea de comandos. Este archivo se utiliza a menudo para personalizar la
conducta predeterminada de bash.

64
Si quiere que su umask de shell por defecto sea cambiada automáticamente cada vez que inicia
una sesión, agregue una línea al final de su archivo ~/.bashrc, el cual establece la umask de la
shell. Los archivos recién creados deberían ser de lectura para todos, pero de escritura únicamente
para el usuario propietario por defecto.

Deliverables A title Question 1

Un archivo ~/.bashrc que establecezca la umask de shell bash por defecto de tal manera que los
archivos sean de lectura para todos pero sólo de escritura para el usuario propietario del archivo
(en particular, el archivo no debería ser de escritura para el grupo propietario).

Possible Solution

The following sequence of commands provides one possible solution to this exercise.

[student@station student]$ echo "umask 022" >> .bashrc


[student@station student]$ cat .bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
umask 022

Al salir e iniciar de nuevo, usted debería ver el siguiente comportamiento.

[student@station student]$ date > test_file.txt


[student@station student]$ ls -l
total 4
-rw-r--r-- 1 student student 29 Feb 20 14:52 test_file.txt

Observe que los permisos de los archivos recién creados es 644, no el permiso por defecto de Red
Hat de 664.

Limpieza

Después de haber evaluado este ejercicio, suprima de su archivo~/.bashrc la línea que ha


agregado.

65
The Linux FileSystem
Detalles de archivo

Conceptos clave

• El término archivo se refiere a los archivos regulares, directorios, enlaces simbólicos,


nodos de dispositivo y otros.
• Todos los archivos tienen atributos comunes: usuario propietario, grupo propietario,
permisos y la información de temporización. Esta información se almacena en una
estructura llamada inodo.
• Los nombres de archivos se encuentran en estructuras de datos llamadas dentries (del
inglés directory entries).
• La información de un inodo un de archivo se puede examinar con los comandos ls -l y stat.
• Dentro del kernel de Linux, los archivos están generalmente identificados por un número
de inodo. El comando ls -i se puede utilizar para examinar los números de inodo.

Discussion

Cómo guarda archivos Linux

Suponga que elvis abre el editor de texto y hace la siguiente lista de mercado.

Eggs
bacon
milk

Cuando termina, y cierra el editor, le preguntan cómo le gustaría llamar al archivo. Escoge
shopping.txt. Luego, lista el contenido del directorio para asegurarse de que esté ahí.

[elvis@station elvis]$ ls -l
total 4
-rw-rw-r-- 1 elvis elvis 16 Jul 11 07:54 shopping.txt

Este corto ejemplo ilustra los tres componentes que Linux asocia con un archivo.

data

Los datos son el contenido del archivo, en este caso, los 16 bytes que componen la lista
del mercado de elvis (13 caracteres visibles y 3 invisibles de "retorno" que indican el final
de la línea). En Linux como en Unix, cada contenido de archivo se almacena como una
serie de bytes.

metadatos

Además de su contenido, en Linux cada archivo tiene información adicional asociada a


éste. Todo el cuaderno anterior estuvo enfocado en dicha información, es decir, el

66
propietario de archivo, el grupo propietario y los permisos. Información, tal como la última
vez que el archivo fue modificado o leído, también se almacena. Muchos de estos
metadatos son reportados al ejecutar el comando ls -l. En Linux (Unix), toda la información
adicional asociada al archivo (con la excepción importante que pronto veremos) se
almacena en una estructura llamada inodo.

filename

El nombre de archivo es la excepción a la regla. Aunque el nombre del archivo podría


considerarse como metadatos asociados con el archivo, éste no se almacena directamente
en el inodo. En su lugar, el archivo se almacena en una estructura llamada dentry, (el
términodentry es un acortamiento para directory entry, y como veremos más adelante, la
estructura está asociada a los directorios). En esencia, el nombre de archivo asocia un
nombre con un inodo.

En resumen, hay tres estructuras asociadas con cada archivo: unadentry, la cual contiene un
nombre de archivo y se refiere a un inodo, el cual contiene los metadatos del archivo y se refiere a
datos del archivo. El entender las relaciones entre estas estructuras le ayudará a entender más
adelnate otros conceptos, tales como enlaces y directorios. Estas estructuras están resumidas así:

Figure 1. Estructuras de archivos

¿Qué hay en un inodo?

En Linux (y Unix), cada archivo existente en el sistema de archivos tiene un inodo asociado, el cual
almacena toda la información de los archivos, a excepción del nombre de archivo. ¿Qué puede
encontrar en un inodo?

Tipo de archivo

En Linux (y UNIX), el término archivo tiene un significado muy general: cualquier cosa que
exista en el sistema de archivos (y por tanto, tiene un inodo asociado con éste) es un
archivo. Esto incluye archivos regulares y directorios, que ya hemos visto, enlaces
simbólicos y nodos de dispositivos que veremos pronto, y un par de criaturas más oscuras

67
relacionadas con la comunicación entre procesos y que van más allá del alcance del curso.
Los posibles tipos de archivos se presentan en la siguiente tabla.

Table 1. Tipos de archivos Linux (Unix)

Tipo de archivo ls Uso


abbr.
Archivo regular - Almacemiento de datos
Directorios d Organización de archivos
Enlaces simbólicos l Referencia a otros archivos
Nodos de dispositivos de caracteres c Acceso a dispositivos
Nodos de dispositivos de bloques b Acceso a dispositivos
Tuberías nombradas p Comunicación entre procesos
Sockets s Comunicación entre procesos

Cada uno de los siete tipos de archivos mencionados anteriormente utiliza la misma
estructura de inodo, por lo tanto, cada uno tiene los mismos tipos de atributos: propietarios,
permisos, modificar tiempos, etc. Cuando se listan los archivos con ls -l, el tipo de archivo
del archivo es identificado por el primer caracter, utilizando las abreviaturas de la segunda
columna.

Note

El término file está sobrecargado en Linux (Unix) y tiene dos significados. Cuando se utiliza
en oraciones tales como "cada archivo tiene un inodo", el término se refiere a cualquiera de
los tipos de archivo listados en el cuadro anterior. Cuando se utiliza en oraciones tales como
"El comando head sólo funciona en archivos, no en directorios", el término archivo se refiere
sólo al tipo específico de archivo que contiene datos. Por lo general, el significado es claro en
el contexto. Cuando tiene que hacerse alguna distinción, se utiliza el término archivo regular
como en "El comando ls -l identifica archivos regulares con un guión (-)".
Propiedades y Permisos

Como lo discutimos en el cuaderno anterior, cada archivo y directorio regular tiene un


grupo propietario, un usuario propietario y una serie de permisos de escritura, lectura y
ejecución. Debido a que esta información se almacena en un inodo de archivo, y la
estructura de inodo es la misma para todos los archivos, todos los siete tipos de archivos
usan los mismos mecanismos para controlar quién tiene acceso a ellos, a saber chmod,
chgrp, y chown.

Al listar archivos con ls -l, la primera columna muestra los permisos (y el tipo de archivo),
la tercera, el usuario propietario y la cuarta, el grupo propietario.

Información de temporización

Cada inodo almacena tres tiempos importantes para el archivo: el atime , el ctime y el
mtime . Estos tiempos registran la última vez que se tuvo acceso (leído), cambiado, o
modificado, respectivamente.

Table 2. Tiempos de Archivo

Abbreviation Nombre Propósito


atime Tiempo de acceso Actualiza cada vez que los datos del archivo son leídos

68
ctime Cambia Tiempo Actualiza cada vez que la información del inodo de archivo
cambia
mtime Última Actualiza cada vez que cambian los datos del archivo
modificación

¿Cuál es la diferencia entre cambiar y modificar ? Cuando cambian los datos de un


archivo, se dice que el archivo es modificado, y el mtime es actualizado. Cuando la
información de inodo de un archivo cambia, se dice que el archivo cambia y el ctime del
archivo se actualiza. Al modificar un archivo (y, por tanto, cambiar el mtime) el ctime
también se actualiza, cuando simplemente se lea un archivo (y, por tanto, cambie el atime)
el ctime no se actualiza.

¿Qué ocurre con el tiempo de creación?

A menudo, la gente confunde el ctime con un "tiempo de creación". Aunque parezca raro, el
Unix tradicional ( y Linux) no registra el tiempo preciso en que el archivo se creó. Algunas
personas han identificado la falta de un tiempo de creación como una debilidad en el diseño
del sistema de archivos de Unix.
Longitud y tamaño del archivo

El inodo registra dos medidas de longitud de un archivo: la longitud de un archivo (el


número real de bytes de datos), y el tamaño del archivo (la cantidad de espacio de disco
que el archivo utiliza). Los dos difirencian el bajo nivel de detalles de cómo se almacenan
los archivos en el disco. Por lo general, el tamaño del archivo aumenta en fragmentos
(suele ser 4 kilobytes) a la vez, mientras que la longitud aumenta byte por byte cada vez
que se agrega información al archivo. Cuando se listen los archivos con el comandols -l, la
longitud del archivo (en bytes) aparecerá en la quinta columna. En cambio, cuando se
listan los archivos con el comando ls -s se reporta el tamaño del archivo (en kilobytes).

Conteo de enlaces

Por último, el inodo registra un conteo de enlaces entre archivos o el número de dentries
(nombres de archivos) que se refieran al archivo. Por lo general, los archivos regulares
sólo tienen un nombre y el conteo de enlace es uno. Sin embargo, esto no siempre es el
caso. Al listar los archivos con ls -l, la segunda columna entrega el conteo de enlaces.

Ver la información del inodo con el comando stat

Red Hat Enterprise Linux incluye el comando stat para examinar en detalle la información del inodo
de un archivo. En la programación de Unix, a una colección de archivos de información de inodo se
le denomina estatus del archivo. El comando stat reporta el estatus de un archivo.

Note

El comando stat generalmente no está instalado por defecto en Red Hat Enterprise Linux. Si
se encuentra con que su máquina no tiene el comando stat, haga que su instructor le instale
el archivo del paquete stat RPM.

stat [OPCIÓN] ARCHIVO...

Muestra la información sobre el estatus del archivo (o el sistema de archivos).

69
Opción Efecto
-c, Sólo muestra la información solicitada usando el formato especificado. Para
--format=FORMAT mayor información, vea la página del manual stat (1).
-f, --filesystem Muestra la información sobre el sistema de archivos al que el archivo
pertenece, en lugar del archivo.
-t, --terse Muestra salida en formato terso (una línea)

En el siguiente ejemplo, madonna examina la información del inodo en el


archivo/usr/games/fortune.

[madonna@station madonna]$ stat /usr/games/fortune


File: `/usr/games/fortune'
Size: 17795 Blocks: 40 IO Block: 4096 Regular
File
Device: 303h/771d Inode: 540564 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)

Access: 2003-07-09 02:36:41.000000000 -0400


Modify: 2002-08-22 04:14:02.000000000 -0400
Change: 2002-09-11 11:38:09.000000000 -0400

El nombre del archivo. Esta es la información que no está realmente almacenada en el inodo,
sino en la dentry, como se explicó anteriormente.
De modo poco práctico para la terminología presentada anteriormente, el comando stat
etiqueta la longitud de un "tamaño" de un archivo.
El número de bloques del sistema de archivos que el archivo consume. Aparentemente, el
comando stat está usando un tamaño de bloque de 2 kilobytes. [1]
El tipo de archivo, en este caso, un archivo regular.

El conteo de enlaces o número de nombres de archivo que se enlazan a este inodo (no se
preocupe si no entiende esto aún).
El usuario propietario del archivo, el grupo propietario y los permisos.

Los atime, mtime, y ctime para el archivo.

Ver la información del inodo con el comandols

Cuando el comando stat es conveniente para listar la información del inodo de archivos
individuales, el comando ls suele hacer un mejor trabajo resumiendo la información para varios
archivos. Volveremos a ver el comando ls, esta vez para discutir algunas de las opciones
importantes para mostrar la información del inodo.

ls [OPCIÓN...] ARCHIVO...

Lista los archivos FILE ..., o si es un directorio, lista el contenido de un directorio.

Opción Efecto
-a, --all Incluye archivos que empiezan con .
-d, --directorio Si ARCHIVO es un directorio, lista información acerca del directorio mismo y
no sobre el contenido del directorio.

70
-F, --clasificar Agrega al nombre de archivos alguno de estos *, /, =, @ ó | para indicar el
tipo de archivo.
-h, --leíble por Usa abreviaturas "leíbles por humanos"cuando reporta la longitud de
humanos archivos.
-i, --inodo Lista el número de índice de cada inodo de archivo.
-l Usa formato de listado largo
-n, --numeric-uid- Usa UIDs y GIDs numéricos en vez de nombres de usuario y nombres de
gid grupo.
-r, --reverse Invierte el orden de la clasificación.
-R, --recursivo Lista subdirectorios de modo recursivo.
--time=WORD Reporta (o clasifica) tiempo especificado por WORD en lugar de mtime.
WORD puede ser "atime", "access", "ctime" o "estatus".
-t Clasifica por tiempo de modificación.

En el siguiente ejemplo, madonna toma un listado largo de todos los archivos en el directorio
/usr/games. Los diferentes elementos que ls -l reporta se discuten en detalle.

[madonna@station madonna]$ ls -l /usr/games/


total 28
drwxr-xr-x 3 root root 4096 Jan 29 09:40 chromium
-rwxr-xr-x 1 root root 17795 Aug 22 2002 fortune
dr-xrwxr-x 3 root games 4096 Apr 1 11:49 Maelstrom

El número total de bloques que los archivos utilizan en el directorio (observe que esto no
incluye subdirectorios).
El tipo de archivo y los permisos del archivo.

El conteo de enlaces del archivo o el número total de dentries (nombres de archivos) que se
refieren a este archivo (observe que, para los directorios, éste es siempre mayor que ¡1!
ummm...)
El propietario del archivo.

El grupo propietario del archivo.

La longitud del archivo en bytes (observe que los directorios tienen una longitud también y que
la longitud parece aumentar en bloques, ummm....)
El mtime del archivo o la última vez que se modificó el archivo.

Identificación de archivos por inodo

Mientras que la gente tiende a usar nombres de archivos para identificar archivos, el kernel de
Linux suele usar el inodo directamente. Dentro de un sistema de archivos, a cada inodo se le
asigna un número único de inodo. El número inodo de un archivo se puede listar con la opción -i
para el comando ls.

71
[elvis@station elvis]$ ls -s /bin
total 4860
4 arch 0 domainname 20 login 92 sed
96 ash 56 dumpkeys 72 ls 32 setfont
488 ash.static 12 echo 72 mail 20 setserial
12 aumix-minimal 44 ed 20 mkdir 0 sh
0 awk 4 egrep 20 mknod 16 sleep
...

En este ejemplo, el directorio chromium tiene un número inodo de 540838. Un archivo se puede
identificar de manera única si se conoce su sistema de archivos y el número de inodo.

Ejemplos

Comparar tamaños de archivo con ls -s y ls -l

El usuario elvis está examinando los tamaños de los archivos ejecutables en el directorio /bin.
Primero ejecuta el comando ls -s.

[elvis@station elvis]$ ls -l /bin


total 4860
-rwxr-xr-x 1 root root 2644 Feb 24 19:11 arch
-rwxr-xr-x 1 root root 92444 Feb 6 10:20 ash
-rwxr-xr-x 1 root root 492968 Feb 6 10:20 ash.static
-rwxr-xr-x 1 root root 10456 Jan 24 16:47 aumix-minimal
lrwxrwxrwx 1 root root 4 Apr 1 11:11 awk -> gawk
...

Luego para cada nombre de archivo, el comando ls reporta el tamaño del archivo en kilobytes. Por
ejemplo, el archivo ash ocupará 96 Kbytes de espacio en el disco. En la salida (abreviada), que
todos los tamaños son divisibles por cuatro. Aparentemente, cuando se almacena un archivo en el
disco, el espacio de disco asigna espacio de disco a los archivos en fragmentos de 4 Kbytes, (esto
se denomina un "tamaño de bloque" del sistema de archivos). Tenga en cuenta que el archivo awk
parece no estar ocupando ningún espacio.

Luego, elvis examina la información del directorio mediante el comando ls -l.

[elvis@station elvis]$ ls -ld /bin


drwxr-xr-x 2 root root 4096 Jul 8 09:29 /bin

Esta vez, las longitudes de los archivos se reportan en bytes. Volviendo a mirar en el archivo ash,
la longitud es reportada como 92444 bytes. Esto es razonable porque redondeando a los próximos
4 Kilobytes, obtenemos los 96 Kbytes reportados por el comando ls -s. Observe otra vez el archivo
awk. El archivo no es un archivo regular, sino un enlace simbólico, lo que explica el porqué no
estaba consumiendo espacio. Los enlaces simbólicos se verán en más detalle próximamente.

Por último, elvis quiere saber acerca de los permisos en el directorio /bin. Sin embargo, cuando
ejecuta ls -l /bin, obtiene una lista de contenido del directorio /bin, no del directorio mismo.
Resuelve su problema agregando la opción -d.

72
[madonna@station madonna]$ ls -iF /usr/games/
540838 chromium/ 540564 fortune* 312180 Maelstrom/

Listar archivos, ordenados de acuerdo con la última modificación

El usuario prince está explorando los archivos de registro del sistema en el directorio /var/log. Le
interesa saber acerca de la actividad reciente en el sistema, por eso quiere saber cuáles archivos
han sido accedidos recientemente. Hace un listado largo del directorio y comienza a examinar las
últimas modificaciones reportadas de los archivos.

[prince@station prince]$ ls -l /var/log


total 16296
-rw------- 1 root root 20847 Jul 12 2002 boot.log
-rw------- 1 root root 45034 Jul 6 2002 boot.log.1
-rw------- 1 root root 29116 Jun 29 2002 boot.log.2
-rw------- 1 root root 18785 Jun 22 2002 boot.log.3
-rw------- 1 root root 15171 Jun 15 2002 boot.log.4
drwxr-xr-x 2 servlet servlet 4096 Jan 20 2002 ccm-core-cms
-rw------- 1 root root 57443 Jul 12 2002 cron
-rw------- 1 root root 62023 Jul 6 2002 cron.1
-rw------- 1 root root 74850 Jun 29 2002 cron.2
...

Con 74 archivos para examinar, prince rápidamente se cansa de revisar los archivos recientes.
Decide dejarle este trabajo dispendioso al comando ls, especificando que la salida se debería
ordenar por mtime con la opción -t.

[prince@station prince]$ ls -lt /var/log


total 16296
-rw------- 1 root root 57443 Jul 12 2002 cron
-rw------- 1 root root 2536558 Jul 12 2002 maillog
-rw------- 1 root root 956853 Jul 12 2002 messages
-rw-rw-r-- 1 root utmp 622464 Jul 12 2002 wtmp
-rw-r--r-- 1 root root 22000 Jul 12 2002 rpmpkgs
-rw-r--r-- 1 root root 38037 Jul 12 2002 xorg.0.log
....

Ahora elvis puede leer fácilmente los archivos cron, maillog y messages como los archivos
modificados más recientemente. Interesado en saber cuáles archivos de registro no se están
utilizando, prince repite el comando, agregándole la opción -r.

73
[prince@station prince]$ ls -ltr /var/log
total 16296
-rw-r--r-- 1 root root 32589 Oct 23 2001 xorg.1.log.old
drwxr-xr-x 2 servlet servlet 4096 Jan 20 2002 ccm-core-cms
drwxr-xr-x 2 root root 4096 Feb 3 2002 vbox
-rwx------ 1 postgres postgres 0 Apr 1 2002 pgsql
drwx------ 2 root root 4096 Apr 5 2002 samba
-rw-r--r-- 1 root root 42053 May 7 2002 xorg.1.log
-rw-r--r-- 1 root root 1371 May 9 2002 xorg.setup.log
-rw------- 1 root root 0 Jun 9 2002 vsftpd.log.4
...

Representar listados con ls -F

La usuaria blondie está explorando el directorio /etc/X11.

[blondie@station blondie]$ ls /etc/X11/


applnk prefdm sysconfig xorg.conf.backup xkb
desktop-menus proxymngr twm xorg.conf.wbx
Xmodmap
fs rstart X xorg.conf.works
Xresources
gdm serverconfig xdm XftConfig.README-OBSOLETE
xserver
lbxproxy starthere xorg.conf xinit xsm

Dado que ella no tiene una terminal en color, tiene dificultad para distinguir entre un archivo regular
y un directorio. Agrega la opción -F para representar la salida.

[blondie@station blondie]$ ls -F /etc/X11/


applnk/ rstart/ xorg.conf Xmodmap
desktop-menus/ serverconfig/ xorg.conf.backup Xresources
fs/ starthere/ xorg.conf.wbx xserver/
gdm/ sysconfig/ xorg.conf.works xsm/
lbxproxy/ twm/ XftConfig.README-OBSOLETE
prefdm* X@ xinit/
proxymngr/ xdm/ xkb@

Ahora, los diversos archivos se representan por tipo. Los directorios terminan en un /, los enlaces
simbólicos en un @, y los archivos regulares con permisos ejecutables (lo que implica que son
comandos que se deben ejecutar) terminan en un *.

Ejercicios en línea

Ver los metadatos de un archivo Lab Exercise Objetivo: Listar archivos de acuerdo con la última
modificación Tiempo estimado: 5 minutos.

Especificaciones

74
1. Cree un archivo en su directorio de inicio llamado etc.bytime. El archivo debe contener un
listado largo del directorio /etc; ordenado de acuerdo con la última modificación. El archivo
modificado más reciéntemente debería estar en la primera línea del archivo.
2. Cree un archivo en su directorio de inicio llamado etc.bytime.reversed. El archivo debe
contener un listado largo del directorio /etc, ordenado a la inversa de acuerdo con la última
modificación. El archivo modificado más reciéntemente debería estar en la última línea de
la lista del archivo.
3. Cree un archivo llamado etc.inum que contenga el número de inodo del directorio /etc
como su único símbolo, (observe que está pidiendo el inodo del directorio mismo).

Deliverables A title Question 1

1. Un archivo llamado etc.bytime que contiene un listado largo de todos los archivos en el
directorio /etc, ordenado de acuerdo con la última modificación, con el primer archivo
modificado más recientemente en primer lugar.
2. Un archivo llamado etc.bytime.reversed que contiene un listado largo de todos los archivos
en el directorio /etc, ordenado de acuerdo con la última modificación, con el último archivo
más reciéntemente modificado, en primer lugar.
3. Un archivo llamado etc.inum que contiene el número de inodo del archivo del
content_view let_
directorio de archivo /etc como su único símbolo.

Final del formulario

Sugerencias

Las primeras líneas del archivo etc.bytime deberían verse de la siguiente manera, aunque los
detalles (tal como la última modificación) pueden diferir.

total 2716
-rw-r--r-- 1 root root 258 May 21 09:27 mtab
-rw-r--r-- 1 root root 699 May 21 09:13 printcap
-rw-r----- 1 root smmsp 12288 May 21 09:10 aliases.db
-rw-rw-r-- 2 root root 107 May 21 09:10 resolv.conf
-rw-r--r-- 1 root root 28 May 21 09:10 yp.conf
-rw------- 1 root root 60 May 21 09:10 ioctl.save
-rw-r----- 1 root root 1 May 21 09:10 lvmtab
drwxr-xr-x 2 root root 4096 May 21 09:10 lvmtab.d
-rw-r--r-- 1 root root 46 May 21 08:55 adjtime

75
Enlaces duros y blandos

Conceptos clave

• El comando ln crea dos tipos distintos de enlaces.


• Los enlaces duros asignan múltiples dentries (nombres de archivos) a un inodo único.
• Los enlaces blandos son inodos distintos que hacen referencia a otros nombres de
archivos.

Discussion

El caso de enlaces duros

En ocasiones, los usuarios de Linux quieren que el mismo archivo exista en dos lugares diferentes
o que tengan dos nombres diferentes. Un método es crear un enlace duro.

Suponga que elvis y blondie están colaborando en un dueto. A ellos les gustaría poder trabajar en
la letra de las canciones si el tiempo les permite y poder beneficiarse del trabajo uno del otro. En
lugar de copiar un archivo actualizado de cada uno, cada vez que hacen un cambio y mantener sus
copias individuales sincronizadas, deciden crear un enlace duro.

Blondie ha establecido un directorio de colaboración llamado ~/music, el cual es grupo propietario


con permiso de escritura de los miembros del grupo music. Ella hace que elvis haga lo mismo.
Luego crea el archivo ~/music/duet.txt, ejecuta chgrp al grupo music y usa el comando lnpara
enlazar el archivo en el directorio de elvis.

[blondie@station blondie]$ ls -ld music/


drwxrwxr-x 2 blondie music 4096 Jul 13 05:45 music/
[blondie@station blondie]$ echo "Knock knock" > music/duet.txt
[blondie@station blondie]$ chgrp music music/duet.txt
[blondie@station blondie]$ ln music/duet.txt /home/elvis/music/duet.txt

Debido a que el archivo fue enlazado y no copiado, es el mismo archivo bajo dos nombres. Cuando
elvis edita /home/elvis/music/duet.txt está editando también el archivo /home/blondie/music/duet.txt.

[elvis@station elvis]$ echo "who's there?" >> music/duet.txt

[blondie@station blondie]$ cat music/duet.txt


Knock knock
who's there?

Detalles de enlaces duros

¿Cómo se implementan los enlaces duros? Cuando se crea el archivo


/home/blondie/music/duet.txt, consta de dentry, inodo y datos, como se ilustra a continuación.

76
Figure 1. Archivo regular

Después de usar el comando ln para crear el enlace, el archivo es todavía un sólo inodo, pero
ahora hay dos dentries refiriéndose a éste.

Figure 2. Enlace duro

Cuando blondie ejecuta el comando ls -l, examina detenidamente en la segunda columna, la cual
reporta el conteo de enlace para el archivo.

[blondie@station blondie]$ ls -l music/duet.txt


-rw-rw-r-- 2 blondie music 25 Jul 13 06:08 music/duet.txt

Hasta ahora, no hemos prestado atención al conteo de enlaces y casi siempre ha sido 1 para
archivos regulares (implicando una dentry que hace referencia a un inodo). Sin embargo, ahora,
dos dentries hacen referencia al inodo y el archivo tiene un conteo de enlace 2. Si blondie cambia
los permisos en el archivo /home/blondie/music/duet.txt, ¿qué sucede al archivo /home/elvis/music/
duet.txt?

[blondie@station blondie]$ chmod o-r music/duet.txt

77
[elvis@station elvis]$ ls -l music/duet.txt
-rw-rw---- 2 blondie music 25 Jul 13 06:08 music/duet.txt
Puesto que ambas partes del enlace comparten el mismo inodo, elvis también ve los permisos
cambiados.

¿Qué sucede si blondie suprime /home/blondie/music/duet.txt? El inodo /home/elvis/music/duet.txt


aún existe, pero con una dentry menos que hace referencia a éste.

[blondie@station blondie]$ rm music/duet.txt

Figure 3. Enlace duro despues de suprimir la mitad

¿Cómo esperaría que fuera ahora el conteo de enlaces del archivo /home/elvis/music/duet.txt?

[elvis@station elvis]$ ls -l music/duet.txt


-rw-rw---- 1 blondie music 25 Jul 13 06:08 music/duet.txt

Un poco incómodo, elvis se ha quedado con un archivo de blondie, no obstante, aún es un archivo
válido. En un nivel bajo, el comando rm no borra un archivo, sino que lo "desenlaza". Un archivo
(es decir, el inodo de archivo y los datos) se borran automáticamente desde el sistema cuando su
conteo de enlace va hasta 0 (lo que implica que no hay más dentries (nombres de archivo)
haciendo referencia al archivo).

El caso de los enlaces blandos

Al otro método para asignar dos nombres a un archivo único se le denomina un enlace blando.
Aunque de modo superficial son similares, los enlaces blandos se implementan de una manera
muy diferente a la de los enlaces duros.

La usuaria madonna es muy organizada y ha agrupado sus tareas en siete listas, una para cada
día de la semana.

78
[madonna@station madonna]$ ls todo/
friday.todo saturday.todo thursday.todo wednesday.todo
monday.todo sunday.todo tuesday.todo

Consulta la lista varias veces al día, pero nota que le cuesta trabajo recordar qué día de la semana
es hoy. Preferiría tener un archivo único llamado today.todo que se actualice cada mañana. Decide
utilizar un enlace blando en su lugar. Debido a que hoy es martes (Tuesday en inglés), usa el
mismo comando ln utilizado para crear enlaces duros, pero agrega la opción de línea de comando
-s para especificar el enlace blando.

[madonna@station todo]$ ls
friday.todo saturday.todo thursday.todo wednesday.todo
monday.todo sunday.todo tuesday.todo
[madonna@station todo]$ ln -s tuesday.todo today.todo
[madonna@station todo]$ ls -l
total 32
-rw-rw-r-- 1 madonna madonna 138 Jul 14 09:54 friday.todo
-rw-rw-r-- 1 madonna madonna 29 Jul 14 09:54 monday.todo
-rw-rw-r-- 1 madonna madonna 579 Jul 14 09:54 saturday.todo
-rw-rw-r-- 1 madonna madonna 252 Jul 14 09:54 sunday.todo
-rw-rw-r-- 1 madonna madonna 519 Jul 14 09:54 thursday.todo
lrwxrwxrwx 1 madonna madonna 12 Jul 14 09:55 today.todo ->
tuesday.todo
-rw-rw-r-- 1 madonna madonna 37 Jul 14 09:54 tuesday.todo
-rw-rw-r-- 1 madonna madonna 6587 Jul 14 09:55 wednesday.todo

Examine de cerca el tipo de archivo (el primer caracter de cada línea en el comando ls -l) del
archivo recién creado today.todo. Este no es un archivo regular ("-"), ni un directorio ("d"), sino un
"l", indicando un enlace simbólico. Un enlace simbólico, también denominado enlace "blando", es
un archivo que hace referencia a otro archivo por nombre de archivo. Los enlaces blandos son
similares a alias encontrados en otros sistemas operativos. Afortunadamente, el comando ls -l
también muestra a qué archivo el enlace blando hace referencia, donde today.todo -> tuesday.todo
implica el enlace blando denominado today.todo hace referencia al archivo tuesday.todo.

Ahora, cada vez que madonna haga referencia al archivo today.todo, estará en realidad
examinando el archivotuesday.todo.

[madonna@station todo]$ cat today.todo


feed cat
take out trash
water plants
[madonna@station todo]$ cat tuesday.todo
feed cat
take out trash
water plants

Detalles de los enlaces blandos

¿Cómo se implementan los enlaces blandos? Al ser creado, el archivotuesday.txt, igual que la
mayoría de archivos, consta de una dentry, un inodo, y datos, como se ilustra en la parte de abajo.
Cuando el enlace blando today.txt fue creado, el enlace blando (a diferencia del enlace duro) es en

79
realidad un archivo nuevo, con un inodo recién creado. Sin embargo, el enlace no es un archivo
regular, sino un enlace simbólico. Los enlaces simbólicos, en lugar de almacenar datos reales,
almacenan el nombre de otro archivo. Cuando se le pide al kernel de Linux referirse a los enlaces
simbólicos, el kernel automáticamente apunta al enlace buscando el nuevo nombre de archivo. El
usuario (o en realidad, el proceso en nombre del usuario) que hizo referencia al enlace simbólico
no conoce la diferencia.

Figure 1. Enlaces blandos

Creación de enlaces con el comando ln

Como se ilustró anteriormente, tanto los enlaces duros como los blandos se crean con el comando
ln.

ln [OPCIÓN...] DESTINO [ENLACE]

Crea el enlace que hace referencia al archivo DESTINO.

ln [OPCIÓN...] DESTINO... [DIRECTORIO]

Crea enlace(s) para el (los)archivo(s) DESTINO en el directorio DIRECTORIO.

Opción Efecto
-f, --force sobrescribir archivos de destino existentes
-s, --symbolic hacer un enlace simbólico (blando) en lugar de un enlace duro

El comando ln se comporta de un modo similar al comando cp: si el último argumento es un


directorio, el comando crea enlaces en el directorio especificado que refieren a los argumentos
anteriores (y se nombran de un modo idéntico). A diferencia del comando cp, si sólo se da un
argumento, el comando ln asumirá un último argumento de ".". Al especificar enlaces, el comando
ln espera primero el nombre del (los) archivo(s) original(es) y el nombre del último enlace. Invertir

80
el orden primero no genera los resultados esperados.Otra vez, cuando tenga alguna duda,
recuerde la conducta del comandocp.

En el siguiente ejemplo corto, madonna crea el archivo orig.txt. Luego trata de hacer un enlace
duro para éste llamado newlnk.txt, pero obtiene el orden de los argumentos incorrectamente.
Dándose cuenta del error, corrige el problema.

[madonna@station madonna]$ date > orig.txt


[madonna@station madonna]$ ln newlnk.txt orig.txt
ln: accessing `newlnk.txt': No such file or directory
[madonna@station madonna]$ ln orig.txt newlnk.txt

Problemas con enlaces blandos

Enlaces colgantes

Los enlaces blandos son susceptibles a un par de problemas que los enlaces duros no tienen. El
primero se llama enlaces colgantes. ¿Qué sucede si madonna renombra o suprime el archivo
tuesday.todo?

[madonna@station todo]$ mv tuesday.todo tuesday.hide


[madonna@station todo]$ ls -l
total 32
-rw-rw-r-- 1 madonna madonna 138 May 14 09:54 friday.todo
-rw-rw-r-- 1 madonna madonna 29 May 14 09:54 monday.todo
-rw-rw-r-- 1 madonna madonna 579 May 14 09:54 saturday.todo
-rw-rw-r-- 1 madonna madonna 252 May 14 09:54 sunday.todo
-rw-rw-r-- 1 madonna madonna 519 May 14 09:54 thursday.todo
lrwxrwxrwx 1 madonna madonna 12 May 14 09:55 today.todo ->
tuesday.todo
-rw-rw-r-- 1 madonna madonna 37 May 14 10:22 tuesday.hide
-rw-rw-r-- 1 madonna madonna 6587 May 14 09:55 wednesday.todo
[madonna@station todo]$ cat today.todo
cat: today.todo: No such file or directory

El enlace simbólico today.todo aún hace referencia al archivo tuesday.todo, pero el archivo
tuesday.todo ¡ya no existe! Cuando madonna trata de leer el contenido de today.todo, encuentra un
error.

Figure 1. Enlaces colgantes

81
Enlaces recursivos

En segundo lugar, los enlaces simbólicos son susceptibles a los enlaces recursivos. En el uso
diario, los enlaces recursivos no son tan comunes como los enlaces colgantes, y alguien casi que
tiene que buscarlos para poder crearlos. ¿Qué sucede si alguien tiene que estar buscándolos para
crearlos? ¿Qué ocurre si madonna crea dos enlaces simbólicos, link_a, que hagan referencia a un
archivo llamado link_b, ylink_b, el cual hace referencia al archivo link_a, como se ilustra a
continuación?

[madonna@station madonna]$ ln -s link_a link_b


[madonna@station madonna]$ ln -s link_b link_a
[madonna@station madonna]$ ls -l
total 0
lrwxrwxrwx 1 madonna madonna 6 Jul 14 10:41 link_a -> link_b
lrwxrwxrwx 1 madonna madonna 6 Jul 14 10:41 link_b -> link_a
Figure 1. Enlaces recursivos

Cuando madonna trata de leer el archivo link_a, el kernel apunta al enlace _a para enlazar_b, el
cual luego vuelve a apuntar al enlace _a y así sucesivamente. Afortunadamente, el kernel solo

82
apuntará a un enlace muchas veces antes de sospechar de que se encuentra en un enlace
recursivo, y desiste.

[madonna@station madonna]$ cat link_a


cat: link_a: Too many levels of symbolic links

Enlaces relativos vs. enlaces relativos blandos

Al crear enlaces blandos, los usuarios pueden elegir entre especificar el enlace del destino
mediante una referencia relativa o absoluta. Si el enlace blando y su destino, nunca van a ser
reubicados la opción no importa. Sin embargo, los usuarios a menudo no pueden prever cómo se
van a utilizar en el futuro los archivos que crean. Normalmente, los enlaces relativos son más
resistentes a cambios inesperados.

Comparar enlaces duros y blandos

¿Cuándo debería utilizarse un enlace blando y cuándo un enlace duro? Generalmente, los enlaces
duros son más apropiados si ambas instancias del enlace tienen un uso razonable, incluso si la
otra instancia no existiera. En el ejemplo anterior, incluso si blondie decidiera no trabajar en el
dueto y removiera el archivo, elvis podría continuar trabajando razonablemente sin el otro archivo.
En el ejemplo anterior, madonna no hubiera podido tener tareas para "today" si no hubiera tenido
para "tuesday". Estos lineamientos generales, sin embargo, no endurecen ni agilizan las reglas.

Algunas veces, restricciones más prácticas escogen de una manera más fácil entre enlaces duros
y blandos. A continuación, se muestran algunas diferencias entre los enlaces duros y blandos. No
se preocupe si no entiende los dos últimos puntos, estos se mencionan aquí para completar la
información proveída.

Table 1. Comparar enlaces duros y blandos

Enlaces duros Enlaces blandos


Los directorios pueden no tener enlaces Los enlaces blandos pueden hacer referencia
duros. a directorios.
Los enlaces duros no tienen un concepto de Los enlaces blandos tienen un concepto de
"original" y "copia". Una vez se ha creado un "referencia" y "referido". Al suprimir archivos
enlace duro, todas las instancias se tratan "referidos" se crea una referencia colgante.
igual.
Los enlaces duros deben hacer referencia a Los enlaces blandos pueden abarcar archivos
archivos en el mismo sistema de archivos. del sistema (particiones).
Los enlaces duros se pueden compartir entre Los enlaces blandos pueden no referirse a
directorios con "chroot". archivos externos de un directorio con
"chroot".

83
Ejemplos

Trabajar con enlaces duros

En su directorio de inicio, blondie tiene un archivo llamado rhyme y un directorio llamado stuff. Ella
hace un listado largo con el comando ls -li, donde la opción -i hace que el comandols imprima el
número de inodos de cada archivo como la primera columna de la salida.

Puesto que cada inodo en un sistema de archivos tiene un número único de inodos, el número de
inodos que se puede utilizar para identificar un archivo. De hecho, cuando se lleve el rastro de
archivos internamente, el kernel suele referirse al archivo más por el número de inodo que por
nombre de archivo.

[blondie@station blondie]$ ls -il


total 8
246085 -rw-rw-r-- 1 blondie blondie 51 Jul 18 15:29 rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:34 stuff

Ella crea un enlace duro en el archivo rhyme y ve el contenido del directorio una vez más.

[blondie@station blondie]$ ln rhyme hard_link


[blondie@station blondie]$ ls -li
246085 -rw-rw-r-- 2 blondie blondie 51 Jul 18 15:29 hard_link
246085 -rw-rw-r-- 2 blondie blondie 51 Jul 18 15:29 rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:34 stuff

El conteo de enlaces para rhyme ahora es 2. Además, observe que el número de inodos tanto para
rhyme como para hard_link es 246085, lo que implica que, aunque hay dos nombres para el
archivo (dos dentries) hay un sólo inodo.

Si cambiamos los permisos en rhyme, los permisos en hard_link también cambiarán. ¿Por qué? los
dos nombres de archivo se refieren al mismo inodo. Puesto que el inodo hace referencia al
contenido de un archivo, también comparten los mismos datos.

[blondie@station blondie]$ chmod 660 rhyme


[blondie@station blondie]$ ls -li
246085 -rw-rw---- 2 blondie blondie 51 Jul 18 15:29 hard_link
246085 -rw-rw---- 2 blondie blondie 51 Jul 18 15:29 rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:34 stuff
[blondie@station blondie]$ echo "Hickory, Dickory, Dock," > rhyme
[blondie@station blondie]$ echo "Three mice ran up a clock." >> hard_link
[blondie@station blondie]$ cat rhyme
Hickory, Dickory, Dock,
Three mice ran up a clock.

84
Mover o incluso suprimir el archivo original no tiene efecto en el archivo de enlace.

[blondie@station blondie]$ mv rhyme stuff


[blondie@station blondie]$ ls -Rli
.:
total 8
246085 -rw-rw---- 2 blondie blondie 51 Jul 18 15:29 hard_link
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:38 stuff

./stuff:
total 4
246085 -rw-rw---- 2 blondie blondie 51 Jul 18 15:29 rhyme

Trabajar con enlaces blandos

La usuaria blondie ahora repite el mismo ejercicio, pero utiliza un enlace blando en lugar de uno
duro. Comienza con una configuración idéntica a la del ejemplo anterior.

[blondie@station blondie]$ ls -li


total 8
246085 -rw-rw-r-- 1 blondie blondie 29 Jul 18 15:25 rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:25 stuff

Ahora crea un enlace blando en el archivo rhyme y ve el contenido del directorio otra vez.

[blondie@station blondie]$ ln -s rhyme soft_link


[blondie@station blondie]$ ls -li
total 8
246085 -rw-rw-r-- 1 blondie blondie 29 Jul 18 15:25 rhyme
250186 lrwxrwxrwx 1 blondie blondie 5 Jul 18 15:26 soft_link -> rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:25 stuff

A diferencia del enlace duro del ejemplo anterior, el enlace blando existe como un inodo distinto
(con un número de inodo distinto) y el conteo de enlaces de cada uno de los archivos permanece
en 1. Lo que implica que ahora hay dos dentries y dos inodos. Cuando se hace referencia, sin
embargo, los archivos se comportan de una manera idéntica al caso de los enlaces duros.

[blondie@station blondie]$ echo "Hickory, Dickory, Dock," > rhyme


[blondie@station blondie]$ echo "Three mice ran up a clock." >> soft_link
[blondie@station blondie]$ cat rhyme
Hickory, Dickory, Dock,
Three mice ran up a clock.

A diferencia del enlace duro, el enlace blando no puede sobrevivir si se mueve o suprime el archivo
original. En cambio, blondie queda con el enlace colgante.

85
[blondie@station blondie]$ ls -liR
.:
total 4
250186 lrwxrwxrwx 1 blondie blondie 5 Jul 18 15:26 soft_link -> rhyme
542526 drwxrwxr-x 2 blondie blondie 4096 Jul 18 15:31 stuff

./stuff:
total 4
246085 -rw-rw-r-- 1 blondie blondie 51 Jul 18 15:29 rhyme
[blondie@station blondie]$ cat soft_link
cat: soft_link: No such file or directory

Trabajar con enlaces blandos y directorios

Los enlaces blandos también son útiles como punteros en directorios. Los enlaces duros sólo se
pueden utilizar con archivos ordinarios.

[einstein@station einstein]$ ln -s /usr/share/doc docs


[einstein@station einstein]$ ls -il
10513 lrwxrwxrwx 1 einstein einstein 14 Mar 18 20:31 docs ->
/usr/share/doc
10512 -rw-rw---- 2 einstein einstein 949 Mar 18 20:10 hard_link
55326 drwxrwxr-x 2 einstein einstein 1024 Mar 18 20:28 stuff

El usuario einstein ahora puede fácilmente cambiarse a los documentos del directorio sin tener que
recordar o teclear la ruta absoluta larga.

Ejercicios en línea

Crear y administrar listas Lab Exercise Objetivo: Crear y administrar enlaces duros y
blandosEstimated Time: 10 mins.

Especificaciones

Todos los archivos se deben crear en su directorio de inicio.

1. Crear un archivo llamado cal.orig en su directorio de inicio que contenga un calendario de


texto del mes actual (como el comando cal lo produce).
2. Cree un enlace duro para el archivo cal.orig llamadocal.harda
3. Cree un enlace duro para el archivo cal.orig llamadocal.hardb
4. Cree un enlace blando para el archivo cal.orig llamado cal.softa
5. Suprima el archivo cal.orig de tal manera que el enlace blando que acaba de crear sea
ahora un enlace colgante.
6. Cree un enlace blando para el directorio /usr/share/doc llamado docabs mediante una
referencia absoluta.
7. Cree un enlace blando para el directorio ../../usr/share/doc llamado docrel, usando una
referencia relativa, (observe que, dependiendo de la ubicación de su directorio de inicio,
usted podría necesitar agregar o suprimir algunas referencias .. desde el archivo siguiente.
Incluya suficientes para que el enlace blando sea una verdadera referencia relativa para el
directorio /usr/share/doc).

86
Si ha terminado el ejercicio correctamente, debería poder reproducir una salida similar a la
siguiente.

[student@station student]$ ls -l
total 12
-rw-rw-r-- 2 student student 138 Jul 21 10:03 cal.harda
-rw-rw-r-- 2 student student 138 Jul 21 10:03 cal.hardb
lrwxrwxrwx 1 student student 8 Jul 21 10:03 cal.softa -> cal.orig
lrwxrwxrwx 1 student student 14 Jul 21 10:03 docabs -> /usr/share/doc
lrwxrwxrwx 1 student student 19 Jul 21 10:03 docrel ->
../../usr/share/doc

Deliverables A title Question 1

1. Un archivo llamado cal.harda.


2. Un archivo llamado cal.hardb que sea un enlace duro para el siguiente archivo.
3. Un archivo llamado cal.softa, el cual es un enlace blando colgante para el archivo no
existente cal.orig.
4. Un archivo llamado docabs, el cual es un enlace blando para el directorio /usr/share/doc,
usando una referencia absoluta.
5. Un archivo llamado docrel, el cual es un enlace blando para el directorio
/usr/share/doc, usando una referencia relativa.

Compartir un archivo de enlace duro Objetivo: Compartir un archivo de enlace duro entre dos
usuarios.

Especificaciones

Usted desearía crear un archivo de enlace duro que le permita compartir con otro usuario.

1. Como usuario primario, crea un subdirectorio /tmp llamado como su nombre de cuenta,
como por ejemplo /tmp/student, donde student es remplazado por su nombre de usuario.
2. Todavía como su usuario primario, cree un archivo llamado /tmp/student/novel.txt que
contenga el texto "Once upon a time."

[student@station student]$ mkdir /tmp/student


[student@station student]$ echo "Once Upon a Time," > /tmp/student/novel.txt
[student@station student]$ ls -al /tmp/student/
total 12
drwxrwxr-x 2 student student 4096 Jul 21 10:13 .
drwxrwxrwt 28 root root 4096 Jul 21 10:12 ..
-rw-rw-r-- 1 student student 18 Jul 21 10:13 novel.txt

3. Ahora inicie sesión (o ejecute su -) en su primera cuenta alterna.Cree un directorio en /tmp,


el cual se llama como su cuenta alterna tal como /tmp/student_a.
4. Como su primer usuario alterno, en su directorio recien creado, cree un enlace duro para
el archivo /tmp/student/novel.txt, llamado /tmp/student_a/novel.lnk. Trate de editar el

87
archivo cambiando la línea desde "Once upon a time,", hasta "It was a dark and stormy
night.". ¿Por qué tuvo problemas? ¿Puede modificar las propiedades o permisos del
archivo novel.lnk? ¿Por qué sí o por qué no?

content_view let_

5. Un archivo llamado /tmp/student/novel.txt, donde student es remplazado por el nombre de


usuario primario, de propiedad de su usuario primario. El archivo debe tener propiedades y
permisos apropiados para que éste pueda ser modificado por su primera cuenta alterna. El
archivo debería contener sólo el texto "It was a dark and stormy night.".

6. Un archivo llamado /tmp/student_a/novel.lnk, donde student_a es remplazado por el


nombre de su primera cuenta alterna. El archivo debería ser un enlace duro para el archivo
/tmp/student/novel.txt.

88
Directorios y nodos de dispositivo

Conceptos clave

• El término archivo se refiere a los archivos regulares, directorios, enlaces simbólicos,


nodos de dispositivo y otros.
• Todos los archivos tienen atributos comunes: usuario propietario, grupo propietario,
permisos e información de temporización.
• La meta información de un archivo se encuentra en una estructura de datos llamada
inodos.
• Los nombres de archivos están en unas estructuras de datos llamadas entradas de
directorio (dentries).
• La meta información de un archivo se puede examinar con los comandos ls -l y stat.

Discussion

Directorios

Estructura del directorio

Al comienzo, presentamos dos estructuras asociadas con los archivos, dentries que asocian
nombres de archivos con inodos e inodos, que asocian todos los atributos de un archivo con su
contexto. Ahora veremos cómo se relacionan estas estructuras con los directorios.

El usuario prince está usando un directorio llamado report para administrar archivos de un informe
que está escribiendo. De modo recursivo lista el directorio report, incluyendo -a (el cual especifica
listar "todas"las entradas, incluyendo los que comienzan por un ".") y el comando -i (el cual
especifica listar el número de inodos de un archivo así como el nombre del archivo). Lo que resulta
es el siguiente listado de directorios y archivos, junto con su número de inodos.

[prince@station prince]$ ls -iaR report


report:
592253 . 249482 .. 592255 html 592254 text

report/html:
592255 . 592253 .. 592261 chap1.html 592262 chap2.html 592263 figures

report/html/figures:
592263 . 592255 .. 592264 image1.png

report/text:
592254 . 592253 .. 592257 chap1.txt 592258 chap2.txt

Observe que los archivos (directorios) ".".y ".."están incluídos en la salida. Como se mencionó en
un cuaderno anterior, el directorio "."se refiere al directorio mismo y el directorio ".."se refiere al
directorio padre. Cada directorio en realidad contiene entradas denominadas . y.., aunque sean
tratadas como archivos ocultos (debido a que "comienzan por ."), no se visualizan a no ser que se
especifique el comando -a.

89
Los mismos directorios, archivos y números de inodo se reproducen abajo en un formato más fácil.

path | inode
--------------------------------------------
report/ | 592253
|-- html | 592255
| |-- chap1.html | 592261
| |-- chap2.html | 592262
| `-- figures | 592263
| `-- image1.png | 592264
`-- text | 592254
|-- chap1.txt | 592257
`-- chap2.txt | 592258

Como se puede ver en la siguiente gráfica del directorio report, los directorios tienen la misma
estructura de los archivos regulares: una dentry, un inodo, y datos. No obstante, los datos
almacenados en los directorios, son las dentries asociadas con los archivos de directorio que se
dice que contienen. Un directorio es un poco más que un cuadro de dentries, asignando nombres
de archivo as los inodos subyacentes que representan archivos. Cuando fue presentado, el nombre
dentry se decía que se derivaba de directoryentry. Ahora vemos que los directorios no son más
complicados que eso: un directorio es una colección de dentries.

Figure 1. La estructura interna de los directorios

Enlaces de directorios

90
Anteriormente vimos que el conteo de enlaces de directorios, como se muestra en la segunda
columna del comando ls -l, fue siempre 2 o más. Esto se deduce naturalmente del hecho que cada
directorio se referencia al menos dos veces, una por sí mismos (como el "."), y otra como su padre
(con un nombre de directorio real, tal como report). El siguiente diagrama sirve de ilustración de las
dentries que se encuentran en el directorio report , su subdirectorio html, y su subdirectorio figures).

Figure 1. Cuadros dentry para los directorios report, report/html y report/html/figures.

Cuando prince hace un listado largo del directorioreport, ve los cuatro archivos en el primer cuadro.

[prince@station prince]$ ls -ial report


total 16
592253 drwxrwxr-x 4 prince prince 4096 Jul 14 13:27 .
249482 drwx-----x 6 prince prince 4096 Jul 14 13:27 ..
592255 drwxrwxr-x 3 prince prince 4096 Jul 14 13:49 html
592254 drwxrwxr-x 2 prince prince 4096 Jul 14 13:49 text

Cada archivo en el listado es un directorio y el conteo de enlaces (aquí la tercera columna, ya que
el numero de inodos ha sido adjuntado con antelación en la primera columna) de cada uno es o
igual o mayor de dos. ¿Podemos responder por cada uno de los enlaces? Comencemos por listar
las referencias al número de inodo 592253 (el directorio report o el anterior ".").

1. La entrada . que se encuentra en el directorio mismo.


2. El directorio padre (no mostrado) contiene una entrada llamada report, la cual hace
referencia al mismo inodo.

91
3. El subdirectorio html contiene una entrada llamada.., la cual hace referencia al inodo
592253 como su directorio padre.
4. Del mismo modo, el subdirectorio text (no descrito) contiene una entrada llamada .. que
hace referencia al mismo inodo.

Respondiendo por si mismo (al cual llama "."), su padre (al cual llama"report"), y sus dos
subdirectorios (a los cuales llama ".."), hemos hallado todos nuestros enlaces en el inodo 592253
reportados por el comando ls -l.

En el siguiente listado, el directorio report/html tiene un conteo de enlaces de 3, ¿puede encontrar


todas las tres referencias para el número de inodo 592255 en la gráfica de arriba?

[prince@station prince]$ ls -ial report/html


total 20
592255 drwxrwxr-x 3 prince prince 4096 Jul 14 13:49 .
592253 drwxrwxr-x 4 prince prince 4096 Jul 14 13:27 ..
592261 -rw-rw-r-- 1 prince prince 2012 Jul 14 13:28 chap1.html
592262 -rw-rw-r-- 1 prince prince 2012 Jul 14 13:28 chap2.html
592263 drwxrwxr-x 2 prince prince 4096 Jul 14 13:28 figures

En resumen, los directorios son simplemente colecciones de dentries para los archivos que se dice
que están en el directorio, los cuales asignan los nombres de archivo a los inodos. Cada directorio
contiene al menos dos enlaces, uno desde su propia entrada de directorio ".", y otro desde su
entrada padre con el nombre convencional del directorio. Se hace referencia a los directorios por
un enlace adicional para cada subdirectorio, los cuales hacen referencia al directorio como "..".

Nodos de dispositivo

Hemos analizado tres tipos de "criaturas" que pueden existir en el sistema de archivos de Linux, es
decir los archivos regulares, los directorios y los enlaces simbólicos. En esta sección, discutiremos
los dos últimos tipos de entradas del sistema de archivos (que se tratarán en este curso), nodos de
dispositivo de bloque y de caracter.

Nodos de dispositivos de bloque y de caracter

Los nodos de dispositivos existen en el sistema de archivos, pero no contienen datos de la misma
forma que los archivos regulares o incluso los directorios y enlaces simbólicos. En su lugar, la labor
de un dispositivo de nodo es actuar como un conducto hacia un controlador de dispositivo
determinado dentro del kernel. Cuando el usuario escribe en el nodo del dispositivo, el nodo del
dispositivo transfiere la información al controlador de dispositivo apropiado en el kernel. Cuando un
usuario desea recopilar información desde un dispositivo particular, se lee desde ese nodo de
dispositivo asociado con el dispositivo justo como si leyera desde un archivo.

Por convención, los nodos de dispositivo viven dentro de un directorio llamado /dev. A continuación
el usuario elvis hace un listado largo de archivos en el directorio /dev.

92
[elvis@station elvis]$ ls -l /dev
total 228
crw------- 1 root root 10, 10 Jan 30 05:24 adbmouse
crw-r--r-- 1 root root 10, 175 Jan 30 05:24 agpgart
crw------- 1 root root 10, 4 Jan 30 05:24 amigamouse
...
crw------- 1 elvis root 14, 7 Jan 30 05:24 audioctl
brw-rw---- 1 root disk 29, 0 Jan 30 05:24 aztcd
crw------- 1 elvis root 10, 128 Jan 30 05:24 beep
brw-rw---- 1 root disk 41, 0 Jan 30 05:24 bpcd
crw------- 1 root root 68, 0 Jan 30 05:24 capi20

Como hay más de7000 entradas en el directorio /dev, la salida se limita sólo a los primeros
archivos. Enfocándonos en el primer caracter de cada línea, la mayoría de los archivos dentro de
/dev no son archivos regulares o directorios, sino nodos de dispositivo de caracter ("c"), o nodos de
dispositivos de bloque ("b"). Los dos tipos de nodos de dispositivos reflejan el hecho de que los
controladores de dispositivos en Linux se dividen en dos clases principales: los dispositivos de
caracter y los dispositivos de bloque.

Dispositivos de Caracter

Los dispositivos de caracter son dispositivos que leen y escriben información como un flujo
de bytes ("caracteres"), y hay un concepto natural de lo que significa leer o escribir el
"próximo " caracter. Ejemplos de dispositivos de caracter incluyen teclado, ratón. tarjetas
de sonido e impresoras.

Dispositivos de bloque

Los dispositivos de bloque son dispositivos que leen y escriben información en fragmentos
("bloques") a la vez. Es costumbre que los dispositivos de bloque permitan acceso
aleatorio, lo que significa que un bloque de datos podría leerse desde cualquier parte del
dispositivo, en cualquier orden. Ejemplos de dispositivos de bloque incluyen, discos duros,
disquetes y controladores de CD/ROM.

Terminales como dispositivos

En el siguiente ejemplo, elvis ha iniciado sesión en una máquina de Linux, en la primera y segunda
consola virtual. En el primer cuaderno, vimos la manera de identificar terminales por nombre y
hallamos que el nombre de la primera consola era tty1, y la segunda consola virtual era tty2. Ahora,
podemos ver que el "nombre" de la terminal es en realidad el nombre del nodo de dispositivo
asignado a esa terminal. En el listado siguiente, los nodos de dispositivo /dev/tty1 a través de
/dev/tty6 son los nodos de dispositivo para las primeras 6 consolas virtuales, respectivamente.

[elvis@station elvis]$ ls -l /dev/tty[1-6]


crw--w---- 1 elvis tty 4, 1 May 14 16:06 /dev/tty1
crw--w---- 1 elvis tty 4, 2 May 14 16:06 /dev/tty2
crw------- 1 root root 4, 3 May 14 08:50 /dev/tty3
crw------- 1 root root 4, 4 May 14 08:50 /dev/tty4
crw------- 1 root root 4, 5 May 14 08:50 /dev/tty5
crw------- 1 root root 4, 6 May 14 08:50 /dev/tty6

93
En el siguiente ejemplo, elvis, está trabajando desde la consola virtual número 1, y redirigirá tres
veces la salida del comando cal, primero, a un archivo llamado /tmp/cal, segundo, a un nodo de
dispositivo /dev/tty1 y por último, al nodo de dispositivo /dev/tty2.

[elvis@station elvis]$ cal > /tmp/cal


[elvis@station elvis]$ cal > /dev/tty1
May 2003
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
[elvis@station elvis]$ cal > /dev/tty2

Este caso debería ser familiar, la salida simplemente se redirige al archivo recién creado cal.
Aparentemente, no se pudo redirigir, pero sí lo hizo. La salida del comando fue redirigida al
nodo del dispositivo de la primera consola virtual, el cual hizo lo que se "suponía que tenía
que hacer", es decir, mostrar toda la información escrita en la pantalla.
¿A dónde va la salida del comando cal esta vez? La información fue redirigida al nodo de
dispositivo para la segunda consola virtual, lo cual hizo lo que se "suponía que debía hacer",
es decir, mostrarla en la segunda consola virtual.

La segunda forma de redirigir amerita un poco más de atención. Cuando elvis redirigió la salida al
nodo de dispositivo que controla su consola virtual actual, /dev/tty1, pareció no haber redirigido
nada en absoluto. ¿Por qué? Cuando elvis ejecuta comandos interactivos sin redirigir, escriben en
los nodos de dispositivo que controlan las terminales por defecto. Redirigir la salida de comando a /
dev/tty1 es como decir "en lugar de escribir su salida en mi terminal, escriba su salida en mi
terminal."

Al cambiar a la segunda consola virtual, utilizando la secuencia de teclas CTRL-ALT-F2, elvis halla
los siguientes caracteres en la pantalla.

Red Hat Enterprise Linux release 3 (Taroon)


Kernel 2.4.20-4ES on an i686

station login: elvis


Password:
Last login: Mon May 14 16:55:22 on tty1
You have new mail.
[elvis@station elvis]$ May 2003
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

Aquí es donde estaba el cursor de elvis después de iniciar sesión en la segunda consola
virtual y cambiar a la consola virtual número 1.
Aquí es donde la salida del comando cal estaba escrita en la terminal. Observe la falta de

94
espacios separando la salida. Esta no es una ocurrencia natural con buen formato, sino algo
extraño que elvis le pidió hacer al controlador del dispositivo.
Por último, la salida del comando cal disminuyó, pero observe que bash shell no ofrece un
intérprete de comandos fresco. De hecho, la shell bash ni siquiera se dio cuenta que los
caracteres fueron escritos en la terminal. Aún está esperando que elvis entre el comando.

Permisos de dispositivo, seguridad y usuario de consola

Continuando con lo anterior, el usuario elvis (quien ha iniciado sesión en las primeras dos consolas
virtuales, filename>tty1

[elvis@station elvis]$ cal > /dev/tty3


-bash: /dev/tty3: Permission denied

¿Por que elvis no pudo realizar el mismo truco en la tercera consola virtual? Porque elvis no ha
iniciado sesión en la tercera consola virtual y por lo tanto, no posee el dispositivo. Examine de
nuevo el listado largo de comandos ls -l de los nodos de dispositivo de la consola virtual:

[elvis@station elvis]$ ls -l /dev/tty[1-6]


crw--w---- 1 elvis tty 4, 1 May 16 13:38 /dev/tty1
crw--w---- 1 elvis tty 4, 2 May 16 13:38 /dev/tty2
crw------- 1 root root 4, 3 May 16 10:02 /dev/tty3
crw------- 1 root root 4, 4 May 16 10:02 /dev/tty4
crw------- 1 root root 4, 5 May 16 10:02 /dev/tty5
crw------- 1 root root 4, 5 May 16 10:02 /dev/tty6

Puesto que los nodos de dispositivo se consideran archivos, también tienen usuarios propietarios,
grupo propietarios y una colección de permisos. Al leer o escribir desde el nodo de dispositivo
aplica solo como si leyera o escribiera a un archivo regular. Esto le permite a un administrador de
sistemas (o al software en el sistema) controlar quién ha tenido acceso a los dispositivos
particulares mediante una técnica familiar, es decir, administrando los propietarios de archivo y los
permisos de archivo.

¿Qué sucede cuando prince inicia sesión en la tercera consola virtual?

[elvis@station elvis]$ ls -l /dev/tty[1-6]


crw--w---- 1 elvis tty 4, 1 May 16 13:38 /dev/tty1
crw--w---- 1 elvis tty 4, 2 May 16 13:38 /dev/tty2
crw--w---- 1 prince tty 4, 3 May 16 13:46 /dev/tty3
crw------- 1 root root 4, 4 May 16 10:02 /dev/tty4
crw------- 1 root root 4, 5 May 16 10:02 /dev/tty5
crw------- 1 root root 4, 6 May 16 10:02 /dev/tty6

Cuando un usuario inicia sesión, se obtiene propiedad del nodo de dispositivo que controla su
terminal. Los procesos que ellos ejecutan pueden luego leer o escribir salida en la terminal. En
general, los permisos en los nodos de dispositivos no permiten a los usuarios estándares acceder a
los dispositivos directamente. Hay dos excepciones.

95
Terminales

Puesto que los usuarios necesitan comunicarse con el sistema, ellos (o más exactamente,
los procesos que ellos ejecutan) deben ser capaces de leer y escribir en la terminal que
están usando. Suele presentarse que parte del proceso de inicio de sesión en un sistema
implica la transferencia de propiedad de nodos de dispositivos de terminal al usuario.

"Usuarios de Consola"

En Red Hat Enterprise Linux, a los usuarios se les otorgan permisos no por quiénes son,
sino por desde dónde se ha iniciado la sesion. Es decir, cuando un usuario inicia sesión en
una consola virtual o en un servidor gráfico X, se considera un "usuario de consola". Los
usuarios de consola tienen acceso a dispositivos de hardware asociados con la consola,
tales como disquetes y tarjetas de sonido. Cuando los usuarios de consola terminan
sesión, las propiedades para estos dispositivos son restauradas a las predeterminadas del
sistema, Nada de esto sucede si un usuario inicia sesión en una red, por ejemplo. -Si el
usuario no está en la máquina, ¿sería razonable usar disquetes?

En resumen, Linux (y UNIX) utilizan los nodos de dispositivo para permitir a los usuarios el acceso
a dispositivos en el sistema. La administración de dispositivos en un sistema de Linux puede ser un
tema extenso y complejo. A manera de introducción, hemos visto suficiente acerca de cómo se
utilizan los nodos de dispositivo de la terminal para presentar el concepto e identificar un par de
ventajas en el enfoque del nodo de dispositivo.

• Al escribir programas, los programadores no necesitan tratar con detalles de dispositivos.


Pueden tratar toda las salidas y las entradas como si estuvieran simplemente leyendo o
escribiendo un archivo.
• El acceso a dispositivos se puede controlar a través de las mismas técnicas de propietarios
de archivos y permisos utilizados en los archivos regulares.

Ejemplos

Interpretación de conteos de enlaces de directorio

El usuario elvis hace un listado largo del directorio /var/spool. Está interesado en interpretar el
conteo de enlaces del subdirectorio como aparece en la segunda columna.

[elvis@station elvis]$ ls -l /var/spool


total 64
drwxr-xr-x 2 root root 4096 Jan 24 16:26 anacron
drwx------ 3 daemon daemon 4096 Jun 18 02:00 at
drwxrwx--- 2 smmsp smmsp 4096 Jul 21 10:42 clientmqueue
drwx------ 2 root root 4096 Jun 18 16:12 cron
drwx------ 3 lp sys 8192 Jul 18 17:38 cups
drwxr-xr-x 23 root root 4096 Jan 24 18:52 lpd
drwxrwxr-x 2 root mail 4096 Jul 21 10:11 mail
drwx------ 2 root mail 8192 Jul 21 10:43 mqueue
drwxr-xr-x 17 root root 4096 Feb 24 19:41 postfix
drwxr-xr-x 2 rpm rpm 4096 Apr 11 06:18 repackage
drwxrwxrwt 2 root root 4096 Apr 5 23:46 samba
drwxr-xr-x 2 root root 8192 Jul 16 17:53 up2date
drwxrwxrwt 2 root root 4096 Feb 3 19:13 vbox

96
Al notar que tiene un conteo de enlaces de 17, elvis concluye que el directoriopostfix contiene 15
subdirectorios. 1 enlace como se muestra arriba para la entrada postfix , 1 enlace para la entrada .
que se encuentra dentro de postfix (no se muestra) y 15 para las entradas .. dentro de 15
subdirectorios.

Al examinar un listado largo del directorio/var/spool/postfix, concluye que estaba en lo cierto (hay
15 subdirectorios).

[elvis@station elvis]$ ls -l /var/spool/postfix/


total 60
drwx------ 2 postfix root 4096 Feb 24 19:41 active
drwx------ 2 postfix root 4096 Feb 24 19:41 bounce
drwx------ 2 postfix root 4096 Feb 24 19:41 corrupt
drwx------ 2 postfix root 4096 Feb 24 19:41 defer
drwx------ 2 postfix root 4096 Feb 24 19:41 deferred
drwxr-xr-x 2 root root 4096 Apr 1 12:22 etc
drwx------ 2 postfix root 4096 Feb 24 19:41 flush
drwx------ 2 postfix root 4096 Feb 24 19:41 incoming
drwxr-xr-x 2 root root 4096 Apr 11 05:54 lib
drwx-wx--- 2 postfix postdrop 4096 Feb 24 19:41 maildrop
drwxr-xr-x 2 root root 4096 Feb 24 19:41 pid
drwx------ 2 postfix root 4096 Feb 24 19:41 private
drwx--x--- 2 postfix postdrop 4096 Feb 24 19:41 public
drwx------ 2 postfix root 4096 Feb 24 19:41 saved
drwxr-xr-x 3 root root 4096 Feb 24 19:41 usr

97
Discos, sistemas de archivos y montaje

Conceptos clave

• Linux permite el acceso de bajo nivel a los controladores de disco a través de nodos de
dispositivo en el directorio /dev.
• Por lo general, los discos se formatean con un sistema de archivos y se montan en un
directorio.
• Los sistemas de archivos se crean con algunas variantes del comando mkfs.
• El sistema de archivos predetermiando de Red Hat Enterprise Linux es el sistema de
archivos ext3.
• El comando mount se utiliza para asignar el directorio root de un sistema de archivos (o
una partición de un disco) a un directorio ya existente. Ese directorio se denomina punto
de montaje.
• El comando umount se utiliza para desmontar un sistema de archivos de un punto de
montaje.
• El comando df se utiliza para reportar el uso del sistema de archivos y mapea los
dispositivos actualmente montados.

Discussion

Dispositivos de disco

Linux (y Unix) permite a los usuarios acceso directo, de bajo nivel a los controladores de disco a
través de los nodos de dispositivos en el directorio /dev. El siguiente cuadro lista los nombres de
archivos de los nodos de dispositivos comunes y los discos con los cuales están asociados.

Table 1. Nodos de dispositivos de disco Linux

Nodo de dispositivo Disco


/dev/fd0 Disquete
/dev/hda Master Primario IDE
/dev/hdb Esclavo Primario IDE
/dev/hdc Master Secundario IDE
/dev/hdd Esclavo Secundario IDE
/dev/sd[a-z] Discos SCSI
/dev/cdrom Enlace simbólico al CD/ROM

Aunque los nodos de dispositivo existen para los controladores de disco, los usuarios estándar no
suelen tener permisos de acceso directo. A continuación elvis ha realizado un listado largo de
varios nodos de dispositivo que aparecen en el cuadro anterior.

98
[elvis@station elvis]$ ls -l /dev/fd0 /dev/hd[abcd] /dev/sda /dev/cdrom
lrwxrwxrwx 1 root root 8 Oct 1 2002 /dev/cdrom ->
/dev/hdc
brw-rw---- 1 elvis floppy 2, 0 Jan 30 05:24 /dev/fd0
brw-rw---- 1 root disk 3, 0 Jan 30 05:24 /dev/hda
brw-rw---- 1 root disk 3, 64 Jan 30 05:24 /dev/hdb
brw------- 1 elvis disk 22, 0 Jan 30 05:24 /dev/hdc
brw-rw---- 1 root disk 22, 64 Jan 30 05:24 /dev/hdd
brw-rw---- 1 root disk 8, 0 Jan 30 05:24 /dev/sda

Por defecto, elvis no tiene permisos para acceder a los controladores fijos de la máquina. Dado que
(aparentemente) está conectado en la consola, se considera el "usuario de la consola" y ha ganado
permisos para acceder a los disquetes y al CD/ROM. Aprovecharemos este hecho durante esta
lección.

Curiosamente, el archivo /dev/cdrom no es un nodo de dispositivo, sino un enlace simbólico que


apunta al nodo de dispositivo de bloque /dev/hdc. Los controladores más modernos de CD/ROM
están físicamente conectados a la máquina mediante una interfaz de IDE o SCSI, y así aparecen al
kernel simplemente como otro controlador SCSI o IDE. Sin embargo, algunas aplicaciones tales
como el reproductor de CD de audio gnome-cd, desean acceder al "CD/ROM". Para ellos,
/dev/cdrom da acceso al CD/ROM, sin importar cómo se enlaza al sistema.

Los discos duros suelen dividirse en particiones. Las particiones son regiones del disco duro que
se pueden utilizar como si cada una fuera un disco individual. Así como hay nodos de dispositivo
para cada disco, los hay también para cada partición de disco. El nombre de una partición de nodo
de dispositivo es simplemente un número adjunto al nombre de nodo de dispositivo del disco. Por
ejemplo, el nodo de dispositivo para la tercera partición del controlador IDE esclavo primario se
denomina /dev/hdb3.

El siguiente diagrama ilustra un disco duro que se ha dividido en cuatro particiones y los nodos de
dispositivo dirigidos a cada una de ellas.

Figure 1. Particiones de disco duro

Controladores de acceso de bajo nivel

A continuación, elvis está explorando el acceso al nivel bajo para su disquete. Comienza por
asegurarse si tiene permisos de lectura y escritura en su nodo de dispositivo del disquete
ejecutando cat en el archivo /etc/resolv.conf y luego redirigiendo la salida del comando al
controlador del disquete (/dev/fd0).

99
[elvis@station elvis]$ ls -l /dev/fd0
brw-rw---- 1 elvis floppy 2, 0 Jan 30 05:24 /dev/fd0
[elvis@station elvis]$ cat /etc/resolv.conf
search example.com
nameserver 192.168.0.254
[elvis@station elvis]$ cat /etc/resolv.conf > /dev/fd0
-bash: /dev/fd0: No such device or address

En un comienzo, perplejo por el mensaje de error, elvis nota que no hay disquete en su controlador
de disquete. Coloca un disco antiguo en blanco (para no preocuparse del contenido) en el
controlador.

[elvis@station elvis]$ cat /etc/resolv.conf > /dev/fd0


-bash: /dev/fd0: Read-only file system

Perplejo de nuevo, elvis quita el disquete del controlador, lo examina, desliza la lengüeta del
disquete a la posición de escritura e inserta de nuevo el disquete.

[elvis@station elvis]$ cat /etc/resolv.conf > /dev/fd0

Finalmente, la luz del controlador del disquete se alumbra y elvis escucha al disco dando vueltas
porque hay información en el disquete. Curioso por ver lo que ha escrito en el disquete, trata luego
de leerlo con el paginador less.

[elvis@station elvis]$ less /dev/fd0


/dev/fd0 is not a regular file (use -f to see it)

El paginador less parece estarle diciendo a elvis, "La gente cuerda no lee los nodos de dispositivo
directamente, pero si realmente quiere hacerlo, yo se lo permito." Como realmente quiere hacerlo,
agrega la opción -f.

[elvis@station elvis]$ less -f /dev/fd0


En la primera página, elvis reconoce los primeros caracteres como el contenido /etc/resolv.conf.
Después de esto, sin embargo, el paginador muestra datos ilegibles con textos de lectura humana
ocasionales e intercalados.

search example.com
nameserver 192.168.0.254
B^RA^^@^@V^^|F^@^@^@AdDBP^A^^|^C^F^B|^@DVP|Q^^^R ABAoot
failed^@^@^@LDLINUX SYS
...

El usuario elvis continua a través del "archivo" usando el paginador less, viendo aparentemente
pedazos de texto aleatorios y caracteres binarios. Cuando cree que lo logra, abandona el
paginador.

100
¿Para qué todo esto? Al acceder a los controladores de disco a través de sus nodos de dispositivo,
los usuarios pueden ver (y escribir) el contenido del controladorbyte por byte. Para el usuario, el
controlador se ve como un archivo bien grande. Cuando elvis hace cat en el contenido de un
archivo al nodo de dispositivo del controlador, la información es transferida, byte por byte al
controlador.

En los primeros bytes del disquete, elvis ve una copia del contenido del archivo /etc/resolv.conf.
¿Cuál es el nombre de archivo asociado con la información, en el disquete? Pregunta delicada. No
tiene . ¿Quién es el usuario propietario? ¿Cuáles son los permisos?No hay ninguno. Es sólo datos.
Cuando elvis va atrás para leer el contenido del controlador, ve los datos que escribió allí, es decir,
el contenido del archivo /etc/resolv.conf. Después de eso, ve lo que habia en el disquete antes de
iniciar.

Sistemas de archivos

La sección anterior demostró la manera de acceder a los controladores en un nivel bajo. Es obvio
que la gente no le gusta almacenar su información en controladores como un flujo de datos. A ellos
les gusta organizar su información en archivos y darle nombres a los archivos. A ellos les gusta
organizar sus archivos en directorios y decir quién puede tener acceso al directorio y quién no.
Toda esta estructuración de información es responsabilidad de lo que se denomina un sistema de
archivos.

Un sistema de archivos proporciona el orden a los controladores de disco organizando el


controlador en fragmentos del mismo tamaño llamados bloques. El sistema de archivos organiza
estos bloques, diciendo "este bloque contendrá sólo dentries", estos 3 bloques aquí y ese allá,
contendrán el contenido del archivo /etc/services" o "este primerbloque almacenará información
sobre la manera en que se están utilizando los otros bloques". Los sistemas de archivos proveen
toda esta estructura que generalmente se ignora.

Antes de que un disco se pueda utilizar para almacenar archivos en el sentido convencional , se
debe ser inicializar con este tipo de estructura de bajo nivel. En Linux, se denomina una "creación
de un sistema de archivos". En otros sistemas operativos, se suele referir como "formatear el
disco". Linux soporta un gran número de tipos diferentes de sistemas de archivos (la página del
manual fs(5) lista apenas unos pocos). Aunque el sistema de archivos nativo de Linux es ext2 (o en
Red Hat Enterprise Linux, ext3), también es compatible con los sistemas de archivo nativos de
muchos sistemas operativos tales como el sistema de archivos DOS FAT o el sistema de archivos
de alta ejecución OS/2.

En Linux, los sistemas de archivos se crean con algunas variantes del comando mkfs. Dado que
estos comandos se suelen utilizar solamente por el usuario administrativo, no viven en los
directorios estándar /bin ni en el directorio /usr/bin, por lo tanto no pueden invocarse como simples
comandos. En cambio, viven en el directorio /sbin, el cual está reservado para los comandos
administrativos. A continuación, elvis lista todos los comandos que comienzan por mkfs en el
directorio /sbin.

[elvis@station elvis]$ ls /sbin/mkfs*


/sbin/mkfs /sbin/mkfs.ext2 /sbin/mkfs.jfs
/sbin/mkfs.reiserfs
/sbin/mkfs.cramfs /sbin/mkfs.ext3 /sbin/mkfs.msdos /sbin/mkfs.vfat

101
Aparentemente, hay una copia del comando mkfs por cada tipo de sistema de archivo que se
puede construir, incluyendo los sistemas de archivos ext2 y msdos. El usuario elvis luego formatea
el mismo disco utilizado anteriormente con el sistema de archivo ext2. Dado que el comando
mkfs.ext2 no vivió en uno de los directorios "estándar", elvis necesita referirse al comando
mediante una referencia absoluta, /sbin/mkfs.ext2.

[elvis@station elvis]$ /sbin/mkfs.ext2 /dev/fd0


mke2fs 1.32 (09-Nov-2002)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
184 inodes, 1440 blocks
72 blocks (5.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
184 inodes per group

Writing inode tables: done


Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or


180 days, whichever comes first. Use tune2fs -c or -i to override.

El comando mkfs.ext2 muestra información acerca del sistema de archivos a medida que se crea
en el dispositivo /dev/fd0. Cuando el comando completa, el sistema de archivo ha sido inicializado y
el disquete está listo para ser utilizado.

El comando mkfs y sus variantes, pueden configurarse con una gran colección de líneas de
opciones, las cuales especifican detalles del nivel bajo acerca del sistema de archivos. Estos
detalles van más allá del objetivo de este curso. Afortunadamente, las diversas opciones se
predeterminan para propósitos generales por defecto. Encontrará mayor información en las
páginas del manual mkfs.ext2(8) y similares.

Montaje del sistemas de archivos

Una vez se le ha dado formato al disco o a la partición del disco con el sistema de archivos, los
usuarios necesitan alguna forma de acceder los directorios y los archivos que el sistema de
archivos provee. En otros sistemas operativos, los usuarios suelen ser mas conscientes de la
particiones de disco porque tienen que referirse a ellos mediante etiquetas tales como C: o D:. En
Unix, los usuarios suelen no darse cuenta de las particiones porque las diferentes particiones de
disco están organizadas en una estructura única de directorio.

¿Cómo se hace esto? Cada sistema de archivos proporciona un directorio raíz que sirve como
base de este sistema de archivos. Una vez se haya iniciado el sistema, una de sus particiones de
discos actúa como la partición raíz y su directorio raíz se convierte en el directorio raíz del sistema
/. Algunas veces, este es el final de la historia. El directorio / tiene subdirectorios y esos
subdirectorios tienen subdirectorios, los cuales residen en el sistema de archivo de la partición raiz.

Sin embargo, si un sistema tiene múltiples discos, o si un disco tiene múltiples particiones, las
cosas se complican. Con el fin de acceder a los sistemas de archivos en las otras particiones, los

102
directorios raíz de aquellos sistemas se asignan a un directorio existente a través de una técnica
estándar de Unix llamada montaje.

En el siguiente diagrama, el sistema de archivos en la partición /dev/hda2 está siendo utilizado


como la partición raíz y contiene los directorios /etc, /tmp, /home y otros directorios esperados. La
partición /dev/hda4 también se ha formateado con el sistema de archivos y su directorio raíz
contiene los directorios /blondie, /prince y otros más. Con el fin de hacer uso del sistema de
archivos, éste se monta en el directorio /home, el cual ya existía en el sistema de archivos de la
partición raíz. Este montaje suele presentarse como parte del proceso de arranque del sistema.

Figure 1. Montaje de un sistema de archivos

Ahora, todas las referencias al directorio /home se asignan de un modo transparente al directorio
raíz del sistema de archivos en /dev/hda4, dando la apariencia que el directorio /home contiene los
subdirectorios blondie, elvis, etc, como se muestra a continuación. Cuando el sistema de archivos
se monta sobre un directorio de esta manera, dicho directorio se denomina punto de montaje.

[elvis@station elvis]$ ls /home


blondie elvis madonna prince

¿Cómo puede elvis saber qué partición contiene un archivo determinado? Usando sólo el comando
ls¡no puede! Para ejecutar el comando ls y usualmente en la mente del usuario, todas las
particiones se combinan correctamente dentro de una aparente única estructura de directorio.

Ver puntos de montaje

¿Cómo puede un usuario determinar qué directorios se están usandos como puntos de montaje?
Un método es ejecutar el comando mount sin argumentos.

[elvis@station elvis]$ mount


/dev/hda3 on / type ext3 (rw)
none on /proc type proc (rw)
usbdevfs on /proc/bus/usb type usbdevfs (rw)
/dev/hda1 on /boot type ext3 (rw)
none on /dev/pts type devpts (rw,gid=5,mode=620)
none on /dev/shm type tmpfs (rw)

103
Sin argumentos, el comando mount devuelve una lista de puntos de montaje, el dispositivo que
está montado a ésta, el tipo de sistema de archivos con el que el dispositivo le ha dado formato y
cualquier otra opción de montaje asociadas con el montaje. En el ejemplo anterior, la partición /dev/
hda3 se está utilizando como partición raíz y el sistema de archivo ext3 en la partición /dev/hda1 ha
sido montado en el directorio /boot. Observe que varios sistemas de archivos listados arriba no
tienen "ningún" dispositivo. Estos son sistemas de archivos virtuales, los cuales son implementados
por el kernel directamente y no existen en ningún dispositivo físico.

¿Para qué molestarnos?

Si rara vez usted sabe qué directorios se están utilizando como puntos de montaje y qué archivos
existen en las particiones, ¿para que molestarse incluso por hablar de esto? Por ahora, daremos
dos razones. La primera razón es que pueden haber problemas sutiles, que pueden empeorar,
relacionados con el sistema de archivos subyacente. A las particiones se les puede acabar el
espacio. Si a un archivo montado en /home se le acaba el espacio, no se pueden crear más
archivos bajo el directorio/home. Sin embargo, esto no afecta al directorio /tmp porque éste
pertenece a otro sistema de archivos. En Unix, cuando una partición se llena, sólo afecta a la parte
de la estructura del directorio bajo su punto de montaje, no a todo el árbol de directorios.

Los usuarios pueden determinar cuánto espacio está disponible en una partición con el comando
df, el cual significa "disk free".

df [OPCIÓN...] [ARCHIVO...]

Muestra información sobre todas las particiones o una partición en la cuales reside un ARCHIVO.

Opción Efecto
-a, --all Muestra todos los sistemas de archivos, incluyendo aquellos de tamaño
0.
-h, --leíble por Imprime tamaños en formato legible por humanos
humanos
-i, --inodes Lista el uso de inodos en lugar del uso del bloques
-T, --print-type incluye el tipo des sistema de archivos

No solo el comando df muestra el espacio restante en las particiones particulares, sino que
presenta en un cuadro leíble de dispositivos montados en cada directorio. A continuación, el
sistema de archivos en /dev/hda2 se está utilizando como partición raíz, el sistema de archivos en /
dev/hda1 está montado en el directorio /boot y /dev/hda4 está montado en /home. Una partición en
un segundo disco, es decir la partición /dev/hdb2, está montada en un directorio no estándar
denominado /data.

[elvis@station elvis]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda2 8259708 6708536 1131592 86% /
/dev/hda1 102454 24227 72937 25% /boot
/dev/hda4 5491668 348768 4863936 7% /home
/dev/hdb2 4226564 1417112 2594748 36% /data
none 127592 0 127592 0% /dev/shm

104
Medios de montaje temporal: el directorio /media.

La segunda razón por la cual los usuarios necesitan conocer los sistemas de archivos y los puntos
de montaje, involucra los medios temporales tales como los disquetes y los CD/ROM. Como
cualquier dispositivo de bloque, los disquetes y los discos CD/ROM se formatean con sistemas de
archivos. Con el fin de acceder a estos sistemas de archivos deben montarse en la estructura del
directorio, mediante un directorio (ya existente) como un punto de montaje. ¿Qué directorio debería
utilizarse?

El directorio /media contiene subdirectorios tales como /media/floppy y /media/cdrom, o incluso


/media/camera que están pensados con este único propósito: servir como puntos de montaje para
los medios temporales, (así el nombre del directorio /media). Si quisiera hacer uso de un disco
temporal, tal como un disquete, debe primero montar el sistema de archivos en una estructura de
directorios usando el comando mount.

[elvis@station elvis]$ mount /media/floppy


[elvis@station elvis]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda2 8259708 6708536 1131592 86% /
/dev/hda1 102454 24227 72937 25% /boot
/dev/hda4 5491668 348768 4863936 7% /home
/dev/hdb2 4226564 1417112 2594748 36% /data
none 127592 0 127592 0% /dev/shm
/dev/fd0 1412 13 1327 1% /media/floppy

En la última línea, el comandodf reporta ahora el controlador de disquete recién montado y elvis
puede copiar archivos en el disquete.

Figure 1. Montaje de un disquete con formato

[elvis@station elvis]$ cp /etc/services /media/floppy/


[elvis@station elvis]$ ls /media/floppy/
lost+found services

¿De dónde viene el directoriolost+found? Este directorio se crea al mismo tiempo que el sistema de
archivos y siempre existe en el directorio raíz de un sistema de archivos ext2 o ext3. Se usa
ocasionalmente para reparar daños en los sistemas de archivos.

105
Cuando elvis ha terminado de usar el disco, lo desmonta del sistema de archivo mediante el
comando umount.

[elvis@station elvis]$ umount /media/floppy/


[elvis@station elvis]$ ls /media/floppy/

Una vez el disco del sistema de archivos haya sido desmontado del directorio/media/floppy, el
directorio es sólo un directorio vacio.

Aspectos del montaje

Los dispositivos de montaje son uno de los temas mas raros y problemáticos para los nuevos
usuarios de Linux ( Unix). Los siguientes problemas se pueden presentar y agravar el asunto:

Permisos

Por defecto, solo el usuario root puede montar y desmontar dispositivos. Sin embargo, los
medios temporales se manejan de un modo diferente. El "usuario de consola" (alguien que
está conectado desde una consola virtual o una pantalla X de inicio) gana propiedades de
dispositivos asociados con la máquina física tales como un disquete y los permisos
especiales para montar estos dispositivos a los puntos de montaje predeterminados tales
como /media/floppy. Si los usuarios inician en el sistema de alguna otra manera como por
ejemplo, por red o vía el comando su, no serán considerados "usuarios de consola" y no
tendrán permiso para montar estos dispositivos.

Sistemas de archivo ocupados

Un sistema de archivo puede solo ser desmontado si se considera "no ocupado". ¿Qué
puede mantener a un sistema de archivo "ocupado"? Cualquier archivo abierto o cualquier
proceso que tenga un directorio actual de trabajo en el sistema de archivos, "ocupa" el
sistema de archivos. La única forma para que el sistema de archivo sea desmontado es
rastrear los procesos que puedan estar "ocupando" el sistema de archivos y matarlos.

Programas de montaje automático

El entorno gráfico GNOME ejecuta un programa de montaje automático, el cual vigila el


controlador del CD/ROM, y de modo automático monta el sistema de archivos de un disco
recién insertado. El programa de montaje automático es parte del entorno gráfico y no
existe si un usuario ha iniciado sesión a través de una consola virtual. Además, el
programa de montaje automático sólo funciona para el controlador de CD/ROM. El
disquete y los otros dispositivos deben montarse "manualmente".

Kernel Buffering

Con el fin de mejorar el rendimiento, el kernel memoriza todas las interacciones del
dispositivo de bloque (disco duro). Por ejemplo, cuando copia un archivo en un disquete, el
archivo puede parecer haber sido copiado casi inmediatamente.'Más tarde, al desmontar el
disquete con el comando umount, el comando se tomará un tiempo para volver mientras
se confirman la escritura en el disquete, Al desmontar el dispositivo, el kernel es forzado a
confirmar todas las transaccciones pendientes en el disco.

106
¿Qué sucedería si usted quitara el disquete del controlador antes de que la escritura
almacenada en el búfer fuera guardada en el disco? El mejor de los casos podría ser que
los archivos que creyó que tenía ya copiados en el disco no estuvieran allí. Lo peor, sería
que puede haber dañado el disco y puede que confunda al Kernel de Linux la próxima vez
se intente montar un disquete.

El resultado: no sólo debe montar medios temporales (como disquetes) antes de poder
utilizarlos, debe también desmontar los medios al terminar.

Ejemplos

Uso de un disquete sin formato

La usuaria madonna tiene una colección de canciones para copiar a un disquete sin formato y
compartirlas con sus amigos. Como sabe que sus amigos usan Red Hat Enterprise Linux, decide
formatear un disquete con un sistema de archivos ext2.

[madonna@station madonna]$ /sbin/mkfs.ext2 /dev/fd0


mke2fs 1.32 (09-Nov-2002)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
184 inodes, 1440 blocks
72 blocks (5.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
184 inodes per group

Writing inode tables: done


Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 21 mounts or


180 days, whichever comes first. Use tune2fs -c or -i to override.

Luego, monta el disquete y copia sus archivos en él.

[madonna@station madonna]$ mount /media/floppy/


[madonna@station madonna]$ cp song* /media/floppy/
[madonna@station madonna]$ cd /media/floppy/
[madonna@station floppy]$ ls
lost+found song02.ogg song04.ogg song06.ogg
song01.ogg song03.ogg song05.ogg song07.ogg

Luego desmonta su disquete.

[madonna@station madonna]$ umount /media/floppy/


umount: /media/floppy: device is busy

107
¿Por qué no se podría desmontar el disquete? Algún proceso tiene un archivo abierto, o un
directorio de trabajo actual en el disco del sistema de archivos. El proceso infractor es la shell bash
de madonna, cuyo directorio de trabajo actual es /media/floppy . Para desmontar el disquete,
madonna debe cd a otra parte, como su directorio de inicio.

[madonna@station floppy]$ cd
[madonna@station madonna]$ umount /media/floppy/

Ahora ella puede quitar el disquete del controlador.

Uso de un disquete con formato DOS

Finalmente, madonna se encuentra con un amigo quien insiste que puede solo usar los disquetes
con formato DOS. Madonna da formato a otro disquete, esta vez con el sistema de archivo MS-
DOS, monta el disquete y copia sus archivos en él.

[elvis@station elvis]$ umount /media/floppy/


[elvis@station elvis]$ ls /media/floppy/

Después de copiar los archivos en el disquete, decide que le gustaría crear un enlace blando para
identificar la canción favorita para su amigo.

[madonna@station madonna]$ /sbin/mkfs.msdos /dev/fd0


mkfs.msdos 2.8 (28 Feb 2001)
[madonna@station madonna]$ mount /media/floppy/
[madonna@station madonna]$ cp song0* /media/floppy/

¿Por qué madonna no pudo crear el enlace? Aunque Linux soporta el sistema de archivos MS-
DOS, el sistema de archivos MS-DOS es mucho más sencillo que los sistemas de archivos
tradicionales de Linux. Linux necesita hacer algunos acuerdos. Uno de estos es que el sistema de
archivos MS-DOS no soporta enlaces blandos (ni enlaces duros). Ningún sistema de archivos
soporta los archivos propietarios y permisos de archivo. ¿Cómo maneja Linux esto? Linux trata
todos los archivos como propiedad del mismo usuario y todos los permisos como 755. ¿Qué
sucede cuando madonna trata de cambiar los permisos en uno de los archivos?

[madonna@station madonna]$ cd /media/floppy/


[madonna@station floppy]$ ls
song01.ogg song03.ogg song05.ogg song07.ogg
song02.ogg song04.ogg song06.ogg
[madonna@station floppy]$ ln -s song06.ogg my_favorite_song.ogg
ln: creating symbolic link `my_favorite_song.ogg' to `song06.ogg':
Operation not
permitted

Otra vez, la operación no es permitida. Los diferentes sistemas de archivo proporcionan diferentes
capacidades y el sistema de archivos de MS DOS no es tan destacado como el sistema de
archivos ext2.

108
Ahora que ha terminado, ejecuta el comandocd a su directorio de inicio y desmonta el disquete.

[madonna@station floppy]$ chmod 664 song05.ogg


chmod: changing permissions of `song05.ogg' (requested: 0664, actual:
0644): Ope
ration not permitted

¿Por qué no ejecutó primero el comando cd a su directorio de inicio?

Imágenes de disquete

Varios amigos le han pedido a mandonna varias copias del mismo disco. Después de un tiempo, se
cansa de formatear los disquetes, montarlos, copiar las mismas 8 canciones y desmontarlos.
Decide agilizar el proceso creando un archivo de imagen para su disquete.

Primero prepara un disquete con los archivos que quiere distribuir.

[madonna@station floppy]$ cd
[madonna@station madonna]$ umount /media/floppy/

Luego, copia, el contenido del disquete desmontado, byte por byte, dentro de un archivo llamado
songs.img.

[madonna@station madonna]$ /sbin/mkfs.ext2 /dev/fd0 > /dev/null


mke2fs 1.32 (09-Nov-2002)
[madonna@station madonna]$ mount /media/floppy/
[madonna@station madonna]$ cp song* /media/floppy/
[madonna@station madonna]$ ls /media/floppy/
lost+found song02.ogg song04.ogg song06.ogg
song01.ogg song03.ogg song05.ogg song07.ogg
[madonna@station madonna]$ umount /media/floppy/

Luego, copia, el contenido del disquete desmontado, byte por byte, dentro de un archivo llamado
songs.img.

[madonna@station madonna]$ cat /dev/fd0 > songs.img

El comando cat que hemos estado usando para ver los archivos de texto sencillos, sirve tanto
como los archivos binarios o en este caso, los datos de disco binarios. Después de unos pocos
segundos de dar vueltas el disquete, ella tiene un nuevo archivo. ¿Qué tan grande es?

[madonna@station madonna]$ ls -s songs.img


1444 songs.img

109
1.4 MBytes, exactamente. ¡Qué se puede esperar de un disquete! Ella almacena este archivo de
imagen desde el disquete y cada vez que alguien quiere una nueva copia de su disquete, invierte el
proceso ejecutando cat volviendo a un disco sin formato.

[madonna@station madonna]$ cat songs.img > /dev/fd0

Dado que la imagen del archivo es transferida, byte por byte, al nuevo disquete, este comando
tiene el efecto de dar formato al disquete con un sistema de archivo ext2 y copia los archivos a
éste, todo en un solo paso. Esta es una técnica muy poderosa conocida como controladores de
imagen, y funciona en cualquier tipo de disco, no sólo en disquetes.

Cuando se accede a los dispositivos en un bajo nivel, es importante que el dispositivo sea
desmontado. Si madonna hubiera ejecutado de último en un disquete montado, el kernel muy
seguramente se habría confundido y el disquete se habría dañado.

Ejercicios en línea

Uso de disquetes Lab Exercise Objetivo: Formatear, montar, y desmontar un disquete

Configuración

Usted necesitará un disquete para este ejercicio. El contenido del disquete será destruído.

Especificaciones

En este ejercicio de laboratorio, usted formateará un disquete, lo montará, copiará archivos en él y


luego lo desmontará.

1. Asegúrese que el disquete no sea protegido contra escritura y colóquelo en el controlador.


2. Dé formato al disquete con el sistema de archivo ext2 mediante el comando
/sbin/mkfs.ext2.
3. Monte el disco en el directorio /media/floppy mediante el comando mount.
4. De modo recursivo copie el contenido del directorio /etc/sysconfig en su disquete (ignore
los anuncios de error de que usted no tiene permisos de lectura para algunos archivos).
5. Desmonte su disquete. Si es posible, intercambie disquetes con su vecino en este
momento.
6. Monte el disquete de su vecino (vuelva a montar el suyo) en el directorio /media/floppy.
7. Con el disquete aún montado, capture la salida del comando df en el archivo df.floppy en
su directorio de inicio.

Deliverables A title Question 1

1. Un disquete formateado con ext2, montado en el directorio /media/floppy.


2. Un directorio /media/floppy/sysconfig, el cual es una copia recursiva del directorio
/etc/sysconfig (quizás con unos pocos archivos inaccesibles omitidos).

Un archivo en su directorio de inicio llamado df.floppy, el cual contiene la salida del


comando df.

Possible Solution

110
The following sequence of commands provides one possible solution to this exercise.

[student@station student]$ /sbin/mkfs.ext2 /dev/fd0


mke2fs 1.32 (09-Nov-2002)
Filesystem label=
OS type: Linux
...
[student@station student]$ mount /media/floppy/
[student@station student]$ cp -r /etc/sysconfig /media/floppy/
cp: cannot open `/etc/sysconfig/rhn/up2date' for reading: Permission
denied
cp: cannot open `/etc/sysconfig/rhn/systemid' for reading: Permission
denied
...
[student@station student]$ df > df.floppy
[student@station student]$ umount /media/floppy/

Limpieza

Usted puede desmontar su disquete después de haber sido calificado, si piensa seguir al siguiente
ejercicio, grabe el contenido de su disquete.

Creación de un disco imagen Lab Exercise Objetivo:Crear una imagen de un controlador de


disquete Tiempo estimado: 15 minutos.

Configuración

Necesitará el disquete creado en el ejercicio anterior, es decir, un disquete con formato ext2 que
contenga una copia recursiva del directorio /etc/sysconfig.

Especificaciones

En este ejercicio de laboratorio, usted creará un archivo imagen de un disquete y luego restaurará
el disquete mediante el archivo imagen.

1. Asegúrese de que el disquete no esté protegido contra escritura y colóquelo en el


controlador del disquete. También revise que el disquete no esté montado. Si es necesario,
desmonte el disquete con el comando umount.
2. Mediante el comando cat, haga un archivo de imagen de un disquete en su directorio de
inicio llamado floppy.img.
3. Mediante el comando ls -s, confirme que el tamaño de su imagen es de 1444 kbytes.
4. Mediante el comando file, asegúrese de que el archivo ha sido identificado como un
sistema de archivo ext2.
5. Con el disquete aún en el controlador y aún desmontado, vuelva a formatear el disquete
con el sistema de archivos msdos (mediante el comando /sbin/mkfs.msdos).
6. Monte su disquete en el directorio /media/floppy y con el comando mount sin argumentos,
confirme que el disquete haya sido formateado con el sistema de archivo msdos (vfat).
7. Desmonte el disquete. Mediante el comando cat, restaure su disquete desde el archivo
imagen.
8. Monte otra vez su disquete en el directorio /media/floppy. Con el comando mount, sin
argumentos, confirme que el sistema de archivos ext2 original ha sido restaurado.

111
Deliverables A title Question 1

1. Un disquete formateado con ext2, montado en el directorio /media/floppy.


2. Una imagen del mismo disquete, almacenada en un archivo floppy.img en su
directorio de inicio.

Possible Solution

Los siguientes comandos dan una solución para los primeros cuatro pasos de este ejercicio.

[student@station student]$ cat /dev/fd0 > floppy.img


[student@station student]$ file floppy.img
floppy.img: Linux rev 1.0 ext2 filesystem data
[student@station student]$ ls -s
total 1448
4 df.floppy 1444 floppy.img

Limpieza

Dado que el archivo imagen que usted creó en este ejercicio es bastante grande, puede suprimirlo
después de que el ejercicio haya sido calificado.

112
Localización de archivos con locate y find

Conceptos clave

• El comando locate utiliza una base de datos para localizar rápidamente los archivos en el
sistema por el nombre de archivo.
• El comando find realiza en tiempo real, una busqueda de modo recursivo del sistema de
archivos.
• El comando find puede buscar archivos basados en información de inodo.
• El comando find puede ejecutar comandos arbitrarios en archivos.

Discussion

Ubicación de archivos

Es común encontrar archivos de configuración en /etc o ejecutables en un directorio bin, sin


embargo, algunas veces es necesario buscar un archivo específico en el sistema. Dos de las
herramientas comunes para esto son los comandos locate y find.

El comando locate escribe los nombres de los archivos y directorios que coinciden con un modelo
proporcionado. Es el más rápido de los dos comandos porque éste depende de una base de datos
(actualizada a diario por defecto) en lugar de buscar en tiempo real. La desventaja de esto es que
no encontrará archivos creados hoy y encontrará archivos que hayan sido borrados desde la última
actualización de la base de datos.

El comando find puede hallar archivos por nombre, pero también puede buscar archivos por
propietario, grupo, tipo, fecha de modificación y otros criterios. Con su búsqueda en tiempo real a
través del árbol de directorio es más lento que con locate, pero también es más flexible.

Uso de Locate

El comando /usr/bin/locate es un enlace simbólico para /usr/bin/slocate - cualquier nombre de


comando puede utilizarse. Una búsqueda slocate considera los permisos de los archivos con
respecto al usuario que realiza la búsqueda y sólo devolverá archivos que el usuario normalmente
puede ver.

Anteriormente, usamos el comando umount para desenlazar un sistema de archivo desde un árbol
de directorios. Veamos qué archivos en el sistema de archivos incluyen la cadena "umount" en sus
nombres.

[blondie@station blondie]$ locate umount


/usr/bin/smbumount
/usr/share/man/man2/umount.2.gz
/usr/share/man/man2/umount2.2.gz
/usr/share/man/man8/umount.8.gz
/usr/share/man/man8/smbumount.8.gz
/usr/share/icons/slick/16x16/devices/hdd_umount.png
/usr/src/linux-2.4.18-24.8.0/fs/jfs/jfs_umount.c
/bin/umount

113
Observe que además de /bin/umount también hemos localizado el comando smbumount y varios
archivos de páginas del manual.

El comando de localización también soporta los "comodines de archivos" o más formalmente, la


expansión del nombre de ruta mediante las mismas expresiones *, ?, y [...] como la shell bash. Por
ejemplo, si usted supiera que había una imagen PNG de un pescado en alguna parte del sistema,
usted trataría de ejecutar el siguiente comando de localización.

[blondie@station blondie]$ locate *fish.png


/usr/share/doc/libogg-devel-1.0/white-xifish.png
/usr/share/doc/libvorbis-devel-1.0/white-xifish.png
/usr/share/pixmaps/gnome-fish.png
/usr/share/icons/Bluecurve/16x16/actions/babelfish.png
/usr/share/icons/Bluecurve/16x16/apps/sawfish.png
/usr/share/icons/Bluecurve/22x22/actions/babelfish.png
/usr/share/icons/Bluecurve/32x32/apps/sawfish.png
/usr/share/icons/Bluecurve/48x48/apps/sawfish.png
/usr/share/backgrounds/tiles/fish.png
/usr/share/galeon/babelfish.png
/usr/share/aquarium/sherman/swordfish.png
/usr/share/aquarium/sherman/blowfish.png

Uso de find

El comando find se utiliza para buscar en el sistema de archivos archivos que cumplan con el
criterio especificado. Casi cualquier aspecto del archivo se puede especificar como por ejemplo, el
nombre, el tamaño, la última modificación, e incluso el conteo de enlaces (la única excepción es el
contenido del archivo. Para el cual debemos esperar por un comando llamado grep, el cual se
complementa muy bien con find).

Toma un poco de tiempo familiarizarse con la sintaxis del comando find, pero una vez aprendida
es muy útil. Un comando find consta por naturaleza de tres partes: un directorio raíz (o directorios),
criterios de búsqueda y una acción.

Buscar (directorio raíz) (criterios) (acción)

El directorio predeterminado es ".", los criterios por defecto son "todo archivo", y la acción por
defecto es "imprimir" (el nombre de archivo), por lo tanto al ejecutar el comando find sin
argumentos simplemente bajará el directorio actual, e imprimirá cada nombre de archivo. Si se
diera un directorio como único argumento, lo mismo se haría para ese directorio.

114
[madonna@station madonna]$ find /etc/sysconfig/networking/
/etc/sysconfig/networking/
/etc/sysconfig/networking/devices
/etc/sysconfig/networking/devices/ifcfg-eth0
/etc/sysconfig/networking/profiles
/etc/sysconfig/networking/profiles/default
/etc/sysconfig/networking/profiles/default/network
/etc/sysconfig/networking/profiles/default/resolv.conf
/etc/sysconfig/networking/profiles/default/hosts
/etc/sysconfig/networking/profiles/default/ifcfg-eth0
/etc/sysconfig/networking/profiles/netup
/etc/sysconfig/networking/profiles/netup/network
/etc/sysconfig/networking/profiles/netup/resolv.conf
/etc/sysconfig/networking/profiles/netup/hosts
/etc/sysconfig/networking/profiles/netup/ifcfg-eth0
/etc/sysconfig/networking/ifcfg-lo

No obstante, por lo general el comando find se le da criterios para refinar su búsqueda, en forma
de opciones (no estándar). Por ejemplo, la opción -name se utiliza para buscar archivos con un
nombre dado (o nombre comodín).

[madonna@station madonna]$ find /etc -name *.conf


/etc/sysconfig/networking/profiles/default/resolv.conf
/etc/sysconfig/networking/profiles/netup/resolv.conf
find: /etc/sysconfig/pgsql: Permission denied
/etc/X11/gdm/factory-gdm.conf
/etc/X11/gdm/gdm.conf
/etc/modprobe.conf
/etc/host.conf
/etc/nsswitch.conf
...

Aunque superficialmente similar a las funciones de los comandos locate, el comando find funciona
realizando una búsqueda en tiempo real. Esto puede tardar mucho más, pero evita el problema de
una base de datos "fuera de sincronización" Tenga en cuenta que si no se sigue el orden correcto,
el comando find se torna confuso rápidamente.

[madonna@station madonna]$ find -name *.conf /etc


find: paths must precede expression
Usage: find [path...] [expression]

Busque criterios

Si usted navega la página find(1) del manual, descubrirá que se pueden especificar una cantidad
abrumadora de criterios para su búsqueda. Casi cualquier aspecto del archivo que el comando stat
o el comando ls puedan reportar es parte del juego limpio. El siguiente cuadro resume algunos de
los criterios de búsqueda más comunes.

Table 1. Criterios de búsqueda para el comando find

115
opción especificaciones
-empty El archivo es un directorio o un archivo regular y está vacío.
-group El archivo pertenece al grupo gname.
gname
-inum n El archivo tiene un número de inodo n.
-links n El archivo tiene n enlaces.
-mmin n El archivo fue modificado hace n minutos.
-mtime n El archivo fue modificado hace n días.
-nombre El nombre del archivo coincide con el archivo comodín patrón.
patrón
-newer El archivo fue modificado más recientemente que filename.
filename
-permmode Los permisos del archivo son exactamente mode.
-perm -mode Todos los bits de permisos mode se establecen para el archivo.
-perm Cualquiera de los bits de permiso modese establecen para el archivo.
+mode
-size n El archivo tiene un tamaño de n.
-type c El archivo es de tipo c, en donde c es "f" (archivo regular), "d" (directorio), o "l"
(enlace simbólico). Vea la página del manual para encontrar mayor información.
-user uname El archivo es de propiedad del usuario uname.

Hay más opciones disponibles, pero con estas se puede dar una idea de la flexibilidad del
comando find. Cualquier criterio que tome un argumento numérico tal como -size o -mtime,
reconoce los argumentos de la forma +3 (lo que significa mayor que 3), -3 (significa menor que 3),
ó 3 (significa exactamente 3).

Si hay múltiples criterios especificados, por defecto, todos los criterios deben cumplirse. No
obstante, si los múltiples criterios son separados por -or, cualquier condición puede cumplirse. Los
criterios pueden ser invertidos por los criterios anteriores con -not.

A manera de ejemplo, el siquiente comando busca todos los archivos bajo /var, los cuales no
tienen permiso de escritura para el grupo.

[elvis@station elvis]$ find /var -not -perm +20


/var
/var/lib
/var/lib/rpm
/var/lib/rpm/Packages
/var/lib/rpm/Basenames
/var/lib/rpm/Name
/var/lib/rpm/Group
...

Buscar acciones

Usted puede también especificar qué le gustaría hacer a los archivos que cumplen con los criterios
especificados, el nombre del archivo imprime en salida estándar, un archivo por línea. Las demás
opciones se resumen en el siguiente cuadro.

Table 1. Especificaciones de acción para el comando find

116
Opción Acción
-exec Ejecuta commanden archivos coincidentes. Usa {}para indicar dónde debe
command ; sustituirse el nombre de archivo.
-ok command ; Igual que -exec, pero prompt para cada archivo
-ls Imprime archivo en formato ls -dils.

Hay otras más. Consulte la página find (1) del manual.

Quizás, el comando más útil y sin duda más extraño de estos es -exec, y su primo cercano -ok. El
mecanismo de -exec es un mecanismo poderoso: en lugar de imprimir los nombres de los archivos
coincidentes, ejecuta los comandos arbitrarios. El mecanismo del comando -exec es extraño
porque la sintaxis para especificar el comando es complicada. El comando debería escribirse
después de la opción-exec, utilizando un {} literal como parámetro para el nombre de archivo. El
comando debería terminarse con un ; literal, pero como veremos en un cuaderno más adelante, el ;
tiene un significado especial para la shell y por lo tanto se debe "escapar" agregándole un \.
Veamos el siguiente ejemplo.

Suponga que madonna quería una copia de cada archivo mayor de 200 bytes del directorio /etc.
Primero, busca los archivos que cumplen con los criterios.

[madonna@station madonna]$ find /etc -size +200k 2>/dev/null


/etc/termcap
/etc/gconf/gconf.xml.defaults/schemas/apps/metacity/general/%gconf.xml
/etc/gconf/gconf.xml.defaults/schemas/apps/metacity/window_keybindings/%gconf.xml
/etc/gconf/schemas/metacity.schemas
/etc/gconf/schemas/gedit.schemas
/etc/gconf/schemas/gnomemeeting.schemas

(El comando 2>/dev/null sirve para "botar " las quejas acerca de los directorios a los que madonna
no tiene permisos de acceso).

Para confirmar los tamaños de los archivos, ella vuelve a ejecutar el comando, especificando la
"acción" de -ls.

[madonna@station madonna]$ find /etc -size +200k -ls 2>/dev/null


228520 728 -rw-r--r-- 1 root root 738310 Jan 25 02:14 /etc/termcap
35154 296 -rw-r--r-- 1 root root 295168 Apr 1 11:52 /etc/gconf/gc
onf.xml.defaults/schemas/apps/metacity/general/%gconf.xml
34176 216 -rw-r--r-- 1 root root 215419 Apr 1 11:52 /etc/gconf/gc
onf.xml.defaults/schemas/apps/metacity/window_keybindings/%gconf.xml
588723 456 -rw-r--r-- 1 root root 459213 Feb 24 18:41 /etc/gconf/sc
hemas/metacity.schemas
588743 304 -rw-r--r-- 1 root root 304919 Feb 4 10:45 /etc/gconf/sc
hemas/gedit.schemas
591139 292 -rw-r--r-- 1 root root 290975 Feb 24 17:50 /etc/gconf/sc
hemas/gnomemeeting.schemas

Ahora, ella crea un directorio llamado /tmp/big y compone un comando cp en la línea de comando
find, recordando lo siguiente.

• Coloque {} como parámetro para nombres de archivos coincidentes.

117
• Termine el comando con un \;.

[madonna@station madonna]$ mkdir /tmp/big


[madonna@station madonna]$ find /etc -size +200k -exec cp {} /tmp/big \;
2>/dev
/null
[madonna@station madonna]$ ls /tmp/big/
%gconf.xml gedit.schemas gnomemeeting.schemas metacity.schemas termcap

En lugar de imprimir el nombre del archivo, el comando find copió los archivos en el directorio /tmp/
big.

Ejemplos

Uso de locate

Hay varias formas de hallar un archivo específico.

[blondie@station blondie]$ locate rmdir


/usr/lib/perl5/5.8.0/i386-linux-thread-multi/auto/POSIX/rmdir.al
/usr/share/doc/bash-2.05b/loadables/rmdir.c
/usr/share/man/man1/rmdir.1.gz
/usr/share/man/man2/rmdir.2.gz
/bin/rmdir
[blondie@station blondie]$ find /bin -name "*dir*"
/bin/mkdir
/bin/rmdir
[blondie@station blondie]$ which rmdir
/bin/rmdir

En los ejemplos anteriores, locate muestra todo en la base de datos con la cadena
"rmdir"incluyendo el comando y las páginas del manual. El comando find muestra todos los
archivos bajo el /bin que incluyen "dir" en el nombre. Por último, el comando which muestra la ruta
absoluta para un comando conocido.

Usted también puede incluir los caracteres de expansión del nombre de archivo en su búsqueda:

[blondie@station blondie]$ locate "*theme*png"


...
/usr/share/galeon/themes/Remembrance/New.png
/usr/share/galeon/themes/Remembrance/Print-prelight.png
/usr/share/galeon/themes/Remembrance/Print.png
/usr/share/galeon/themes/Remembrance/Stop-prelight.png
/usr/share/galeon/themes/Remembrance/Refresh.png
/usr/share/galeon/themes/Remembrance/Up-prelight.png
/usr/share/galeon/themes/Remembrance/Stop.png
/usr/share/galeon/themes/Remembrance/empty.png
/usr/share/galeon/themes/Remembrance/Up.png
/usr/share/galeon/themes/Remembrance/empty-prelight.png

118
Recuerde que el comando locate usa una base de datos y no localizará archivos que hayan sido
creados desde la última modificación de la base de datos. El ejemplo anterior no debería mostrar
ninguna salida de dicho comando.

[blondie@station blondie]$ touch ~/locate_example_file


[blondie@station blondie]$ locate locate_example_file

Uso de find

El comando find busca el árbol de directorios real desde el punto de inicio especificado.

[elvis@station elvis]$ find /home/elvis


/home/elvis/
/home/elvis/.kde
/home/elvis/.kde/Autostart
/home/elvis/.kde/Autostart/Autorun.desktop
/home/elvis/.kde/Autostart/.directory
/home/elvis/.bash_logout
/home/elvis/.bash_profile
/home/elvis/.bashrc
/home/elvis/.emacs
/home/elvis/.gtkrc
/home/elvis/somefile

El comando find listará todos los archivos incluyendo todos los archivos ocultos cuando sólo se
especifica un directorio de inicio. Sin embargo, cuando se está buscando el nombre de archivo, es
importante especificar si se van a buscar archivos ocultos.

[elvis@station elvis]$ find /home/elvis -name "*bash*"


[elvis@station elvis]$ find /home/elvis -name ".*bash*"
/home/elvis/.bash_logout
/home/elvis/.bash_profile
/home/elvis/.bashrc

El directorio de inicio para find pueden ser múltiples directorios de inicio.

119
[elvis@station elvis]$ find /bin /usr/bin -name "*dir*"
/bin/mkdir
/bin/rmdir
/usr/bin/dir
/usr/bin/dircolors
/usr/bin/vdir
/usr/bin/dirname
/usr/bin/mdir
/usr/bin/ttmkfdir
/usr/bin/directomatic
/usr/bin/pi-nredir

Busca los enlaces simbólicos creados en el capítulo anterior.

[einstein@station einstein]$ find ~ -type l


/home/einstein/docs
/home/einstein/fd0

Genera con ls -l un listado de estilos de todo lo que no sea propiedad en el sistema de los usuarios
root, bin o student. Pueden haber directorios donde el acceso de búsqueda sea negado por lo
tanto, también redirige los errores a /dev/null para que no aparezcan en la pantalla.

[elvis@station elvis]$ find / -not -user root -not -user bin -not -user student
-ls 2> /dev/null
...
8037 1 drwxr-xr-x 2 ntp ntp 1024 Dec 22 17:08 /etc/ntp
8040 0 -rw-r--r-- 1 ntp ntp 0 Aug 31 2002
/etc/ntp/step
-tickers
8038 1 -rw-r--r-- 1 ntp ntp 4 Aug 31 2002
/etc/ntp/drif
t
8039 1 -rw------- 1 ntp ntp 266 Aug 31 2002
/etc/ntp/keys
42299 8 -rw-r----- 1 smmsp root 12288 Mar 4 08:17
/etc/mail/vir
tusertable.db
42300 12 -rw-r----- 1 smmsp root 12288 Mar 4 08:17
/etc/mail/acc
ess.db
42301 8 -rw-r----- 1 smmsp root 12288 Mar 4 08:18
/etc/mail/dom
aintable.db
42302 8 -rw-r----- 1 smmsp root 12288 Mar 4 08:18
/etc/mail/mai
lertable.db
28204 12 -rw-r----- 1 smmsp smmsp 12288 Mar 16 15:36
/etc/aliases.
db
44276 2044 -rwxr-xr-x 1 rpm rpm 2083816 Sep 4 2002 /bin/rpm

120
Uso de find para ejecutar comandos en archivos

Busca todos los archivos que están bajo /tmp con el conteo de enlace mayor que 1 y hace una
copia de cada uno en un directorio llamado /tmp/links.

[blondie@station blondie]$ ls -l /tmp/*file


-rw-rw-r-- 2 blondie blondie 0 Mar 17 22:33
/tmp/linkfile
-rw-rw-r-- 2 blondie blondie 0 Mar 17 22:33 /tmp/newfile
[blondie@station blondie]$ mkdir /tmp/links
[blondie@station blondie]$ find /tmp -type f -links +1 -exec cp {} /tmp/
links \;
[blondie@station blondie]$ ls /tmp/links
linkfile
newfile

Ejercicios en línea

Ubicación de archivos Lab Exercise Objetivo: Diseñar y ejecutar un comando find que genere el
resultado descrito en cada uno de los siguientes.Tiempo estimado: 20 minutos.

Especificaciones

Use el comando find para buscar archivos coincidentes con los siguientes criterios y redireccione
la salida a los archivos especificados en su directorio de inicio. Al listar los archivos asegúrese de
que cada nombre de archivo sea una referencia absoluta.

Encontrará un número de mensajes de "Permiso denegados" cuando find trata de acceder de


modo recursivo a los directorios, para los cuales usted no tiene permiso. No se preocupe por estos
mensajes de error. Usted los puede suprimir añadiendo el comando 2> /dev/null a su comando
find.

Puede que necesite consultar la página del manual find(1) para hallar respuesta a algunos de los
problemas.

content_view let_
Deliverables A title Question 1

1. El archivo varlib.games contiene un listado de todos los archivos bajo el directorio /var/lib,
pertenecientes al usuario "games".
2. El archivo var.rootmail contiene un listado de todos los archivos bajo el directorio /var,
pertenecientes al usuario "root" y al grupo "mail".
3. El archivo bin.big contiene un listado de estilos ls -dils de todos los archivos bajo el
directorio /usr/bin mayores de 1000000 caracteres de tamaño.
4. Ejecute el comando file en cada archivo bajo /etc/sysconfig y registre la salida en el archivo
sysconfig.find.

121
5. El archivo big.links contiene un listado de nombres de archivos regulares bajo el directorio /
usr/lib/locale, el cual tiene un conteo de enlaces mayor a 100.

122
Comprimir archivos: gzip y bzip2

Conceptos clave

• La comprensión de archivos pocas veces ahorra espacio en el disco.


• El comando más utilizado para comprimir es gzip.
• El comando bzip2 es más reciente y proporciona la compresión maś eficaz.

Discussion

¿Por qué comprimir archivos?

Los archivos que no se utilizan mucho con frecuencia se comprimen. Los archivos grandes también
se comprimen antes de transferirlos a otros sistemas o usuarios. Las ventajas del ahorro de
espacio y de amplitud de banda suelen superar el tiempo que toma para comprimir o descomprimir
archivos.

Los archivos de texto a menudo tienen patrones que se pueden comprimir hasta un 75% , pero los
archivos binarios rara vez comprimen más de un 25%. De hecho, es incluso posible que un archivo
binario sea ¡más grande que el original!

Utilidades estándares de compresión Linux

Dado que se han desarrollado cada vez mejores técnicas de compresión, se han ganado nuevas
utilidades de compresión. Sin embargo, para compatibilidad retroactiva las utilidades de
compresión aún se retienen. A menudo, se compensa entre la eficiencia de compresión y la
actividad de CPU. Algunas veces, utilidades más antiguas son "suficientemente "buenas para
hacer el trabajo en mucho menos tiempo.

La siguiente lista presenta las dos utilidades para comprimir más comunes que se utilizan en Linux
y Unix.

gzip (.gz)

El comando gzip es la utilidad de descompresión más versátil y la que más se utiliza. Los
archivos comprimidos con gzip se descomprimen con gunzip. Además, el comando gzip
soporta las siguientes opciones.

Opción Efecto
-c Redireccionar la salida a stdout
-d Descomprimir en lugar de comprimir el archivo
-r Ir de modo recursivo a través de subdirectorios, comprimiendo archivos individuales.
-1 ... -9 Especificar la compensación entre la intensidad del CPU y la eficiencia de la
comprensión.
bzip2 (.bz)

El comando bzip2 es un recién llegado que tiende a generar los archivos comprimidos más
compactos, pero utiliza la CPU de manera más intensiva. Los archivos comprimidos con
bzip2 se descomprimen con bunzip2. El comando bzip2 soporta las siguientes opciones.

123
Opción Efecto
-c Redireccionar la salida a stdout
-d Descomprimir en lugar de comprimir el archivo

Los ejemplos a continuación ilustran el uso y la eficiencia relativa de los comandos de compresión.

[elvis@station elvis]$ ls -sh termcap


725K termcap
[elvis@station elvis]$ gzip termcap
[elvis@station elvis]$ ls -sh termcap*
234K termcap.gz
[elvis@station elvis]$ gzip -d termcap
[elvis@station elvis]$ ls -sh termcap*
725K termcap

[elvis@station elvis]$ ls -sh termcap


725K termcap
[elvis@station elvis]$ bzip2 termcap
[elvis@station elvis]$ ls -sh termcap*
185K termcap.bz2
[elvis@station elvis]$ bunzip2 termcap.bz2
[elvis@station elvis]$ ls -sh termcap*
725K termcap

Otras utilidades de compresión

Otra utilidad de compresión disponible en Red Hat Enterprise Linux es zip. Esta utilidad es
compatible con las utilidades de DOS/Windows PKzip/Winzip y pueden comprimir más de un
archivo en un archivo único, algo que los comandos gzip y bzip2 no pueden hacer.

Los usuarios de Linux y Unix prefieren usar los comandos tar ygzip juntos en lugar de zip. El
comando tar se describe en la siguiente lección.

Ejercicios en línea

Trabajar con las utilidades de compresión Lab Exercise Objetivo: Comprimir archivos
grandesEstimated Time: 10 mins.

Especificaciones

1. Copie los archivos /etc/gconf/schemas/gnome-terminal.schemas y /usr/bin/gimp dentro de


su directorio de inicio, conservando sus nombres de archivo originales, (el primero es un
ejemplo de un archivo de texto grande, el segundo es un ejemplo de un archivo grande
binario). Utilice el comando gzip para comprimir cada uno de los archivos recién creados.
2. Nuevamente, copie los archivos /etc/gconf/schemas/gnome-terminal.schemas y
/usr/bin/gimp dentro de su directorio de inicio. Esta vez, utilice el comando bzip2 para
comprimir los dos archivos.
3. Por última vez, copie los archivos /etc/gconf/schemas/gnome-terminal.schemas y
/usr/bin/gimp dentro de su directorio de inicio. Utilice el comando ls -s para comparar los
tamaños de varias de las técnicas de compresión.

124
Deliverables A title Question 1

1. El archivo gnome-terminal.schemas en su directorio de inicio, el cual es una copia de


/etc/gconf/schemas/gnome-terminal.schemas.
2. El archivo gnome-terminal.schemas.gz, la versión con gzip de gnome-terminal.schemas.
3. El archivo gnome-terminal.schemas.bz2, la versión con bzip2 degnome-terminal.schemas.
4. El archivo gimp en su directorio de inicio, el cual es una copia de /usr/bin/gimp.
5. El archivo gimp.gz, la versión comprimida con gzip de gimp.

El archivo gimp.bz2, la versión comprimida con bzip2 de gimp.

content_view let_

125
Archivar ficheros con tar

Conceptos clave

• Al archivar ficheros se puede almacenar una estructura entera de directorio como un


archivo único.
• Los archivos se crean, se listan y se extraen con el comando tar.
• A menudo, los archivadores de ficheros también se comprimen.
• La aplicación fileroller proporciona una interfaz GUI para archivadores de ficheros.

Discussion

Archivadores de ficheros

Con frecuencia, si un directorio y sus archivos subyacentes no se van a utilizar por un tiempo, o si
el árbol entero de directorios se transfiere de un lugar a otro, la gente convierte al árbol de
directorios en un archivador. El archivo contiene el directorio y sus archivos y subdirectorios
subyacentes, empacados como un solo archivo. En Linux (y Unix), el comando más común para
crear y extraer archivos es el comando tar.

En un inicio, los archivadores de ficheros fueron una solución para hacer una copia de seguridad
de discos en cintas magnéticas. Al hacer una copia de seguridad de un sistema de archivos, la
estructura entera de directorio se convertía en un solo archivo, el cual se escribía directamente al
controlador de cinta. El comando tar se deriva del inglés "t"ape "ar"chive.

Actualmente, el comando tar se utiliza muy rara vez para escribir directamente en las cintas, pero
en su lugar crea archivadores de ficheros que a menudo se denominan "ficheros tar", "archivos
tar", o algunas veces de un modo informal como "tarballs". A estos paquetes de archivos suele
dárseles la extensión del nombre de archivo .tar.

Conceptos básicos del comando Tar

Cuando se ejecuta el comandotar, se debe seleccionar la primera línea del comando de las
siguientes opciones.

Opción Efecto
-c, --create Crear un archivador de ficheros
-x, --extract Extraer un archivador de ficheros
-t, --list Lista el contenido de un archivador de ficheros

Hay otros, pero casi siempre uno de estos tres será suficiente. Para mayor información consulte la
página del manual tar(1).

Casi cada invocación del comando tar debe incluir la opción -f y su argumento, el cual especifica el
archivador de ficheros que se está creando, extrayendo o listando.

A manera de ejemplo, el usuario prince ha estado trabajando en un informe, el cual involucra varios
archivos y subdirectorios.

126
report/
|-- html/
| |-- chap1.html
| |-- chap2.html
| `-- figures/
| `-- image1.png
`-- text/
|-- chap1.txt
`-- chap2.txt

3 directories, 5 files

Le gustaría enviar por correo-e una copia del informe a un amigo. En lugar de adjuntar cada
archivo de manera individual a un correo-e decide crear un archivador del directorio del informe.
Utiliza el comando tar, especificando -c para "c"rear un archivo y utilizar la opción -f para
especificar el archivador de ficheros que va a crear.

[prince@station prince]$ tar -c -f report.tar report


[prince@station prince]$ ls -s
total 24
4 report 20 report.tar

El archivador de ficheros recién creado report.tar, contiene ahora todo el contenido del directorio
report y sus subdirectorios. Con el fin de confirmar que el archivo fue creado correctamente, prince
lista el contenido del archivador del fichero con el comando tar -t (utilizando una vez más -f para
especificar el archivador de fichero).

[prince@station prince]$ tar -t -f report.tar


report/
report/text/
report/text/chap1.txt
report/text/chap2.txt
report/html/
report/html/figures/
report/html/figures/image1.png
report/html/chap1.html
report/html/chap2.html

Para confirmar una vez más, prince extrae el archivador de ficheros en el directorio /tmp mediante
el comando tar -x.

127
[prince@station prince]$ cd /tmp
[prince@station tmp]$ tar -x -f /home/prince/report.tar
[prince@station tmp]$ ls -R report/
report/:
html text

report/html:
chap1.html chap2.html figures

report/html/figures:
image1.png

report/text:
chap1.txt chap2.txt

Convencido de que el archivador de ficheros contiene el informe y que su amigo podrá extraerlo,
limpia la copia de prueba y utiliza el comando mutt para enviar por correo-e el archivador a manera
de anexo.

[prince@station tmp]$ rm -fr report/


[prince@station tmp]$ cd
[prince@station prince]$ mutt -a report.tar -s "My Report"
elvis@example.com

No se preocupe si no está familiarizado con el comando mutt. Sólo sirve de ejemplo del porqué
alguien podría querer crear un archivador tar.

Algo más acerca del comando tar

La primera opción de tar debe ser una de las opciones especiales descritas anteriormente. Puesto
que la primera es siempre una de las pocas opciones, el comando tar permite un atajo, usted no
necesita incluir el guión inicial. Con frecuencia, los usuarios con experiencia en ejecutar tar utilizan
el modo abreviado de la línea de comando de la siguiente manera.

[prince@station prince]$ tar cf report.tar report


[prince@station prince]$ tar tf report.tar
report/
report/text/
report/text/chap1.txt
report/text/chap2.txt
report/html/
report/html/figures/
report/html/figures/image1.png
report/html/chap1.html
report/html/chap2.html

Crear archivos presenta una serie de preguntas complicadas tales como las siguientes.

• ¿Cuando se crean archivos, cómo se deberían manejar los enlaces? ¿Debo archivar el
enlace? o ¿a qué se refiere el enlace?

128
• Cuando extraemos los archivos como root, ¿quiero que todos los archivos pertenezcan a
root o al propietario original? ¿Qué sucede si el propietario original no existe en el sistema
en el que estoy desempacando el tar?
• ¿Qué sucede si el controlador de cinta magnética en el que estoy archivando no tiene más
espacio cuando voy en la mitad del archivo?

Las respuestas a estas y otras preguntas se pueden resolver con un abrumador número de
opciones para el tar como tar --help o una mirada rápida a la página del manual tar(1) se lo
mostrará. El siguiente cuadro lista algunos de las opciones que se utilizan con más frecuencia a
continuación explicaremos su uso.

Opción Efecto
-C, --directory=DIR Cambia al directorio DIR
-P, --absolute-reference sin / inicial desde los nombres de archivos
-v, --verbose Lista los archivos procesados
-z, --gzip internamente gzip el archivo
-j, --bzip2 internamente bzip2 el archivo

Referencias absolutas

Suponga que prince desea archivar una instantánea de la configuración de la red de trabajo actual
de su máquina. Podría ejecutar un comando como el siguiente (observe la inclusión de la opción -v
que lista cada archivo a medida que se procesa).

[prince@station prince]$ tar cvf net.tar /etc/sysconfig/networking


tar: Removing leading `/' from member names
etc/sysconfig/networking/
etc/sysconfig/networking/devices/
etc/sysconfig/networking/devices/ifcfg-eth0
etc/sysconfig/networking/profiles/
etc/sysconfig/networking/profiles/default/
etc/sysconfig/networking/profiles/default/network
...
Como lo implica el mensaje inicial, lo que era una referencia absoluta para
/etc/sysconfig/networking se convierte en referencias relativas dentro del archivo: Ninguna de las
entradas tienen barras oblicuas iniciales. ¿Por qué sucede esto? ¿Qué sucede si prince vuelve y
extrae el archivo?

129
[prince@station prince]$ tar xvf net.tar
etc/sysconfig/networking/
etc/sysconfig/networking/devices/
etc/sysconfig/networking/devices/ifcfg-eth0
etc/sysconfig/networking/profiles/
etc/sysconfig/networking/profiles/default/
etc/sysconfig/networking/profiles/default/network
etc/sysconfig/networking/profiles/default/resolv.conf
...
[prince@station prince]$ ls -R etc/
etc/:
sysconfig

etc/sysconfig:
networking

etc/sysconfig/networking:
devices ifcfg-lo profiles

etc/sysconfig/networking/devices:
ifcfg-eth0

etc/sysconfig/networking/profiles:
default netup

etc/sysconfig/networking/profiles/default:
hosts ifcfg-eth0 network resolv.conf

etc/sysconfig/networking/profiles/netup:
hosts ifcfg-eth0 network resolv.conf

Dado que las entradas al fichero fueron relativas, el archivador fue desempacado en el directorio
local. Como regla, los archivadores de ficheros siempre desempacarán de modo local, reduciendo
la posibilidad de sobrescribir ficheros en el sistema al desempacar un archivo en ellos. Al construir
el archivo, esta conducta se puede anular con la opción -P.

Establecer el contexto

Al extraer el archivo anterior, el primer directorio "interesante" es el directorio networking, porque


contiene los directorios y subdirectorios relevantes. Sin embargo, cuando se extrae el archivo y
"adicional" etc y etc/sysconfig son creados. Para obtener un directorio interesante, alguien tiene
que abrirse camino.

Al construir un archivo, la opción -C puede utilizarse para ayudar a establecer el contexto


cambiando el directorio antes de que se construya el archivo. Compare los siguientes dos
comandos tar.

130
[prince@station prince]$ tar cvf net.tar /etc/sysconfig/networking
tar: Removing leading `/' from member names
etc/sysconfig/networking/
etc/sysconfig/networking/devices/
etc/sysconfig/networking/devices/ifcfg-eth0
etc/sysconfig/networking/profiles/
etc/sysconfig/networking/profiles/default/
etc/sysconfig/networking/profiles/default/network
...
[prince@station prince]$ tar cvf net.tar -C /etc/sysconfig networking
networking/
networking/devices/
networking/devices/ifcfg-eth0
networking/profiles/
networking/profiles/default/
networking/profiles/default/network
...

Dado que las entradas al fichero fueron relativas, el archivador fue desempacado en el directorio
local. Como regla, los archivadores de ficheros siempre desempacarán de modo local, reduciendo
la posibilidad de sobrescribir ficheros en el sistema al desempacar un archivo en ellos. Al construir
el archivo, esta conducta se puede anular con la opción -P.

Establecer el contexto

Al extraer el archivo anterior, el primer directorio "interesante" es el directorio networking, porque


contiene los directorios y subdirectorios relevantes. Sin embargo, cuando se extrae el archivo y
"adicional" etc y etc/sysconfig son creados. Para obtener un directorio interesante, alguien tiene
que abrirse camino.

Al construir un archivo, la opción -C puede utilizarse para ayudar a establecer el contexto


cambiando el directorio antes de que se construya el archivo. Compare los siguientes dos
comandos tar.

[prince@station prince]$ tar cf /tmp/prince.tar -C /home/prince .


[prince@station prince]$ ls -s /tmp/prince.tar
224 /tmp/prince.tar
[prince@station prince]$ gzip /tmp/prince.tar
[prince@station prince]$ ls -s /tmp/prince.tar.gz
28 /tmp/prince.tar.gz

Dado que los usuarios están a menudo creando y comprimiendo archivos o trantando con archivos
que han sido comprimidos, el comando tar proporciona tres opciones para comprimir internamente
(o descomprimir) archivadores de ficheros. Arriba, prince pudo haber obtenido el mismo resultado
al agregar la opción -z.

[prince@station prince]$ tar czf /tmp/prince.tar.gz -C /home/prince .


[prince@station prince]$ ls -s /tmp/prince.tar.gz
28 /tmp/prince.tar.gz

131
La combinación de los comandos tar y gzip se encuentra tan a menudo, que la extensión
de.tar.gzsuele abreviarse como .tgz.

[prince@station prince]$ tar czf /tmp/prince.tgz -C /home/prince .


[prince@station prince]$ tar tzf /tmp/prince.tgz
./
./.kde/
./.kde/Autostart/
./.kde/Autostart/Autorun.desktop
./.kde/Autostart/.directory
./.bash_logout
./.bash_profile
...

¿Qué sucede si trata un archivo comprimido como si fuera un archivo descomprimido?

[prince@station prince]$ tar tf /tmp/prince.tgz


tar: This does not look like a tar archive
tar: Skipping to next header
tar: Error exit delayed from previous errors

Como el archivo estaba comprimido, debe descomprimirse (ya sea con la opción o con el comando
de descompresión apropiados) antes de que el archivo pueda ser extraído o examinado. Es
importante etiquetar los archivos con las extensiones de nombre de archivo apropiadas para que
cualquiera sepa cómo desempacarlo.

Ejemplos

Creación de un archivo tar

El usuario einstein desea hacer una copia de la documentación de bash para poder llevarla
consigo. Pronto ejecuta tar en el directorio/usr/share/doc/bash-2.05b.

[einstein@station einstein]$ tar cvzf bashdoc.tgz -C /usr/share/doc/


bash-2.05b
bash-2.05b/
bash-2.05b/article.ms
bash-2.05b/CHANGES
bash-2.05b/COMPAT
bash-2.05b/FAQ
...
[einstein@station einstein]$ ls -s bashdoc.tgz
264 bashdoc.tgz

Una vez pone el fichero en su nueva ubicación, extrae el archivo.

132
[einstein@station einstein]$ tar xvzf bashdoc.tgz
bash-2.05b/
bash-2.05b/article.ms
bash-2.05b/CHANGES
bash-2.05b/COMPAT
bash-2.05b/FAQ
bash-2.05b/INTRO
...

Ejecutar tar directamente en el disquete

El usuario maxwell desea comparar rápidamente la configuración LDAP en dos equipos diferentes.
Las máquinas no están conectadas a la red, pero ambas tienen un disquete. En lugar de crear un
archivo, formateando un disquete, montando un disquete, copiando el archivo y desmontando el
disquete, maxwelll decide ahorrarse unos cuantos pasos. Con un disquete desmontado en el
controlador, ejecuta el siguiente comando.

[maxwell@station maxwell]$ tar cvzf /dev/fd0 -C /etc openldap


openldap/
openldap/ldapfilter.conf
openldap/ldap.conf
openldap/ldapsearchprefs.conf
openldap/ldaptemplates.conf

Luego retira el disquete y lo lleva a la segunda máquina. A continuación extrae el archivo en su


directorio local.

[maxwell@station maxwell]$ tar xvzf /dev/fd0


openldap/
openldap/ldapfilter.conf
openldap/ldap.conf
openldap/ldapsearchprefs.conf
openldap/ldaptemplates.conf
openldap/ldaptemplates.conf

gzip: stdin: decompression OK, trailing garbage ignored


tar: Child died with signal 13
tar: Error exit delayed from previous errors

Aunque el comando tar (o más exactamente, el comando gzip) se quejó de la "basura de rastreo",
el archivo se extrajo con éxito.

¿Qué sucedió aquí? El comando tar escribió directamente al nodo de dispositivo del disquete, para
que el archivador de fichero fuera escrito byte por byte al disquete como datos crudos. Al extraer el
archivador, el archivo completo se lee byte por byte. Sin embargo, el comando gzip sigue
ejecutándose, tratando de descomprimir lo que estaba en el disquete antes de que se escribiera el
archivo. Esta es la "basura de rastreo" de la que el comando gzip se quejó. ¿Cuál era el nombre
de archivo del archivador cuando estaba en el disquete? -¡Pregunta delicada!

¡Ay!

133
El usuario einstein quiere crear un archivo de su directorio de inicio. Ensaya el siguiente comando.

[einstein@station einstein]$ tar cvzf ~/einstein.tgz ~


tar: Removing leading `/' from member names
home/einstein/
home/einstein/.kde/
home/einstein/.kde/Autostart/
...
home/einstein/.bash_history
home/einstein/einstein.tgz
tar: /home/einstein/einstein.tgz: file changed as we read it
tar: Error exit delayed from previous errors

¿Por qué el comando tar mostró un error? El archivador estaba siendo escrito en el fichero /home/
einstein/einstein.tgz. El archivador incluyó cada fichero en el directorio /home/einstein. Por último,
el comando tar trató de adjuntar el fichero /home/einstein/einstein.tgz al archivador /home/einstein/
einstein.tgz. Esto obviamente causa problemas.

Afortunadamente, el comando tar es lo suficientemente inteligente como para detectar referencias


circulares. En los "viejos tiempos" (no tan distantes), el primer signo de que algo andaba mal en
situaciones como estas, era el largo tiempo de espera que se tomaba el comando tar para
ejecutar, y la segunda clave, era el mensaje de error que decía que el disco no tenía espacio.

¿Qué solución? Asegúrese que el archivador de ficheros que está creando no existe en el
directorio que usted está archivando. El directorio /tmp es muy útil.

[einstein@station einstein]$ tar czf /tmp/einstein.tgz ~


tar: Removing leading `/' from member names
[einstein@station einstein]$ mv /tmp/einstein.tgz .

Ejercicios en línea

Archivar directorios Lab Exercise Objetivo: Crear un archivo con el comando tar.Tiempo
estimado: 15 minutos.

Especificaciones

1. En su directorio de inicio, cree el archivo zip_docs.tar, el cual es un archivo de


documentación para el paquete comprimido con zip ubicado en el directorio /usr/share/doc/
zip*.
2. Cree el archivo /tmp/student.tgz, el cual es un archivo comprimido con gzip de su directorio
de inicio. Remplace student con su nombre de usuario.

Deliverables A title Question 1

1. El archivo zip_docs.tar en su directorio de inicio, el cual es un archivo de su directorio /usr/


share/doc/zip*.
2. El archivo /tmp/student.tgz, con student remplazado con su nombre de usuario, el cual es
un archivo comprimido con gzip de su directorio de inicio.

134
Creación de un archivo crudo en un disquete Lab Exercise Objetivo: Crear un archivo
directamente en un disquete.Tiempo estimado: 5 minutos.

Configuración

El laboratorio requiere un disquete. En el laboratorio, el contenido de un disco se sobrescribirá.

Especificaciones

1. Escriba un archivo crudo, comprimido con gzip del directorio /usr/share/doc/gzip*


directamente en un disquete. Especifique el directorio usando una referencia absoluta.
2. Extraiga el archivo del disquete a su directorio de inicio. Deje el disquete en el controlador
cuando haya terminado.

Deliverables A title Question 1

1. Un disquete que contiene un archivo crudo comprimido con gzip del directorio
/usr/share/doc/gzip*, en donde el directorio se especificó como una referencia absoluta.

En su directorio de inicio, los directorios usr/share/doc/..., los cuales fueron extraídos de su


disquete.

Possible Solution

El siguiente comando es una solución para el paso 1 del ejercicio.

[student@station student]$ tar cvzf /dev/fd0 /usr/share/doc/gzip-*

135
The Bash Shell
Introducción a Bash

Conceptos clave

• La shell por defecto en Red Hat Enterprise Linux es la shell bash.


• La shell bash se puede utilizar de modo interactivo o como un lenguaje de escritura de
gran alcance.
• Tras el arranque, bash ejecuta comandos hallados en el archivo ~/.bashrc, permitiéndole a
los usuarios personalizar su shell.
• La shell bash guarda el historial de las líneas de comando ejecutadas. La líneas de
comando se pueden recuperar desde el historial mediante varias expansiones de historial
que comienzan por "!".

Discussion

La shell bash

En Linux, la shell es el programa más utilizado. La shell es lo que usted ve cuando inicia sesión o
cuando abre una terminal y lo que más usa para iniciar cada comando. Aunque hay una variedad
de shells disponibles, todas siguen la misma conducta básica: escuchar los comandos del usuario,
iniciar procesos como se especifica en los comandos e informar los resultados al usuario. La shell
más utilizada en Linux es la shell bash, la cual es la shell por defecto en Red Hat Enterprise Linux.

La shell bash no sólo es de fácil uso para tareas sencillas, sino también tiene capacidades de gran
alcance para facilitar tareas complejas o incluso hacerlas posibles. Esta eficacia trae consigo
complejidad, solo basta con dar un vistazo a la página bash del manual (que tiene mas de 4.500
líneas) para convencerse. Este cuaderno presentará muchas de estas capacidades de gran
alcance.

Shells interactivas vs. Scripts de shell

La shell bash está diseñada para ser eficaz para dos tipos diferentes de uso. Usted ya está
familiarizado con el uso del comando bash como una shell interactiva. Muchas de estas
características de bash permiten a las personas escribir comandos de una manera más fácil y
eficaz y gran parte de este cuaderno se enfocará en estas habilidades.

La shell bash también está diseñada para ser un lenguaje de escritura de gran alcance. Los scripts
de la shell bash son programas pequeños escritos mediante la misma sintaxis que se utiliza en la
línea de comandos. Los scripts de shell permiten a los usuarios automatizar las acciones repetidas
al combinar una serie de comandos. A diferencia de las shells interactivas, los scripts de shell
suelen ejecutar una serie de comandos de modo no interactivo y muchas de estas características
de la shell bash proveen una programación lógica (tales como ramas y bucles) para escribir scripts
sofisticados. Al final de este cuaderno encontrará una introducción a la escritura de shell.

Al continuar a través de este cuaderno, trate de tener en la mente estos dos usos diferentes de la
shell bash. Algunas características de bash, tales como el historial de comandos, que pronto
veremos, son casi inútiles en los scripts de shell. Otros rasgos, tales como la sustitución aritmética,
pueden no parecer út¡les en la línea de comandos, pero pueden ser útiles en un script de shell. Si

136
la utilidad de una característica de un bash no es de inmediato obvia, trate de verla en otro
contexto.

Shells de inicio

En la práctica, los usuarios a veces necesitan iniciar una shell de modo manual. Cada vez que
alguien inicie sesión o abra una terminal, una shell se inicia automáticamente. Sin embargo, a
veces los usuarios desearían ejecutar una shell diferente u otra instancia de la misma shell. Dado
que la shell es sólo "otro programa", nuevas shells pueden iniciarse desde la shell existente. La
nueva shell se denomina subshell de la shell original. Cuando se sale de la subshell, el control
vuelve a la shell original. En el siguiente ejemplo, madonna inicia una subshell bash, lista los
procesos desde dentro de ésta para confirmar que las dos shells se están ejecutando y luego sale
de la subshell.

[madonna@station madonna]$ bash


[madonna@station madonna]$ ps
PID TTY TIME CMD
9750 pts/5 00:00:00 bash
9786 pts/5 00:00:00 bash
9814 pts/5 00:00:00 ps
[madonna@station madonna]$ exit
exit
[madonna@station madonna]$

Cuando inicia una subshell bash, las diferencias aparentes entre la subshell y la shell padre son
mínimas y se debe tener cuidado de seguir el rastro de la shell en la que se encuentra.

El archivo ~/.bashrc

Como parte de su inicialización, la shell bash buscará en el directorio de inicio del usuario un
archivo titulado .bashrc. El archivo se emplea para personalizar la shell bash. Cuando la shell
inicia, los comandos listados en el archivo se ejecutan como si fueran escritos en la línea de
comandos. Técnicamente, la shell bash "lee" el archivo. Los conceptos relacionados con la lectura
de archivos y la inicialización de shell se tratarán en detalle más adelante. Aquí, presentaremos
rápidamente este sólo archivo para poder hacer uso de él en ejercicios posteriores.

A continuación, madonna edita su archivo ~/.bashrc agregándole el comando cal, para que tras el
arranque la shell bash se presente un calendario del mes actual.

137
[madonna@station madonna]$ nano .bashrc

... (madonna appends a single line containing the command "cal") ...

[madonna@station madonna]$ cat .bashrc


# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

cal

La usuaria madonna agregó esta única línea. Las líneas restantes se encuentran en un
archivo por defecto ~/.bashrc de un usuario.

Ahora, cada vez que madonna inicia una shell bash (por ejemplo, iniciando en una consola virtual
o abriendo otra ventana de terminal), se presenta un calendario.

[madonna@station madonna]$ bash


August 2003
Su Mo Tu We Th Fr Sa
-*// 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
[madonna@station madonna]$ exit

Introducir Comandos

Las shells interactivas repiten el ciclo de escuchar una línea de comandos, evalúan el comando
solicitado, realizan todas las acciones solicitadas y muestran los resultados. La shell escucha al
teclado de entrada y emplea la tecla de ENTER para reconocer el final de la entrada como en la
siguiente ejecución del comando echo.

[madonna@station madonna]$ echo "hello world"


hello world

Historial de comandos

Como conveniencia para los usuarios de shells interactivas, el comando shell bash mantiene el
historial de cada uno de los comandos escritos por el usuario y ofrece una variedad de formas para
hacer que los comandos desde este historial estén a su alcance. La forma más fácil de ver el
historial actual es mediante el comandohistory.

138
[blondie@station blondie]$ history
1 ls -l /home/
2 ls -ln /home/
3 exit
4 exit
5 id
...
167 mv rhyme stuff/
168 ls -Rli
169 exit
170
171 exit
172 history

Como se muestra, el comando history entrega un historial de los comandos previamente escritos,
con cada entrada precedida por un "número de historial". El comando history va hasta el final de la
lista. Desde la línea de comandos, las teclas de dirección ARRIBA y ABAJO atraviesan pronto la
lista de arriba a abajo, mientras que las teclas de dirección IZQUIERDA y DERECHA moverán el
cursor para permitir al usuario editar un comando dado. Por ejemplo, si blondie quisiera luego
ejecutar el comando ls -li, podría pulsar la tecla ARRIBA 5 veces y su intérprete de comandos
llenaría con el comando ls -Rli. Podría entonces pulsar dos veces la tecla de dirección IZQUIERDA
y RETROCESO para suprimir R de la línea de comandos seguido por la tecla ENTER. Mediante
las teclas de flecha, los usuarios pueden rápidamente revisar, editar y ejecutar comandos
tecleados anteriormente.

Sustitución de historial

Como una alternativa a las teclas de dirección, la shell bash también realiza "sustitución de
historial", la cual se desencadena por el signo de exclamación. El siguiente cuadro resume la
sintaxis de sustitución de historial más utilizada.

Table 1. Sustitución de historial bash

Sintaxis Sustitución
!! Comando anterior
!n Comando número n
!-n El comando más reciente n
!cmd El comando más reciente que comienza por cmd

A manera de ejemplo de la sintaxis anterior, analice la siguiente salida (abreviada) cuando blondie
ejecuta el comando history.

139
[blondie@station blondie]$ history
...
161 ls
162 ls -il
163 ln rhyme hard_link
164 ls -il
165 chmod 660 rhyme
166 ls -il
167 mv rhyme stuff/
168 ls -Rli
169 exit
170
171 exit
172 history

El siguiente cuadro lista lo que blondie escribiría en la línea de comandos y el comando resultante
que ejecutaría.

Línea de comandos Comando resultante


!! historial
!165 chmod 660 rhyme
!-5 ls -Rli
!mv mv rhyme stuff/

Conservar el historial entre sesiones

No sólo el comando shell bash mantiene un historial de comandos dentro de una sesión, sino que
también conserva los historiales de comandos entre sesiones. Cuando la shell bash sale, entrega
el historial actual del comando dentro de un archivo llamado .bash_history en un directorio de inicio
del usuario. Tras el arranque, la shell inicializa el historial de comandos desde el contenido de este
archivo.

¿Qué repercusión tienen estas shells interactivas múltiples (pertenecientes a un mismo usuario) al
ejecutar al mismo tiempo? Puesto que el historial solo se ha guardado en el disco cuando la shell
sale, los comandos ejecutados en un proceso bash no están disponibles en el historial de
comandos de un procesobash ejecutado simultáneamente. Además, la última shell al salir
sobrescribirá las historias de las shells que salieron anteriormente.

Si está establecido así, las siguientes variables configuran los detalles de cómo se guarda el
historial de comandos.

Table 1. Variables del historial de comandos de shell bash

Variable Valor Efectos


predeterminado
HISTFILE ~/.bash_history El archivo en el cual el historial de comandos se guarda al
salir y desde el cual se inicializa al arrancar.
HISTFILESIZE 1000 El archivo HISTFILE se truncará a este tamaño en el
arranque.
HISTSIZE 1000 El número máximo de comandos que se escribrirán al salir
en el archivoHISTFILE.

140
Trucos del historial de comandos

La shell bash ofrece muy pocas técnicas para acceder previamente los comandos tecleados (o
elementos del mismo).

ESC-. y ALT-.

El último símbolo de la línea de comandos tecleados anteriormente puede recuperarse con


cualquiera de las dos secuencias de teclas mencionadas anteriormente. Una vez
aprendido, este truquito suele ser muy útil. El último simbolo de un comando suele
representar el objeto que alguien está manipulando. Por ejemplo, alguien podría hacer un
directorio y enseguida ejecutar cd en éste o editar un archivo e inmediatamente querer
utilizar chmod para cambiar sus permisos. Si la secuencia clave se repite, la shell bash
continuará el ciclo a través de los últimos símbolos de las primeras líneas de comando.

CTRL-R

Esta secuencia clave imita a !cmd en espíritu. El texto tecleado después de CTRL-R
coincide con los comandos tecleados anteriormente con la ventaja de que las líneas de
comandos coincidentes se ven de modo inmediato al teclear el texto. Usted también tiene
la oportunidad de editar la línea recuperada (utilizando las teclas de dirección IZQUIERDA
y DERECHA u otros golpes de teclado de edición de líneas de comando) antes de ejecutar
el comando.

fc

El comando fc permite a los usuarios "arreglar" el comando escrito anteriormente al abrir el


editor por defecto del usuario (por defecto vi) con el comando anterior escrito como texto.
Tras salir del edtor (presumiblemente después de editar de alguna forma el comando), el
nuevo texto se ejecutará de inmediato. Para aquellos expertos en salir del editor
rápidamente, el comando es muy útil.

Ejemplos

Uso del historial de comandos para acortar el ciclo "editar/compilar/ejecutar"

Con frecuencia, los programadores de lenguajes compilados tales como C suelen hallarse en un
ciclo repetitivo: editar un archivo, compilarlo y luego ejecutar el programa. A continuación, madonna
edita un archivo que contiene un programa pequeño C y luego lo compila con el compilador C gcc.
Después de ejecutar el programa, decide hacer algunos cambios. Hace entonces uso del historial
de comandos para agilizar el proceso.

141
[madonna@station madonna]$ nano hello.c
[madonna@station madonna]$ cat hello.c
#include "stdio.h"

int main(void)
{
printf("hello world\n");
return 0;
}
[madonna@station madonna]$ gcc -o hello hello.c
[madonna@station madonna]$ ./hello
hello world
[madonna@station madonna]$ !n
nano hello.c

(... madonna edits the file, replacing the string "hello world"
with "hello dolly" ...)

[madonna@station madonna]$ !c
cat hello.c
#include "stdio.h"

int main(void)
{
printf("hello dolly\n");
return 0;
}

[madonna@station madonna]$ !g
gcc -o hello hello.c
[madonna@station madonna]$ !.
./hello
hello dolly

Observe que la shell bash imprime el comando seleccionado desde el historial de madonna antes
de ejecutar el comando.

Uso de ESC.

Ahora madonna quisiera crear un subdirectorio bin, establece sus permisos para que sólo ella
pueda acceder a éste y mover su archivo ejecutable hello en él. Usa la secuencia de teclas ESC-.
para agilizar el proceso.

[madonna@station madonna]$ mkdir bin


[madonna@station madonna]$ chmod 700 <ESC-.>
[madonna@station madonna]$ mv hello <ESC-.>
[madonna@station madonna]$ ls <ESC-.>
hello

Quizas no es el ejemplo más interesante porque bin es un directorio muy pequeño para teclear de
todas maneras. Sin embargo, si hubiera sido el directorio /usr/lib/perl5/ven or_perl/5.8.0/HTML/, los
golpes de teclado grabados serían impresionantes.

142
Inhibición del historial de comandos

Madonna es desconfiada y preferiría que su historial de comandos fuera almacenado en el disco al


salir de la shell. Suprime su archivo del historial y crea un enlace blando con el mismo nombre que
apunta al nodo de dispositivo /dev/null.

[madonna@station madonna]$ rm .bash_history


[madonna@station madonna]$ ln -s /dev/null .bash_history
[madonna@station madonna]$ ls -l .bash_history
lrwxrwxrwx 1 madonna madonna 9 Aug 26 16:35 .bash_history -> /dev/null
[madonna@station madonna]$ cat .bash_history
[madonna@station madonna]$

Madonna ahora puede usar el historial de comandos de bash para recuperar los comandos
utilizados en la shell actual, pero ningún historial de comandos se almacenará entre las instancias
de shell.

Ejercicios en línea Lab Exercise Objetivo: Personalizar su archivo ~/.bashrc para mantener un
registro de cuándo se inician las shells.Estimated Time: 10 mins.

Especificaciones

1. Use un editor de texto para modificar el archivo .bashrc desde su directorio de inicio,
agregando la siguiente línea al final del archivo.

date >> .bash_timestamps

1. Observe el archivo .bash_timestamps, y confirme si se agrega una nueva marca de tiempo


cada vez que inicia una nueva shell bash.
2. De nuevo, mediante un editor de texto, agregue una línea de comentario a su archivo
.bashrc que describa brevemente por qué el comando de fecha fue agregado e incluya su
nombre de usuario como la persona que hizo la modificación.

Deliverables A title Question 1

En su directorio de inicio, un .bashrc modificado que agregue una marca de tiempo al


archivo .bash_timestamps cada vez que se inicie una shell bash.

El archivo .bashrc debe también contener una línea de comentario que incluya su nombre de
usuario.

143
Listas de comandos y scripts

Conceptos clave

• Comandos múltiples se pueden separar con un ;.


• Tras la salida, cada comando devuelve un entero a su padre denominado valor de retorno.
• La variable de shell $? se expande al valor de retorno de un comando ejecutado
previamente.
• && y || separan condicionalmentecomandos múltiples.

Discussion

Ejecución de comandos múltiples

La shell bash permite a los usuarios unir comandos múltiples en una sola línea de comandos
separando los comandos con un ;. (en inglés es igual; las frases independientes se separan con un
punto y coma). Veamos un ejemplo:

[elvis@station elvis]$ cd /etc/X11; ls


applnk prefdm sysconfig xorg.conf.backup xkb
desktop-menus proxymngr twm xorg.conf.wbx Xmodmap
fs rstart X xorg.conf.works Xresources
gdm serverconfig xdm XftConfig.README-OBSOLETE xserver
lbxproxy starthere xorg.conf xinit xsm
[elvis@station X11]$

El efecto es idéntico al escribir comandos en líneas separadas.

[elvis@station elvis]$ cd /etc/X11


[elvis@station X11]$ ls
applnk prefdm sysconfig xorg.conf.backup xkb
desktop-menus proxymngr twm xorg.conf.wbx Xmodmap
fs rstart X xorg.conf.works Xresources
gdm serverconfig xdm XftConfig.README-OBSOLETE xserver
lbxproxy starthere xorg.conf xinit xsm
[elvis@station X11]$

La única diferencia entre los dos enfoques es que no se tiene la oportunidad de examinar el efecto
del primer comando antes de que el segundo comando se ejecute. Muy pocas veces existe la
necesidad real de ejecutar comandos múltiples desde una solo línea de comandos, pero suele ser
conveniente combinar los comandos.

Ejecución de comandos en una subshell

La shell bash permite a los usuarios la fácil ejecución de comandos en una subshell, delimitando el
comando entre paréntesis. Considere el siguiente ejemplo:

144
[elvis@station elvis]$ (cd /etc/X11; ls)
applnk prefdm sysconfig xorg.conf.backup xkb
desktop-menus proxymngr twm xorg.conf.wbx Xmodmap
fs rstart X xorg.conf.works Xresources
gdm serverconfig xdm XftConfig.README-OBSOLETE xserver
lbxproxy starthere xorg.conf xinit xsm
[elvis@station elvis]$

A primera vista, la conducta parece idéntica a la del ejemplo anterior. Una mirada más de cerca
revela una diferencia sutil pero importante. En el primer ejemplo, cuando los comandos se separan
apenas por un punto y coma, los comandos se ejecutan en la shell actual. El intérprete de
comandos de bash revela que, después de ejecutados los comandos, la shell del directorio de
trabajo actual ha cambiado a /etc/X11 como resultado del comando cd.

En el ejemplo anterior, al delimitar los comandos entre paréntesis, el directorio de shell actual no
cambia. Cuando bash encuentra un paréntesis en la línea de comandos, éste genera un nuevo
proceso hijobash (llamado subshell) y ejecuta los comandos dentro de la subshell. Después de
ejecutarlos, la subshell sale y el usuario queda en la shell original (shell sin cambios). El efecto es
parecido a la siguiente secuencia de comandos.

[elvis@station elvis]$ bash


[elvis@station elvis]$ cd /etc/X11; ls
applnk prefdm sysconfig xorg.conf.backup xkb
desktop-menus proxymngr twm xorg.conf.wbx Xmodmap
fs rstart X xorg.conf.works Xresources
gdm serverconfig xdm XftConfig.README-OBSOLETE xserver
lbxproxy starthere xorg.conf xinit xsm
[elvis@station X11]$ exit
exit
[elvis@station elvis]$

La subshell se inicia manualmente al ejecutar el comando bash.

Los comandos se ejecutan ahora en la subshell.

Al terminar, se sale de la subshell.

Ahora que elvis está de nuevo en su shell original, las modificaciones en la subshell (tales
como el cambio en el directorio de trabajo actual) han quedado atrás.

¿Por qué podría alguien desear ejecutar un comando en una subshell? Las subshells se utilizan
para evitar efectos secundarios. Lo que suceda en la subshell no debería tener efecto en el entorno
original de la shell (como en inglés, lo que está entre paréntesis no debe cambiar la frase que lo
rodea).

Introducción a los scripts de shell

La clave para usar Red Hat Enterprise Linux de modo efectivo es la automatización. Un buen
administrador de Linux debe ser en realidad extremadamente perezoso cuando se trata de hacer
algo aburridor o repetitivo. Las secciones anteriores ilustraron la manera de encadenar comandos
para ejecutar de modo consecutivo o simultáneo en lugar de esperar a que el comando termine

145
antes de teclear el próximo. También le introdujeron a las características del historial de bash y le
mostraron cómo referirse a comandos tecleados previamente para que sólo tenga que escribirlos
una vez.

Sin embargo, aún falta una parte importante de la caja de herramientas del administrador del
sistema: la escritura de scripts. Un script, en su forma más simple, es un texto con una lista de
comandos en él. Los comandos se envían a través de un programa específico llamado intérprete,
el cual ejecuta un comando a la vez. Este intérprete suele ser la shell bash (conocida como
/bin/bash o /bin/sh) y cada comando es un comando común de Linux. Otros intérpretes permiten
utilizar lenguajes de programación de gran alcance como Perl, Python y Ruby.

Antes de comenzar a escribir sus propios scripts hay algunas cosas importantes que recordar:

• La primera línea de su script debe especificar a qué intérprete enviar las instrucciones.
Esto se hace con una cadena especial llamada "shebang" (pronunciada "shuh-bang"), la
cual se ve así: #!. A la shebang le sigue un nombre de un intérprete para este script. Así,
por ejemplo, para usar bash como su intérprete usted debería usar #!/bin/sh o
#!/bin/bash. La mayoría de los scripts sólo usan #!/bin/sh. Al referirse al intérprete como
#!/bin/bash se habilitan otras características, pero se limita la compatibilidad del script con
los sistemas antiguos de Unix y rara vez es necesario.
• Antes de ejecutar un script, usted debe habilitar el permiso "ejecutable" en él (de lo
contrario, es sólo un archivo de texto). El comando para esto es chmod u+x
<scriptname>. Le otorga (y sólo a usted) permiso para ejecutar este script justo como
usted haría con otro comando. El comando chmod se tratará en detalle más adelante en
esta clase.
• Si creó un script llamado foo.sh en su directorio de inicio y justo después tecleó foo.sh
obtendría el mensaje de error "no existe tal directorio o archivo". Esto se debe a que
cuando teclea un comando hay una serie de directorios en donde Linux busca ese
comando. Estos directorios se conocen colectivamente como su RUTA y, por razones de
seguridad, su RUTA nunca incluye el directorio actual. Para resolver este problema tiene
dos alternativas:
1. Usted puede especificar de modo explícito la ubicación del script al teclear
~/foo.sh o ./foo.sh ("." siempre se refiere al directorio actual).
2. Puede colocar el script en un directorio que sea parte de su RUTA. Los usuarios
que no son root no tienen permiso para colocar archivos en la mayoría de estos
directorios, pero todos los usuarios tienen un bin personal, al cual pueden escribir
en su directorio de inicio. Por lo tanto, si foo.sh fuera movido a ~/bin se podría
ejecutar al teclear simplemente foo.sh en la línea de comandos. Esta es la técnica
preferida.

aprenderá más acerca de la RUTA en capítulos siguientes.

Veamos un simple ejemplo. Suponga que usted es un administrador que necesita ver con
frecuencia qué usuarios han iniciado sesión en el sistema. Esta información puede obtenerse al
ejecutar el comando w (sí, eso es todo) pero mientras esto proporciona un buen resumen de quién
ha iniciado sesión, no imprime la hora en la que se tomó esta instantánea de la actividad del
usuario. Otro comando, llamado date imprime la fecha y hora actual, pero no la información del
usuario. Si solo usted pudiera combinar esos dos comandos...

Suponga que creó un script llamado wdate.sh en su directorio personal bin:

146
[student@station ~]$ cat ~/bin/wdate.sh
#!/bin/sh
date
w
[student@station ~]$ chmod u+x ~/bin/wdate.sh
[student@station ~]$ wdate.sh
Thu Jul 14 12:13:54 PDT 2005
12:13:54 up 2 days, 12:50, 8 users, load average: 0.35, 0.27, 0.18
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
student_a tty1 - Mon23 ?xdm? 2:43m 3.06s /bin/bash
student tty2 :0.0 Tue17 0.00s 2.19s 0.00s /bin/sh /
home/student/bin/wdate.sh
[student@station ~]$

Observe que el script había sido colocado en ~/bin y era ejecutable antes de ejecutarse como un
comando normal. Al ejecutar date seguido por w, ¡nos da dos comandos por el precio de uno!
Obviamente, este script podría luego modificarse para ejecutar un número arbitrario de comandos
seguidos. De hecho, los scripts pueden ser mucho más eficaces que apenas una lista de
comandos y pueden ser programas complejos en su propio derecho. El material complementario
de esta lección describe técnicas avanzadas para scripts y pueden habilitarse a discreción de su
instructor. Por ahora, concéntrese en dominar los scripts básicos como una valiosa técnica de
almacenamiento. La regla de oro del administrador es que si usted tiene que hacer una tarea más
de dos veces,¡haga un script!

Valores de retorno

Cada proceso en Linux tiene un ciclo de vida. Todos los procesos comienzan a solicitud de otro
proceso (a menudo shell). El proceso solicitado se denomina padre, y el proceso recién nacido el
hijo. El proceso hijo suele realizar sus deberes (incluyendo generar sus propios hijos), y luego elige
morir. Un proceso de salida deja atrás una pequeña parte de información cuando muere, llamado el
valor de retorno del proceso o estatus de salida. El proceso padre es responsable de reunir los
valores de retorno de los hijos muertos.

Los valores de retorno vienen en forma de enteros los cuales van de 0 a 255. Los programas
pueden escoger líbremente el valor al salir [1]. A menudo, lo que significan las implicaciones por
valores de retorno son parte de una interfaz de un programa bien definido y están documentadas
en la página man del programa, (si no está familiarizado con el comandodiff, la sección de
"DIAGNÓSTICO" de su página del manual ofrece un ejemplo). Una convención de Linux (y Unix)
es que un programa devuelve en 0 para implicar "éxito" en lo que estaba intentando hacer, y un
valor de retorno de no cero que implica algun tipo de error.

La shell bash almacena el valor de retorno del comando ejecutado anteriormente en una variable
especial llamada ?. Infortunadamente, no hemos descrito aún todas las variables de shell (eso
sigue luego), pero observemos que el valor de esta variable (por ejemplo, el valor de retorno del
programa ejecutado antes), puede examinarse con el comando echo $?.

En el siguiente ejemplo, el comando ls se utiliza para examinar los permisos del archivo
/etc/passwd. Dado que el comando "funciona", el comando ls devuelve un valor de retorno de 0.

En contraste, los siguientes


[elvis@station elvis]$ejemplos
ls -l muestran cómo responde el comando ls al listar un archivo
/etc/passwd
-rw-r--r-- 1 root root 3694 Aug 15 16:26 /etc/passwd
[elvis@station elvis]$ echo $?
0

147
[elvis@station elvis]$ ls -l /etc/password
ls: /etc/password: No such file or directory
[elvis@station elvis]$ echo $?
1

Dado que el comando "no funcionó", devolvió un valor de retorno de 1. Devolver un 0 de éxito y un
1 cuando se presenta cualquier tipo de error, es una conducta normal. Si una página man del
programa no menciona otra cosa, generalmente se puede asumir esta conducta.

Ejecución de comandos múltiples de modo condicional

La shell bash usa &&y || para unir dos comandos de modo condicional. Cuando los comandos se
unen de este modo, el primero siempre se ejecutará. El segundo comando puede que se ejecute o
no dependiendo del valor de retorno del primer comando. Por ejemplo, un usuario puede desear
crear un directorio y luego mover un nuevo archivo dentro de ese directorio. Si la creación del
directorio fracasa, entónces no hay razón para mover el archivo. Los dos comandos pueden
acoplarse de la siguiente forma.

[elvis@station elvis]$ echo "one two three" > numbers.txt


[elvis@station elvis]$ mkdir /tmp/boring && mv numbers.txt /tmp/boring
[elvis@station elvis]$ ls

Al acoplar los dos comandos con &&, el segundo comando sólo ejecutará el primer comando que
tuvo éxito (por ejemplo, tuvo un valor de retorno de 0). Esto es similar a la operación "and" que se
encuentra en varios lenguajes de programación. En el ejemplo anterior, el comando mkdir tuvo
éxito y luego el archivo se movió. ¿Qué sucedería si el comando mkdir fracasara?

[elvis@station elvis]$ echo "one two three five seven eleven" >
primes.txt
[elvis@station elvis]$ mkdir /tmp/mostly/boring && mv primes.txt
/tmp/mostly/boring
mkdir: cannot create directory `/tmp/mostly/boring': No such file or
directory
[elvis@station elvis]$ ls
primes.txt

Dado que el comando mkdir fracasó (el directorio /tmp/mostly no existá, por lo tanto el directorio
/tmp/mostly/boring no se pudo crear), bash no trató de ejecutar el comando mv.

Igualmente, los comandos múltiples pueden combinarse con ||. En este caso, bash ejecutará el
segundo comando sólo si el primer comando "fracasa"(tiene un valor de retorno diferente a cero).
Esto es igual al operador "or" que se encuentra en lenguajes de programación. En el siguiente
ejemplo, elvis intenta cambiar los permisos en un archivo. Si el comando fracasa, un mensaje para
ese efecto se imprime en la pantalla.

148
[elvis@station elvis]$ chmod 600 /tmp/boring/numbers.txt || echo "chmod failed."
[elvis@station elvis]$ chmod 600 /tmp/mostly/boring/primes.txt || echo "chmod failed"
chmod: failed to get attributes of `/tmp/mostly/boring/primes.txt': No such file or
directory
chmod failed

En el primer caso, el comando chmod tuvo éxito, y no se imprimió ningún mensaje. En el segundo
caso, el comando chmod fracasó (porque el archivo no existía) y apareció el mensaje "chmod
failed" (aparte del mensaje de error estándar de chmod).

Ejemplos

Echoing $? twice

El usuario elvis acaba de aprender sobre los valores de retorno, y está examinando los valores de
retorno de varios comandos. Después de ejecutar (sin éxito) el comando ls, encuentra que, como
era de esperar, la variable de bash ? contiene 1. Al examinar la variable otra vez, se da cuenta que
ahora contiene un 0. ¿Qué hizo cambiar el valor?

[elvis@station elvis]$ ls -l /etc/password


ls: /etc/password: No such file or directory
[elvis@station elvis]$ echo $?
1
[elvis@station elvis]$ echo $?
0

Recuerde que la variable de bash ? contiene el valor de retorno de los comandos ejecutados más
recientemente. En el primer caso, éste contenía el valor de retorno (sin éxito) del comando ls. En el
segundo caso, éste contenía el valor de retorno del comando echo (con éxito).

Visualización de recordatorios

El usuario ahora quiere desarrollar un esquema en donde pueda dejar recordatorios y que
automáticamente aparezcan al iniciar una shell. Crea un archivo en el directorio de inicio llamado
reminders con el texto brush your teeth y agrega la siguiente línea a su archivo ~/.bashrc.

cat /home/elvis/reminders

Luego prueba su configuración de modo manual iniciando una nueva shell bash.

149
[elvis@station elvis]$ echo "brush your teeth" > reminders
[elvis@station elvis]$ nano .bashrc
[elvis@station elvis]$ cat .bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

cat reminders
[elvis@station elvis]$ bash
brush your teeth
[elvis@station elvis]$ exit
exit
[elvis@station elvis]$

Todo parece funcionar bien, hasta que elvis sigue su consejo de limpieza y borra su archivo
reminders. La próxima vez que inicia una shell se encuentra con lo siguiente:

[elvis@station elvis]$ bash


cat: reminders: No such file or directory
[elvis@station elvis]$

Dándose cuenta que le gustaría ejecutar el comando cat sólo si el archivo reminders existe, edita
la línea que agregó a su archivo .bashrc con lo siguiente:

ls reminders > /dev/null && cat reminders

Ahora el comando cat sólo se ejecutará si el comando ls tiene éxito, porque el archivo reminders
existe, (¿hay una mejor forma de hacer esto? Sí, pero aún no hemos aprendido lo suficiente para
hacerlo.)

Ejercicios en línea Lab Exercise Objetivo: Ejecutar comandos dentro de una subshell.Estimated
Time: 10 mins.

Especificaciones

1. Agregue una sola línea al final del archivo .bashrc en su directorio de inicio. La línea debe
ejecutar los comandos cd /usr y ls en una sola subshell , (al ejecutarla, el directorio de
trabajo actual de su shell no se afectará.)

Si se implementa correctamente, al iniciar una nueva shell debería ver una salida similar a la
siguiente:

150
[elvis@station elvis]$ bash
bin etc include lib local share tmp
dict games kerberos libexec sbin src X11R6
[elvis@station elvis]$

Deliverables A title Question 1

1. Un archivo ~/.bashrc cuya última línea ejecute los comandos cd /usr y ls en una sola
subshell.

Limpieza

Una vez obtenga la calificación, restaure su archivo ~/.bashrc al estado original.

151
Variable de bash

Conceptos clave

• Las variables de la shell se asignan mediante una sintaxis A=apple.


• Las variables se examinan ("desreferencian") con el caracter $ como en echo $A.
• En el nivel de kernel, cada proceso tiene una colección de variables de entorno que los
procesos hijos heredan.
• El comando export convierte una variable de shell en una variable de entorno.
• Los comandos set y env listan las variables de shell y las variables de entorno,
respectivamente.

Discussion

Conceptos básicos de la variable de shell

La shell bash le permite a los usuarios establecer y hacer referencia a las variables de shell. Una
variable de shell es simplemente un valor con nombre que la shell recuerda. Las variables de shell
se pueden utilizar en comandos y scripts de shell y pueden también referenciarse en programas
como opciones de configuración. Por ejemplo, el cliente de correo electrónico mutt ejecuta un
editor externo al escribir un mensaje. Por defecto este editor esvi. Sin embargo, antes de ejecutar
vi comprobará si una variable llamadaEDITOR se ha establecido. Si se ha establecido, entonces el
comando definido por EDITOR se utiliza en lugar de vi. La mayoría de los programas que lanzan
editores externos funcionan del mismo modo.

Hay dos tipos de variables de shell: variables locales y variables de entorno. Una variable local
existe solo dentro de la shell en la cual se crea. Las shells hijas heredan las variables de entorno
como cuando se lanza una terminal después de iniciar sesión. Primero, veremos cómo definir una
variable local, luego hablaremos acerca de cómo definir variables de entorno incluyendo la bash
misma.

El configurar las variables locales es bastante sencillo. En el siguiente ejemplo, prince establecerá
la variable A con el valor apple.

[prince@station prince]$ A=apple

Si usted sigue, asegúrese de no dejar ningún espacio a los lados del signo =. Ahora la shell se
"cuelga"a esta asociación por todo el tiempo que exista la shell (o hasta que se anule
explícitamente, ver a continuación). Cada vez que prince quiera usar el valor "apple", puede usar la
variable A en su lugar, iniciando la variable con el signo ($), como en el comando echo mostrado
abajo. Esto se llamadesreferenciar la variable A.

[prince@station prince]$ echo $A


apple

La variable se puede utilizar en cualquier parte de la línea de comandos (o en los scripts de shell).
¿Qué sucede si prince, en lenguaje colorido, decidiera escribir unas cuantas líneas acerca de las

152
manzanas (o apples en inglés) y las almacenara en un archivo llamado ode_to_apple.txt. La
siguiente línea podría ayudarlo a empezar:

[prince@station prince]$ echo "Oh, I like them squishy" >> ode_to_$A.txt


[prince@station prince]$ ls
ode_to_apple.txt

Cuando la shell bash examinó la línea de comandos, remplazó $A por apple. Estos son los
conceptos básicos de las variables de shell. Las variables se establecen y se configuran con una
sintaxis VAR=valor y se desreferencian con una sintaxis $VAR.

Detalles de la variable de shell

¿Qué puede utilizarse como nombres de variables? Los nombres de variables pueden ser
cualquier cadena de caracteres alfanuméricos (A-Z, a-z, 0-9), y el guión bajo (_), pero no pueden
comenzar por un número. Las variables de shell distinguen mayúsculas de minúsculas, como se
muestra a continuación.

[prince@station prince]$ B=banana


[prince@station prince]$ echo $B is my favorite fruit
banana is my favorite fruit
[prince@station prince]$ echo $b is my favorite fruit
is my favorite fruit

En el primera impresión en pantalla, $B fue remplazado por el valor banana. ¿Cómo fue
desreferenciado $b? Si se le pide a la shell desreferenciar una variable no establecida, ésta
remplaza la referencia de la variable con una cadena vacía (en otras palabras, con nada). Dado
que b se considera como una variable diferente a B, y que la variable b nunca ha sido asignada, la
shell remplaza la referencia $b con nada. Por protocolo, las variables suelen definirse con
mayúsculas, pero esto no es más que protocolo.

¿Cuál puede ser el valor de la variable? Cualquier cosa. El truco se presenta en la asignación.
Cuando se asignan las variables, la sintaxis es nombre=valor, sin dejar espacios. ¿Qué sucedería
si prince quisiera que la variable FRUIT apuntara a la frase mushy bananas?

[prince@station prince]$ FRUIT=mushy bananas


-bash: bananas: command not found

Nos hemos tropezado con una sintaxis avanzada para configurar las variables, es decir
nombre=valor comando, el cual establece la variable name sólo para la ejecución del comando
especificado. La shellbash obedientemente estableció la variable FRUIT en el valor mushy y fue a
ejecutar el comando bananas, con resultados esperables. Pero esto no es lo importante, lo
importante es que si quiere establecer una variable a un valor que contenga espacios, debe incluir
el valor entre comillas.

153
[prince@station prince]$ FRUIT="mushy bananas"
[prince@station prince]$ echo $FRUIT is my favorite fruit
mushy bananas is my favorite fruit

Con esta modificación, prince obtiene la conducta correcta desde la shell bash, si no la gramática
inglesa correcta.

Cuando se desreferencian las variables, el nombre de la variable puede marcarse con corchetes {},
si es necesario. Por ejemplo, ¿qué sucedería si arriba, prince hubiera querido guardar su poema
dentro de un archivo llamado apple_ode.txt? El ensaya el primer método obvio, en el mismo
directorio como se muestra arriba.

[prince@station prince]$ echo $A


apple
[prince@station prince]$ echo "Oh, I like them squishy" > $A_ode.txt
[prince@station prince]$ ls
ode_to_apple.txt

¿Dónde está el archivo apple_ode.txt? Un par de cosas han conspirado contra prince. Primero, la
shell bash desreferenció el nombre correcto de variable, pero no el que prince quería. ¿De qué
puede estar compuesta una variable? De caracteres alfanuméricos y minúsculas. La shell bash
apuntó a la variable (sin inicializar) A_ode (a nada) y creó el archivo resultante .txt. En segundo
lugar, debido a que .txt comienza por un ., es un "archivo oculto", así como ls -a lo revela.

[prince@station prince]$ ls -a
. .bash_profile .gtkrc .plan
.. .bashrc .kde .txt
.bash_history .gnome-desktop ode_to_apple.txt .viminfo
.bash_logout .gnupg .pgpkey .xauthizv2EF
[prince@station prince]$ cat .txt
Oh, I like them squishy

El usuario prince puede salir de esta situación utilizando corchetes para delimitar el nombre
deseado de la variable.

[prince@station prince]$ echo "Oh, I like them squishy" > ${A}_ode.txt


[prince@station prince]$ ls
apple_ode.txt ode_to_apple.txt

Utilizar corchetes para delinear nombres de variable siempre es correcto y en algunos casos, es
necesario.

Al terminar con una variable, la variable se puede desligar de su valor con el comando unset.

[prince@station prince]$ unset A


[prince@station prince]$ echo $A

[prince@station prince]$

154
Variables de Bash

El siguiente cuadro lista algunas variables que se establecen automáticamente con la shell bash.
Estas variables son de sólo lectura y no pueden ser configuradas por el usuario.

Table 1. Variables Bash de sólo lectura

Variable Se expande hasta


? El estatus de salida del comando ejecutado más recientemente
- Opciones de banderas de la shell actualmente activadas
$ Id (pid) del proceso de la shell actual
! Id (pid) del proceso del comando secundario más reciente
_ Último símbolo del comando anterior
PPID Id (pid) del proceso padre de la shell.
SHELLOPTS Lista separada por comas de las opciones de shell actual como lo informó el
comando set -o.
UID El userid del usuario actual

Estas variables son establecidas por la shell para proveer información. Estas no se pueden
reasignar por el usuario, así como prince lo descubre a continuación.

[prince@station prince]$ echo $SHELLOPTS


braceexpand:emacs:hashall:histexpand:history:interactive-
comments:monitor
[prince@station prince]$ SHELLOPTS=foo
-bash: SHELLOPTS: readonly variable

Las siguientes variables son inicializadas por la shell bash, pero pueden ser reasignadas.

Table 2. Variables Bash preasignadas

Variable Se expande hasta


BASH_VERSION La versión actual bash
HOSTNAME El nombre del host DNS de la máquina actual
OLDPWD El directorio de trabajo anterior
PWD The current working directory
RANDOM Un número aleatorio entre 0 y 32767
SECONDS El número de segundos desde que la shell se inició

Variables de entorno

El configurar y resolver variables debería ser bastante sencillo, (siempre y cuando se acuerde de
los espacios). Ahora presentaremos un concepto un poco más sutil y mucho más útil: variables de
entorno.

Así como la shell bash permite asignar parejas de valores-nombre llamados variables de shell, el
kernel de Linux permite a cualquier proceso definir las parejas nombre-valor llamadas variables de
entorno. Estas variables son una parte del proceso almacenado en el kernel, simplemente como el
id del proceso, el id del usuario y el directorio actual de trabajo son parte del proceso. Lo más
importante es que cada vez que se inicie un proceso (tal como la shell bash iniciando el comando
ls), las variables de entorno son heredadas por el proceso hijo. Esto le permite a los usuarios

155
utilizar la shell bash para crear o modificar una variable de entorno y luego todos los comandos
iniciados por la shell heredarán esa variable.

¿Cómo creamos variables de entorno dentro de la shell bash? Primero, una variable de shell se
crea y luego la variable de shell es "promovida" a una variable de entorno mediante el comando
export, (la variable será luego exportada a cualquier proceso hijo futuro). Considere el siguiente
ejemplo:

[prince@station prince]$ A=apple


[prince@station prince]$ B=banana
[prince@station prince]$ echo a:$A b:$B
a:apple b:banana
[prince@station prince]$ export A
[prince@station prince]$ bash
[prince@station prince]$ ps
PID TTY TIME CMD
2251 pts/5 00:00:00 bash
2316 pts/5 00:00:00 bash
2342 pts/5 00:00:00 ps
[prince@station prince]$ echo a:$A b:$B
a:apple b:
[prince@station prince]$ exit
exit
[prince@station prince]$ echo a:$A b:$B
a:apple b:banana
[prince@station prince]$ unset A B

El usuario prince ha creado dos variables de shell, A y B.


La variable A se promueve a una variable de entorno con el comando export.
El usuario prince inicia una subshell bash.
Al ejecutar el comando ps, prince confirma que hay otras shells ejecutándose: el padre y el
hijo (su shell actual).
Dado que la variable A pasa a ser una variable de entorno, ésta fue heredada por la shell hija
del padre. Por el contrario, la shell hija no sabe nada de la variable de shell padreB.
Cuando prince sale de la shell hija, vuelve a la shell padre, donde la variable B está aún
definida.
Por último, prince desenlaza tanto la variable de entornoA como la shell de entorno B con el
mismo comando unset.

Las variables de entorno suelen utilizarse para configurar comandos con información acerca de
configuraciones locales o en otras palabras, la información acerca del entorno local. A manera de
ejemplo, muchos comandos buscarán una variable de entorno llamada LANG para determinar el
lenguaje del usuario y modificar su salida como corresponde.

156
[prince@station prince]$ echo $LANG
en_US.UTF-8
[prince@station prince]$ date
Fri Aug 1 11:54:24 EDT 2002
[prince@station prince]$ LANG=de_DE
[prince@station prince]$ date
Fre Aug 1 11:54:53 EDT 2002
[prince@station prince]$ LANG=es_ES
[prince@station prince]$ date
vie ago 1 11:55:09 EDT 2002

Al establecer la variable de entorno LANG para de_DE, la abreviatura habitual para el día "viernes"
en alemán entonces se convierte en la abreviación alemana por regla. Al establecer LANG como
es_ES, los efectos son incluso más obvios, puesto que las abreviaturas de los días y meses han
cambiado al español (como también las convenciones de las mayúsculas).

Un punto importante que merece reformularse. El comando date no cambió la conducta porque el
comando bash tenía una variable de entorno denominada LANG (directamente). El proceso al
ejecutar el comando date modificó su salida porque tenía su propia variable de entorno llamada
LANG. Esto simplemente sucedió para heredar esta variable de la shell bash. Todos los procesos
tienen variables de entorno, no sólo shells.

¿Por qué prince no tuvo que exportar explícitamente la variable LANG? La variable ya es una
variable de entorno configurada por los scripts de arranque. Una vez que una variable es una
variable de entorno, se puede modificar ( y suprimir) mediante la misma sintaxis de las variables de
shell.

A menudo, los usuarios utilizan una sintaxis más corta para crear y exportar una variable de
entorno:

[prince@station prince]$ export EDITOR=nano

Con este sólo comando, prince ha creado, asignado y exportado la variable EDITOR.

Listado de variables

Examinar variables con set y env

La shell bash provee dos comandos para listar variables definidas. El comando set, sin
argumentos, lista las variables de shell y las variables de entorno asociadas con la shell, mientras
que el comando env, otra vez sin argumentos, lista sólo variables que han sido exportadas al
entorno.

157
[prince@station prince]$ set
BASH=/bin/bash
BASH_VERSINFO=([0]="2" [1]="05b" [2]="0" [3]="1" [4]="release"
[5]="i386-redhat-
linux-gnu")
BASH_VERSION='2.05b.0(1)-release'
COLORS=/etc/DIR_COLORS.xterm
COLUMNS=80
...
[prince@station prince]$ env
HOSTNAME=localhost
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
USER=prince
MAIL=/var/spool/mail/prince
...

Variables de entorno más utilizadas

El siguiente cuadro lista algunas variables de entorno que con frecuencia se utilizan para
personalizar un entorno de usuario.

Table 1. Variables de entorno más utilizadas

Variable Uso
TERM Especifica la configuración de bajo nivel de la terminal del usuario. La variable es más
relevante al utilizar una consola de línea serial ("terminal tonta") para acceder al
sistema.
PATH Especifica los directorios para buscar archivos ejecutables en ellos.
DISPLAY Especifica qué clientes del servidor X deberían usar el entorno gráfico.
LANG Especifica el lenguaje preferido para los programas internacionalizados.
EDITOR Muchos programas dependen de un editor externo para la entrada de parte del
usuario. A menudo, el editor por defecto es vi. Si la variable de entorno EDITOR está
establecida, el editor especificado se utilizará en su lugar.
PRINTER La mayoría de los comandos que envían o administran trabajos de impresión
examinarán esta variable de entorno para determinar la impresora predeterminada.

Ejemplos

Uso de variables para hacer referencia a las palabras más utilizadas

El usuario prince desea mantener al día los aspectos relacionandos con el software de Open
Source y suele utilizar los enlaces de texto del navegador web links para visitar
http://www.redhat.com/opensourcenow/key_issues.html. En lugar de teclear de modo repetitivo la
URL, prince modifica su archivo ~/.bashrc, para que la URL sea almacenada en la variable
OSNISSUES. Ahora prince puede referirse a la página web de un modo más fácil.

158
[prince@station prince]$ vim .bashrc
[prince@station prince]$ cat .bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

OSNISSUES=http://www.redhat.com/opensourcenow/key_issues.html
[prince@station prince]$ bash
[prince@station prince]$ links $OSNISSUES

Mediante http_proxy para definir un servidor Proxy HTTP

Dado que prince está utilizando un computador sin conexión directa al internet, debe configurar su
navegador de red para usar el servidor proxy encontrado en la dirección IP 10.1.1.1 y en el puerto
8080. Mientras trata de entender cómo establecer un servidor proxy para el navegador de texto
links, se encuentra con lo siguiente en la página de manual links(1).

PROTOCOL_proxy Links supports the use of proxy servers that can act
as firewall gateways and caching servers. They are
preferable to the older gateway servers (see
WWW_access_GATEWAY, below). Each protocol used by
Links, (http, ftp, gopher, etc), can be mapped sepa-
rately by setting environment variables of the form
PROTOCOL_proxy (literally: HTTP_proxy, FTP_proxy,
HTTPS_proxy, etc), to "http://some.server.dom:port/".

Con el fin de establecer el servidor proxy, agrega la siguiente línea a su archivo ~/.bashrc.

HTTP_proxy=http://10.1.1.1:80

Prince inicia una nueva shell (para que el archivo .bashrc sea leído) y trata de tener acceso a la
página web de Open Source.

[prince@station prince]$ links


http://www.redhat.com/opensourcenow/key_issues.html
Looking up www.redhat.com
www.redhat.com
Unable to locate remote host www.redhat.com
Alert!: Unable to connect to remote host.

links: Can't access startfile


http://www.redhat.com/opensourcenow/key_issues.html

159
El navegador de enlaces aparentemente no está tratando de usar el servidor proxy. Cuando prince
revisa sus pasos, se da cuenta que aunque configuró la variable http_proxy, olvidó exportar la
variable. Dado que la variable es una variable de shell establecida y no una variable de entorno, no
es heredada por el proceso links. Prince edita la línea que agregó a su archivo .bashrc,
agregándole la palabra exportar:

[prince@station prince]$ cat .bashrc


# .bashrc

# User specific aliases and functions

# Source global definitions


if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

export HTTP_proxy=http://10.1.1.1:80

De nuevo inicia una nueva shell (para que lea el archivo .bashrc otra vez) y ensaya una vez más.

[prince@station prince]$ links


http://www.redhat.com/opensourcenow/key_issues.html

Dado que la variable http_proxy ahora es exportada como una variable de entorno, es heredada
por el proceso links, y links usa con éxito el servidor de proxy para contactar el sitio. Puesto que
prince incluyó la línea en su archivo ~/.bashrc, la variable de entorno se configurará
automáticamente cada vez que inicie una nueva shell, y prince no necesita preocuparse por esto.

Agregar un directorio a su PATH

Cuando la shell bash examina una línea de comandos, asume que la primera palabra es el nombre
del programa que se va a ejecutar. Luego debe ubicar el archivo que contiene el programa en el
sistema de archivos. Dado que la búsqueda de un archivo ejecutable, por ejemplo, ls en todo un
sistema de archivos, tardaría mucho, la shell busca en la variable de entorno PATH para obtener
instrucciones.

La variable de entorno PATH contiene una lista de directorios en los cuales deberían buscar los
archivos ejecutables, separados por una coma:

[prince@station prince]$ echo $PATH


/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/home/prince/bin

Considere ejecutar el comando xclock, el cual comienza por un reloj en el entorno gráfico X. Por
medio de la variable PATH, bash primero busca el archivo /bin/xclock, y al no encontrarlo, busca
entonces /usr/bin/xclock. El proceso continua hasta encontrar el archivo ejecutable
/usr/bin/X11/xclock.

160
No todos los archivos ejecutables en el sistema residen en directorios que están en la lista por su
variable de entorno PATH. Se dice que algunos programas viven "fuera de su ruta". Sin embargo,
el hecho que un programa viva fuera de su ruta, no significa que no pueda ejecutarse. Significa que
usted debe especificar el comando mediante una referencia absoluta.

A manera de ejemplo, el comando lsof lista los archivos actualmente abiertos en el sistema, (el
nombre se deriva del inglés LiSt Open Files.) Dado que este comando lo suelen utilizar
administradores de sistemas, y no usuarios "normales", el comando vive en el directorio /usr/sbin,
el cual se adhiere "fuera del" PATH por defecto en Red Hat Enterprise Linux. El usuario prince
desearía usar el comando para listar todos los archivos actualmente abiertos que el proceso init
está utilizando.

[prince@station prince]$ ls -l /usr/sbin/lsof


-rwxr-xr-x 1 root root 95640 Jan 24 2003 /usr/sbin/lsof
[prince@station prince]$ lsof -c init
-bash: lsof: command not found

Al examinar su PATH, el directorio /usr/sbin no está listado, así que prince trata de ejecutar el
comando como una referencia absoluta.

[prince@station prince]$ /usr/sbin/lsof -c init


COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
init 1 root mem REG 3,3 27036 245377 /sbin/init
init 1 root mem REG 3,3 104560 244833 /lib/ld-2.3.2.so
init 1 root mem REG 3,3 1536292 476416 /lib/tls/libc-2.3.2.so

Dado que él preferiría poder ejecutar el comando directamente, prince desearía agregar el
directorio /usr/sbin a su ruta. Utiliza un truco estándar de Linux (y Unix) para agregar el directorio a
su ruta.

[prince@station prince]$ PATH=$PATH:/usr/sbin

El comando puede ser pensado como si se dijera "establezca la variable PATH"sea cualquiera que
sea actualmente, pero luego agregue :/usr/sbin. Tras examinarlo, la variable PATH ha agregado el
directorio /usr/sbin y prince ahora puede listar los archivos fácilmente.

[prince@station prince]$ echo $PATH


/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/home/prince/bin:/usr/sbin
[prince@station prince]$ lsof -c init
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
init 1 root mem REG 3,3 27036 245377 /sbin/init
init 1 root mem REG 3,3 104560 244833 /lib/ld-2.3.2.so
init 1 root mem REG 3,3 1536292 476416 /lib/tls/libc-2.3.2.so

161
Expansión de la línea de comandos

Conceptos clave

• La shell bash expande ciertos metacaracteres de línea de comandos antes de interpretar


el comando.
• La expansión con la tilde amplía los símbolos que comienzan por una tilde (~) a los
directorios de inicio de usuarios.
• La expansión de llaves amplía los símbolos con corchetes ({}) en palabras múltiples, cada
una contiene una sola palabra a partir de la lista especificada.
• La sustitución de comandos expande el texto delimitado por comillas invertidas (``) o "dólar
paréntesis" ($()) en la salida producida por el comando encerrado.
• Las comillas dobles ("..." ), las comillas sencillas ('...') y el caracter de barra invertida
pueden usarse para evitar que la shell expanda los caracteres.

Discussion

Expansiones de línea de comandos

Generalidades

Antes de ejecutar un comando, la shell bash ejecuta varias expansiones en la línea de comandos.
Varios tipos de expansiones de bash, tales como la expansón del nombre de ruta (comodín) y la
expansión de variables ya se han descrito. El siguiente cuadro lista los tipos de expansiones bash
con una descripción de cada una a continuación.

Table 1. Expansiones de línea de comandos en la shell bash

Expansión Sintaxis Se expande hasta


Historial ! Una línea de comandos anterior
Llaves {} Texto especificado
Tilde ~username Directorio de inicio de un usuario
Variable $, ${...} Shell y variables de entorno
Aritmética $((...)) Cálculo numérico
Sustitución de `...`, $(...) Salida de la ejecución del comando en una subshell
comandos
Nombre de ruta *, ?, [...], Nombres de archivos coincidentes en el sistema de
[^...] archivos

Expansión del historial

La expansión del historial, la cual se invoca con un signo de exclamación, se describió de modo
extensivo en una lección anterior. Aquí se incluye debido al contexto.

Expansión de llaves

La expansión de llaves expande una sola palabra en palabras múltiples, sustituyendo uno de los
elementos en "llave" para cada palabra. Por ejemplo, la expresión {c,b,r}at se expandiría en tres
palabrascat bat rat. La expansión de llaves se utiliza para referirse (o crear) archivos que tienen
prefijos, postfijos o componentes de ruta comunes, (recuerde que varios ejercicios de laboratorio

162
han utilizado expansión de llaves para crear rápidamente un gran número de directorios o archivos
y luego subdirectorios dentro de ellos).

[prince@station prince]$ mkdir chap{01,02,03,04}

El usuario prince ahora tiene los siguientes cuatro directorios:

|-- chap01/
|-- chap02/
|-- chap03/
`-- chap04/

4 directories, 0 files

[prince@station prince]$ mkdir chap{01,02,03,04}/{html,text}

Ahora se han agregado los siguientes directorios.

|-- chap01/
| |-- html/
| `-- text/
|-- chap02/
| |-- html/
| `-- text/
|-- chap03/
| |-- html/
| `-- text/
`-- chap04/
|-- html/
`-- text/

12 directories, 0 files

En el primer comando mkdir, la palabra entre corchetes se expande a cuatro directorios chap01,
chap02, chap03, y chap04. En el segundo comando mkdir, la palabra con doble corchete se
expande a ocho directorios chap01/html, chap01/text, chap02/html y así sucesivamente.

A diferencia de los archivos/comodines, las palabras que resultan de la expansión de llaves no


coinciden con los archivos en el sistema de archivos (los archivos no tienen que existir). De hecho,
las palabras expandidas no tienen que ser nombres de archivos, aunque en la práctica suelen
serlos.

Expansión de tilde

Quizás este es el concepto más sencillo de expansión, la expansión de tilde, el cual expande un
~nombredeusuario para el usuario del directorio de inicio del nombredeusuario, como se listó en el
archivo/etc/passwd (o la base de datos apropiada del usuario). A continuación, prince utiliza la
expansión tilde para referirse a su directorio propio y a los directorios de elvis, y luego un
subdirectorio del directorio de inicio de elvis.

163
[prince@station prince]$ ls -ld ~ ~elvis
drwx-----x 15 elvis elvis 4096 Jul 21 17:41 /home/elvis
drwx-----x 9 prince prince 4096 Aug 4 06:58 /home/prince
[prince@station prince]$ ls -l ~elvis/pub
total 4
drwxrwxr-x 2 elvis music 4096 Jul 13 05:46 music

A menudo en este curso y en otros textos, la tilde se utiliza para implicar que un archivo debería
existir en el directorio de inicio del usuario, tal como el archivo ~/.bash_history. Ahora podemos ver
la razón de esta convención.

Expansión de variables

La expansión de variables se trató de modo extenso en la lección anterior. Reformulando, la shell


bash expandirá (desreferenciará) expresiones de la forma $VARNAME o ${VARNAME} al valor de
la shell o variable de entornoVARNAME.

Expansión aritmética

La shell bash suele considerarse un entorno deficiente para cálculos numéricos y los operadores
aritméticos tales como +, -, *, y / en la línea de comando no tienen el significado matemático
habitual. Sin embargo, la shell bash trata de manera especial texto delimitado con una sintaxis $
((...)). Primero, las variables se tratan como enteros numéricos cuando resulte apropiado, y
segundo, los operadores matemáticos estándar como por ejemplo +, -, *, y / se tratan como tal. La
shell bash "expandirá" toda la expresión y la remplazará por el resultado numérico. Los operadores
aritméticos son los mismos del lenguaje de programación C y están totalmente documentados en la
página de manual bash(1) bajo "EVALUACIÓN ARITMÉTICA".

En el siguiente ejemplo, prince utilizará una expansión aritmética para calcular el área de un
rectángulo.

[prince@station prince]$ WIDTH=16


[prince@station prince]$ HEIGHT=82
[prince@station prince]$ echo $(( $WIDTH * $HEIGHT))
1312

Sin embargo, las limitaciones de cálculos numéricos se descubren rápidamente cuando prince trata
de volver a calcular el área mediante un número de punto flotante.

[prince@station prince]$ WIDTH=16.8


[prince@station prince]$ echo $(( $WIDTH * $HEIGHT))
-bash: 16.8 * 82: syntax error in expression (error token is ".8 * 82")

La shell bash sólo soporta enteros aritméticos.

Sustitución de comandos

Quizás de las expansiones más complejas y útiles, la sustitución de comandos permite a los
usuarios ejecutar comandos arbitrarios en la subshell e incorporar los resultados dentro de la línea

164
de comandos. La sintaxis de la"vieja escuela" para la sustitución de comandos es encerrar el
comando entre "acentos graves" (la comilla simple inclinada hacia la izquierda que se encuentra en
la misma tecla de ~, cerca de 1 en la mayoría de los teclados), y el comando de sustitución suele
denominarse "sustitución de acentos graves". La sintaxis más moderna soportada por la shell bash
es similar a la expansión aritmética, pero con solo un par de paréntesis: $(subcomando)

Como ejemplo de una sustitución de comandos, prince desearía crear un directorio que contenga
la fecha en su nombre. Después de examinar la página de manual date(1), crea una cadena de
formato para generar la fecha en un formato compacto.

[prince@station prince]$ date +%d%b%Y


04May2003

Ahora, ejecuta el comando mkdir mediante la sustitución de comandos.

[prince@station prince]$ mkdir reports.$(date +%d%b%Y)


[prince@station prince]$ ls
reports.04May2003

O pudo haber combinado las ventajas de la sustitución de comandos y la sustitución del historial
como se muestra a continuación.

[prince@station prince]$ mkdir reports.$(!da)


mkdir reports.$(date +%d%b%Y)
[prince@station prince]$ ls
reports.04May2003
La shell bash implementa la sustitución de comandos al generar una nueva subshell, ejecutar el
comando, registrar la salida y salir de la subshell. El texto se utiliza para invocar la sustitución de
comandos luego es remplazado por la salida registrada desde el comando.

Expansión de nombre de ruta

La expansión de nombre de ruta o "comodín de archivo", se describió en el cuaderno anterior, pero


no se introdujo como una expansión de shell. Ahora podemos ver que el nombre de ruta es uno de
los tipos de expansiones implementados por la shell bash. Para repasar, la sintaxis de la
expansión del nombre de ruta vea la siguiente tabla.

Table 1. Expansión del nombre de ruta bash

Caracter Coinciden
* 0 ó más caracteres
? exactamente un caracter
[...] exactamente uno de los caracteres incluídos
[^...] exactamente uno de los caracteres excluídos

Comillas y caracteres de escape

La shell bash usa varios caracteres de puntuación que se encuentran en el teclado para ejecutar
diferentes tipos de expansiones, redirecciones y otra clase de actos de expertos. Aunque es eficaz,
hay situaciones en que los usuarios desean utilizar uno de estos caracteres sin la invocación de

165
ningún tipo de conducta especial. Parafraseando a Sigmund Freud, "A veces un signo dólar es
sólamente un signo de dolar."

La shell bash proporciona tres mecanismos para evitar que los caracteres sean interpretados por
la shell, escapando, utilizando comillas dobles o sencillas.

Table 1. Uso de comillas y escape de la shell bash

Sintaxis Efecto
\ Impide que el siguiente caracter sea interpretado por la shell.
"..." Impide que los caracteres incluídos sean interpretados por la shell, exceptuando los
caracteres $, !, y ` (acento grave).
'...' Impide que todos los caracteres incluídos sean interpretados por la shell.

Considere los siguientes ejemplos, donde prince está tratando de imprimir en pantalla. En el primer
caso, prince define la variable CAR, y trata de imprimir la línea sin comillas.

[prince@station prince]$ CAR=corvette


[prince@station prince]$ echo <pre>little red $CAR</pre>
-bash: syntax error near unexpected token `newline'

SIn comillas, bash interpretó los caracteres > y < como solicitudes para redirigir la salida (y
entrada) del comando. La shell se confundió cuando se le pidió redirigir la salida dos veces. El
usuario prince, trata de nuevo, esta vez utilizando comillas dobles.

[prince@station prince]$ echo "<pre>little red $CAR</pre>"


<pre>little red corvette</pre>

En este caso, las comillas dobles protegieron los caracteres < y >. Sin embargo, el signo de dólar,
todavía se interpreta como marcador para una variable. El usuario prince intenta de nuevo con
comillas sencillas.

[prince@station prince]$ echo '<pre>little red $CAR</pre>'


<pre>little red $CAR</pre>

En este caso, todos los caracteres de puntuación fueron protegidos de la interpretación de la shell.
Como una alternativa, los caracteres pueden escaparse individualmente con una barra invertida
precedente.

[prince@station prince]$ echo \<pre\>little red $CAR\</pre\>


<pre>little red corvette</pre>
[prince@station prince]$ echo \<pre\>little red \$CAR\</pre\>
>pre<little red $CAR</pre>

Una nota sobre las comillas

166
Como hemos visto, bash hace uso de una variedad de signos de puntuación relacionados con
comillas, asignando a cada uno un propósito diferente. Los tres estilos de comillas se ilustran con
el comando echo de abajo. Con el fin de reforzar las diferencias, los tres estilos de comillas se
describen a continuación.

[prince@station prince]$ FOOD=guacamole


[prince@station prince]$ echo "wow! `whoami` sells $FOOD" 'for $!'
wow! prince sells guacamole for $!

Comillas dobles: "..."

Las comillas dobles se utilizan en situaciones donde usted desearía tratar la mayoría de la
puntuación literalmente o combinar palabras en un sólo símbolo, pero aún puede hacer uso
de variables, sustitución de comandos y sustitución de historial.

Comillas sencillas inclinadas a la derecha (apóstrofes): '...'

Las comillas sencillas son las más poderosas y se utilizan en situaciones similares a las
comillas dobles cuando quiere que toda la puntuación, incluyendo las variables y la
sustitución de comandos, se traten literalmente.

Comillas sencillas inclinadas hacia la izquierda (acentos graves): `...`

Los acentos graves son básicamente diferentes a las comillas simples o dobles, no son
para citar. Estos acentos se utilizan para invocar la sustitución de comandos en el texto
incluido.

Sutilezas de la expansión de línea de comandos

Hemos visto que bash se aplica a un gran número de expansiones de línea de comandos antes de
que un comando se ejecute. La frase incluye una sutileza que no siempre es apreciada y puede
algunas veces llevar a confusiones. Las expansiones de shell se presentan antes de que el
comando se ejecute. A veces, algunos los comandos esperan argumentos que contienen
caracteres especiales para la shell bash. Un ejemplo es el comando find. Si no se tiene cuidado al
utilizar comillas o escapar los caracteres especiales, bash podría "expandirlos" antes de que el
comando los vea. El siguiente ejemplo del comando find en acción podría ayudar.

Al iniciar desde un directorio vacío, prince ejecuta find para buscar todos los archivos terminados
en .conf en el directorio /etc.

[prince@station prince]$ find /etc -name *.conf


find: /etc/sysconfig/pgsql: Permission denied
/etc/sysconfig/networking/profiles/default/resolv.conf
/etc/sysconfig/networking/profiles/netup/resolv.conf
find: /etc/default: Permission denied
/etc/X11/gdm/factory-gdm.conf
/etc/X11/gdm/gdm.conf
/etc/modprobe.conf
...

167
Pasando por alto algunas quejas acerca de los directorios inaccesibles, el comando funciona.
Luego, prince crea los archivos a.conf y b.conf en el directorio local e intenta de nuevo.

[prince@station prince]$ touch a.conf b.conf


[prince@station prince]$ ls
a.conf b.conf
[prince@station prince]$ find /etc -name *.conf
find: paths must precede expression
Usage: find [path...] [expression]

¿Por qué el comando que funcionó hace apenas unos segundos no funciona ahora? La respuesta,
como podría esperarse, tiene que ver con la expansión de línea de comandos.

Primero, veamos el segundo caso. La shell bash encontró el siguiente comando.

find /etc -name *.conf

¿Qué hace primero bash? Aplica la expansión de línea de comandos. Después de examinar el
directorio local y hallar los archivos a.conf y b.conf, la shell remplaza el comodín *.conf con los
nombres de archivo coincidentes, a.conf b.conf. Esta es una expansión de nombre de ruta
bastante antigua. Después de la expansión, el comando se ve de esta manera.

find /etc -name a.conf b.conf

Ahora bash ejecuta el comando, el cual genera un mensaje de error (porque la opción -name no
pudo manejar dos argumentos).

Volviendo al primer comando, ¿por qué funcionó? Al implementar la expansión del nombre de ruta,
la shell bash intenta ayudar a la gente. Si un comodín "falta " (por ejemplo, ningún archivo coincide
con la expresión especificada), bash conserva el comodín. En el primer caso, como ninguno de los
archivos coincidió con *.conf, bash pasó el argumento al comando find como está escrito. [1]

¿Cuál es la forma correcta de manejar la situación? Usar comillas o escapar los caracteres
especiales, como se muestra a continuación:

[prince@station prince]$ find /etc -name "*.conf"


find: /etc/sysconfig/pgsql: Permission denied
find: /etc/default: Permission denied
/etc/sysconfig/networking/profiles/default/resolv.conf
/etc/sysconfig/networking/profiles/netup/resolv.conf
/etc/X11/gdm/factory-gdm.conf
/etc/X11/gdm/gdm.conf
/etc/modprobe.conf
...

Debido a que se ha utilizado el * , la shell bash no intentará realizar una expansión de nombre de
ruta y el comando funciona como se desea. La lección es: si está pasando un caracter especial

168
dentro de un comando, usted debería proteger el caracter con comillas (o un escape de barra
invertida).

Ejemplos

Uso de expansión de llaves

El usuario prince está configurando un directorio llamadoogg en el que va a almacenar archivos de


música que ha "quemado" (copiado) de sus discos favoritos. Con el fin de organizar las cosas, le
gustaría crear directorios basados en estilos diferentes de música y en cada uno de los
subdirectorios crear un archivo llamado playlist. En la siguiente transcripción, prince usa una
expansión de llave para agilizar su trabajo.

[prince@station prince]$ mkdir ogg


[prince@station prince]$ mkdir ogg/{blues,folk,rap,pop}
[prince@station prince]$ touch ogg/{blues,folk,rap,pop}/playlist

En este punto, prince ha creado la siguiente estructura de directorio.

ogg/
|-- blues
| `-- playlist
|-- folk
| `-- playlist
|-- pop
| `-- playlist
`-- rap
`-- playlist

4 directories, 4 files

¿Pudo prince haber utilizado el comodín de archivo (expansión de nombre de ruta) en su lugar? Al
utilizar el comando mkdir, el comodín de archivo habría sido inútil porque los directorios blues, folk,
etc.., no existían. ¿Qué sucedería si prince hubiera utilizado el comodín de archivo para el
comando touch?

[prince@station prince]$ touch ogg/*/playlist


touch: creating `ogg/*/playlist': No such file or directory

Los directorios blues, folk, etc., existeron, pero ninguno de los archivos playlist existia, por lo tanto
el comodiín se perdió. Para situaciones en que el archivo podría o no existir, la expansión de llaves
tiende a funcionar mejor que el comodín.

Más acerca de la terminación con el tabulador

Hemos visto que la shell bash graba las pulsaciones al completar nombres de comandos o
nombres de archivos cuando se pulsa la tecla TAB. La shell bash completará nombres de usuario
y variables, cuando las palabras comienzan por los caracteres ~ o $, respectivamente. Por
ejemplo, si un usuario escribe ~el<TAB>, bash podría completar el símbolo ~elvis. De la misma
manera, $PA<TAB> podría completarse $PATH. De forma similar a la expansión del comando y

169
nombre de archivo, si los caracteres iniciales tecleados hasta el momento no especifican
únicamente una variable (o nombre de usuario), bash emite un pitido. Al pulsar dos veces el TAB
se listarán las posibles terminaciones.

Poner entre comillas los nombres de archivos raros

En un cuaderno anterior, mencionamos que los nombres de archivo en Linux (y Unix) podrían estar
compuestos por cualquier caracter a excepción de uno (¿Recuerda cuál?[1]) En el mismo cuaderno,
se les dijo a los estudiantes que aunque se podían utilizar caracteres especiales, era mejor
evitarlos. Ahora estamos en una buena posición para ver el porqué. Suponga que prince quiere
crear un archivo único llamado Make $$$ *Fast* !!.

[prince@station prince]$ touch Make $$$ *Fast* !!


touch Make $$$ *Fast* l
[prince@station prince]$ ls
13986$ *Fast* l Make

El comando touch accede, creando los archivos que bash le pide hacer. Primero, como los
símbolos están separados por espacios, bash los trata como cuatro palabras separadas. Luego la
shell bash aplica sus distintas expansiones a las palabras.

1. El archivo Make se crea fácilmente.


2. La shell bash aplica la sustitución de variables a $$$, resultando en 13986$. (¿De dónde
sale el número 13986?[2])
3. El símbolo *fast* sobrevive con el preservado del *, pero ese no tenía que ser el caso.
4. Por último, !! se expande a l desde el historial de comandos del usuario, el cual
aparentemente (y un poco extraño) fue el anterior comando ejecutado.

Una vez se han aplicado las extensiones, la shell bash invoca touch con cuatro argumentos, para
que touch obedientemente cree cuatro archivos.

¿De qué manera persuadimos a bash para que cree un archivo con nuestro rito proporcionado por
Linux de incluir espacios y puntuación en el nombre de archivo? Obviamente con comillas.

[prince@station prince]$ touch 'Make $$$ *Fast* !!'


[prince@station prince]$ ls
13986$ *Fast* l Make Make $$$ *Fast* !!

Con sólo ls, es difícil distinguir entre múltiples archivos y un archivo único con espacios en el
nombre. Un ls -l ayuda a aclarar la situación.

170
[prince@station prince]$ ls -l
total 0
-rw-rw-r-- 1 prince prince 0 Aug 31 06:19 13986$
-rw-rw-r-- 1 prince prince 0 Aug 31 06:19 *Fast*
-rw-rw-r-- 1 prince prince 0 Aug 31 06:19 l
-rw-rw-r-- 1 prince prince 0 Aug 31 06:19 Make
-rw-rw-r-- 1 prince prince 0 Aug 31 06:40 Make $$$
*Fast* !!

Observe que las comillas sirven en realidad para dos propósitos.

1. Las comillas inhiben la interpretación de los signos de puntuación como lo solicitan las
expansiones de shell.
2. Las comillas impiden la división de palabras, la cual es la forma como la shell bash
compone argumentos para los programas que ejecuta. Por ejemplo, el comando touch
one two three haría que bash ejecute el comandotouch con tres argumentos, one, two, y
three. Por el contrario, el comando touch "one two three" haría que bash pase el único
argumento del comando touch a one two three (aunque uno con espacios).

Ejercicios en línea Lab Exercise Objetivo: Usar varias sustituciones de shell bash de modo
efectivo. Tiempo estimado: 15 minutos.

Especificaciones

1. Configure su archivo ~/.bashrc para que, tras el arranque, la variable LINUX_VERS


contenga toda la primera línea del archivo /var/log/dmesg, (el archivo /var/log/dmesg se
regenera cada vez que se arranca la máquina, por lo que deberá establecer la variable de
modo dinámico. Recuerde que el comando head -1 mostrará la primera línea del archivo).
2. En su directorio de inicio, cree archivos con los sigu¡entes nombres de archivo, (el
contenido de los archivos es irrelevante).
a. archivo sin título
b. **'s y ||'s
c. >> README!! <<
3. En su directorio de inicio, cree un subdirectorio denominado shirts. Dentro del
subdirectorio, cree 108 archivos de la forma estilo.tamaño.color.ext, donde cada archivo
contenga una combinación de valores a partir del cuadro siguiente.
Estilo tee, crew, turtleneck
Tamaño XXL, XL, L, M, S, XS
Color red, yellow, blue
Extensión info, inv
4. Por ejemplo, el directorio debería contener archivos titulados tee.XXL.red.info,
tee.XXL.red.inv, tee.XL.red.info, tee.XL.red.inv y así sucesivamente.

Deliverables A title Question 1

1. Tras el arranque, la variable LINUX_VERS debe establecerse para que contenga la


primera línea del archivo /var/log/dmesg.
2. Los archivos a continuación deberían existir en el directorio de inicio del usuario.
a. archivo sin título
b. **'s y ||'s
c. >> README!! <<

171
3. Un directorio llamado ~/shirts, el cual contiene exactamente 108 archivos, cada uno
de forma estilo.tamaño.color.ext. Cada nombre de archivo contiene una combinación
de los valores que aparecen en el cuadro de arriba.

172
Personalización de la shell

Conceptos clave

• La shell bash internamente implementa ciertos comandos sencillos que están muy ligados
con la conducta de la shell. Estos se conocen como los comandos incorporados.
• Los alias de shell crean comandos aparentes que expanden a texto arbitrario.
• Los alias de shell se establecen y examinan con el comando alias.
• Los alias de shell se remueven con el comando unalias.
• El intérprete de comandos de la shell bash se puede personalizar mediante la variable
PS1.
• Las banderas de shell se pueden establecer con el comando set -f y se limpian con set +f.
• Las opciones de shell se examinan, establecen y se anulan con el comando shopt.

Discussion

Esta lección se centra en las técnicas utilizadas para personalizar la shell bash, como por ejemplo
crear comandos alias, personalizar el intérprete de comandos de la shell y establecer las opciones
de la shell. La lección comienza con un tema que no es la personalización real, pero está
relacionada con la conducta de la shell, el tema de los comandos internos.

Comandos internos de la shell

Al evaluar una línea de comandos, la shell trata la primera palabra como un comando. La shell
bash implementa algunos comandos de modo interno, lo que significa que los comandos no
existen en el sistema de archivos como un programa cargable, sino que la shell misma los
implementa. Estos comandos se conocen como comandos internos de la shell. Estos suelen ser
comandos sencillos relacionados con cambios a la shell misma.

En un cuaderno anterior, presentamos el comando which, el cual reportará en qué parte del
sistema de archivo reside el archivo ejecutable que contiene un comando en particular. A
continuación, madonna observa que el comando date es implementado por el programa que se
encuentra en el archivo ejecutable /bin/date:

[madonna@station madonna]$ which date


/bin/date

¿Qué sucede cuando madonna utiliza which para buscar el archivo ejecutable que contiene el
programa cd?

[madonna@station madonna]$ which cd


/usr/bin/which: no cd in
(/usr/local/j2sdk1.3.1/bin:/bin:/usr/bin:/usr/local/bin
:/usr/bin/X11:/usr/X11R6/bin:/home/madonna/bin)

De acuerdo con which, el comando cd no existe como ejecutable en el sistema de archivos. El


comando cd es un ejemplo de un comando interno de la shell. Una lista de comandos internos de

173
la shell y su documentación correspondiente se puede ver mediante el comando help, el cual es en
sí mismo un comando interno de la shell.

[madonna@station madonna]$ help


GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu)
These shell commands are defined internally. Type `help' to see this
list.
Type `help name' to find out more about the function `name'.
Use `info bash' to find out more about the shell in general.
Use `man -k' or `info' to find out more about commands not in this list.

...

alias [-p] [name[=value] ... ] bg [job_spec]


bind [-lpvsPVS] [-m keymap] [-f fi break [n]
builtin [shell-builtin [arg ...]] case WORD in [PATTERN [| PATTERN].
cd [-L|-P] [dir] command [-pVv] command [arg ...]
compgen [-abcdefgjksuv] [-o option complete [-abcdefgjksuv] [-pr] [-o
...

El comando help entrega una versión de la información sobre la shell, menciona un par de sitios
donde la documentación de bash puede encontrarse y presenta bota una lista de comandos
internos. Observe que la lista contiene el comando cd. El comando help también se puede utilizar
para ver documentación detallada acerca de un comando interno específico.

[madonna@station madonna]$ help cd


cd: cd [-L|-P] [dir]
Change the current directory to DIR. The variable $HOME is the
default DIR. The variable CDPATH defines the search path for
the directory containing DIR. Alternative directory names in CDPATH
are separated by a colon (:). A null directory name is the same as
the current directory, i.e. `.'. If DIR begins with a slash (/),
then CDPATH is not used. If the directory is not found, and the
...

Dado que el comando cd está ligado a la conducta de la shell, es decir, cambia el directorio de
trabajo de la shell, este es un buen candidato para un comando interno. Varios comandos que ya
ha estado utilizando, tales como cd, pwd, y echo, son en realidad internos de la shell.

Alias

Los alias permiten a los usuarios personalizar los nombres de los comandos o enlazar comandos
con las opciones o argumentos más utilizados. Una vez creados, los alias se utilizan como si
fueran cualquier otro comando.

El comando alias

Los alias se crean (y examinan) mediante el comando interno alias. Al crear alias, el comando
alias utiliza la siguiente sintaxis.

174
alias NAME=VALOR

Este comando crearía un alias denominado NOMBRE, el cual apuntaría al valor VALOR. La
sintaxis debería ser reminiscente a la utilizada para asignar variables de shell. En particular, como
en la asignación de variable, la asignación de alias no permite espacios en ningún lado del signo
de igual. Del mismo modo, dado que la sintaxis sólo espera un símbolo único después del signo
igual, las frases que contienen múltiples palabras (separadas por espacios) deben ir entre comillas.

En el siguiente ejemplo, madonna establece el alias h como un atajo para el comando head. Dado
que el alias apunta a una sola palabra (head), madonna no tiene que preocuparse por citar el valor.
Luego utiliza el nuevo alias para examinar varias de las primeras líneas del archivo /etc/services.

[madonna@station madonna]$ alias h=head


[madonna@station madonna]$ h /etc/services
# /etc/services:
# $Id: 010_text.dbk,v 1.3 2004/01/07 18:41:02 bowe Exp $
#
# Network services, Internet style
#
# Note that it is presently the policy of IANA to assign a single well-
known
# port number for both TCP and UDP; hence, most entries here have two
entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all
ports
# are included, only the more common ones.

En el siguiente ejemplo, madonna advierte que a menudo está listando todos los procesos
ejecutándose en la máquina con el comando ps aux. Decide entonces que cada vez que ejecute
ps, prefería la salida más completa que ps aux presenta y por lo tanto establece un alias para el
comando ps.

[madonna@station madonna]$ alias ps="ps aux"


[madonna@station madonna]$ ps
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1376 72 ? S Aug30 0:04 init [
root 2 0.0 0.0 0 0 ? SW Aug30 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Aug30 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Aug30 0:00
[ksoftirqd_CPU0]
root 9 0.0 0.0 0 0 ? SW Aug30 0:00 [bdflush]
root 5 0.0 0.0 0 0 ? SW Aug30 0:00 [kswapd]
...

175
En este caso, puesto que ella quiso que el alias apuntara a una frase de dos palabras (ps y aux),
necesitó encerrar la frase entre comillas (para que tras "la división de palabras", la shell trate la
frase como una sola palabra).

El comando alias también se utiliza para examinar los alias actualmente definidos. Si madonna
quisiera repasar los alias que estableció podría sencillamente ejecutar el comando alias (sin
argumentos).

[madonna@station madonna]$ alias


alias h='head'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias ps='ps aux'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

El comando alias lista los alias establecidos por madonna (h y ps), como también otros alias
establecidos por los scripts de arranque bash de madonna (y son parte de la configuración
predeterminada de Red Hat Enterprise Linux).

Si se dan argumentos (sin el signo de igual), el comando alias mostrará el alias actual para el
argumento, si existe alguno:

[madonna@station madonna]$ alias ps h foo


alias ps='ps aux'
alias h='head'
-bash: alias: foo: not found

El comando unalias

Los alias se pueden suprimir con el comando interno de la shell unalias. Para suprimir un alias,
pase el nombre de alias como un argumento al comando unalias. A continuación madonna
suprime el alias que creó anteriormente para ps.

[madonna@station madonna]$ unalias ps


[madonna@station madonna]$ alias ps
-bash: alias: ps: not found

Evaluación de alias

¿Cuándo busca alias la shell de bash ? A diferencia de las variables, no hay signos de puntuación
asociados con ninguna clase de "expansión de alias". En su lugar, la shell de bash busca alias en
donde se espera un comando (es decir, como la primera palabra en la línea de comando). Si la
primera palabra es reconocida como un alias , el alias se expande. La excepción es si el alias se
expande al comando que tiene el mismo nombre de alias en cuyo caso la shell simplemente
ejecuta la expansión y sigue adelante, (de otra manera, los usuarios podrían fácilmente crear alias
que pondrían la shell en un bucle infinito).

176
Los usuarios pueden no darse cuenta de que están usando alias en lugar del comando mismo. Un
buen ejemplo es la configuración predeterminada de Red Hat Enterprise Linux, la cual alias el
comando ls al valor ls --color=tty, (este instruye a ls para proporcionar caracteres de control
especiales que dan color a diferentes tipos de archivos, pero solo si el comando está escribiendo
en una terminal. Cuando se redirige a un archivo, no se presenta ningún color).

Ejecución de comandos

Hemos descrito varios tipos de palabras considerados por la shell bash como "comandos". Para
resumir, y proveer un contexto, la siguiente lista resume los pasos que la shell bash realiza al
evaluar la primera palabra de la línea de comandos, (el siguiente no es el algoritmo exacto, el cual
es más complicado, pero sirve como una aproximación útil).

1. Realiza cualquier expansión de la shell.


2. ¿La palabra se define como un alias? Si es así, expanda el alias y vuelva a comenzar (a
menos que el alias se expanda a un comando que tenga el mismo nombre del alias en
cuyo caso expande el alias y empieza de nuevo, pero no vuelve a expandir alias).
3. ¿La palabra se define como una función de una shell? Si es así, llame la función de la shell
en la shell actual, (las funciones de la shell van más allá del alcance de este curso, pero
están incuídas aquí para completar la información).
4. ¿La palabra es un comando intermo de la shell? Si es así, ejecute el comando interno.
5. ¿La palabra contiene un /? Si es así, ejecute el archivo si existe y tiene permisos
ejecutables.
6. Si la palabra no contiene un /, busque un archivo con un nombre similar en todos los
directorios en orden como se definió en el entorno de variable PATH. Si existe un archivo
coincidente y tiene permisos ejecutables, ejecute el archivo.

Personalizar el intérprete de comandos de bash

La shell bash interactiva, mientras que repite su bucle de "escuchar", "evaluar" y "ejecutar", expide
un intérprete de comandos cada vez que vuelve a la etapa de "escuchar". El intérprete de
comandos se utiliza para contarle al usuario que la evaluación de la etapa anterior ha terminado y
que la shell está esperando intrucciones. En la configuración predeterminada de Red Hat
Enterprise Linux , el intérprete de comandos también provee más información, incluyendo el
nombre de usuario actual, nombre de la máquina y directorio de trabajo.

El comando bash en realidad tiene cuatro intérpretes de comandos diferentes los cuales se utilizan
en diferentes situaciones. Los dos más vistos son el intérprete de comandos primario, utilizado
cada vez que bash está listo para un nuevo comando y el intérprete de comandos secundario
utilizado cuando un usuario presiona la tecla INTRO, pero la línea de comandos tiene obviamente
una sintaxis inacabada (tal como unas comillas que aún no se han cerrado). A continuación
[madonna@station madonna]$ sirve de intérprete de comandos primario, mientras que> sirve de
intérprete de comandos secundario.

[madonna@station madonna]$ echo "Little Miss Muffet


> Sat on a Tuffet"
Little Miss Muffet
Sat on a Tuffet

Personalización del intérprete de comandos de bash con PS1 y PS2

177
Los usuarios pueden personalizar los intérpretes de comandos de bash mediante las variables de
shell PS1 y PS2, las cuales bash usa para componer los dos prompts. El ejemplo anterior implicó
que el intérprete de comandos primario es la forma de decir de bash "Estoy esperando", y el
intérprete de comandos secundario es la forma de decir de bash "Todavía estoy esperando". Para
plantear el punto de una forma obvia, madonna personalizará sus intérpretes de comandos para
decir justo eso.

[madonna@station madonna]$ PS1="I'm waiting ... "


I'm waiting ... PS2="I'm still waiting ... "
I'm waiting ... echo "Hickory Dickory Dock
I'm still waiting ... three mice ran up the clock"
Hickory Dickory Dock
three mice ran up the clock
Estoy esperando ...

Inmediatamente tras cambiar el valor de la variable PS1, bash comenzó a utilizar el nuevo valor
como su intérprete de comandos primario.

A menudo los usuarios desearían que el intérprete de comandos también visualizara información
útil. La shell de bash permite a los usuarios insertar secuencias de escape dentro de la definición
de PS1, que remplaza con información dinámica cuando se genera el intérprete de comandos. El
cuadro a continuación resume algunas de las secuencias más comunes. Para obtener una lista
más completa, vea la página de manual bash(1).

Table 1. Secuencias de escape comunes utilizadas en intérpretes de comandos bash

Secuencia Expansión
\a Campana audible de la terminal
\d fecha en formato"día mes"
\h el nombre del host hasta el primer "."
\T La hora actual en formato de 12 horas HH:MM:SS
\u el nombre de usuario del usuario actual
\W el nombre de la base del directorio de trabajo actual
\! El número de historial de este comando
\$ Si el UID efectivo es 0, un #, de lo contrario un $
\nnn el caracter correspondiente al número octal nnn

La expansión de parámetros (variables), la expansión aritmética, y la sustitución de comandos se


aplican al valor de PS1 cuando el intérprete de comandos es generado también.

La secuencia de escape \$ puede requerir más explicación. La shell de bash utiliza esta secuencia
para reproducir una característica de la shell Bourne originial (/bin/sh). El intérprete de comandos
por defecto de la shell Bourne es un dólar ($) para los usuarios estándar y un signo (#) para el
usuario root. Con la secuencia de escape \$, un valor predeterminado PS1 para todo el sistema
puede utilizarse, imitándo esta conducta original.

Al personalizar el intérprete de comandos de bash, el intérprete de comandos suele verse más


limpio si la variable PS1 está definida con un espacio al final.

Opciones y banderas de la shell de bash

178
Se utilizan dos comandos internos para configurar la conducta de la shell mediante las opciones de
shell. Uno es el comando set, el cual se utiliza para modificar la conducta de shell mediante (por lo
general) banderas de una letra, y el otro esshopt, usado para configurar las opciones de la shell.

Banderas de la shell: el comando interno set

El comando set realiza una labor triple. Cuando se utiliza con la línea de comandos, como suele
ser el caso, el comando se utiliza para establecer, o anular las banderas de shell. Observe el
cuadro siguiente con las banderas más utilizadas y sus opciones. Cuando se llamado sin
argumentos, el comando set visualiza todas las variables de shell y sus valores (como se describió
en una lección anterior). El último uso del comando incorporado se utiliza en la escritura de shell y
por ahora puede hacerse caso omiso sin ningún problema.

Table 1. Banderas de la shell que el comando interno set utiliza.

Bandera Efecto
-f Inhabilita la expansión de nombres de ruta (comodín)
-n Lee comandos pero no los ejecuta (se usa para revisar sintaxis en los
scripts).
-o Establece la opción especificada. Algunas de las opciones más comunes
nombredeopción incluyen lo siguiente.

emacs

Emplea líneas de comandos con enlaces de teclas del estilo emacs

ignoreeof

No sale de la shell cuando se lee EOF (CTRL-D)

vi

Usa enlaces clave de línea de comando del estilo vi


-v Imprime comandos como se leen (útil para depurar scripts)
-x Imprime comandos despues de aplicadas las expansiones (útil para depurar
scripts y examinar expansiones de la shell)
-C No le permite a la shell reescribir archivos en redirección.

El comando set con la sintaxis normal de las opciones (tal como set -x) habilita la bandera
especificada. Para inhabilitar la bandera, remplace el guión (-) por un signo más (+) (tal como set
+x). La lista de opciones establecidas puede almacenarse en la variable de shell $-.

Por ejemplo, a continuación, madonna temporalmente inhabilita el comodín de archivo (habilitando


la bandera de shell -f) y luego restaurando el comodín de archivo (inhabilitando el mismo).

179
[madonna@station madonna]$ set -f
[madonna@station madonna]$ ls /etc/*.conf
ls: /etc/*.conf: No such file or directory
[madonna@station madonna]$ set +f
[madonna@station madonna]$ ls /etc/*.conf
/etc/aep.conf /etc/lftp.conf /etc/pnm2ppa.conf
/etc/aeplog.conf /etc/libuser.conf /etc/pwdb.conf
/etc/cdrecord.conf /etc/logrotate.conf /etc/resolv.conf
/etc/esd.conf /etc/lpd.conf /etc/rndc.conf
...

No se preocupe si no entiende aún los efectos de todas las banderas de shell. En su lugar,
asegúrese de saber cómo se utiliza el comando set para habilitar o inhabilitar una bandera si es
necesario. Si en una lección posterior le dijeran "esta acción puede inhabilitarse al configurar la
bandera -H de shell ", usted sabrá cómo hacerlo.

Opciones de la shell: el comando interno shopt

El comando bash también tiene una segunda serie de variables de configuración, las cuales se
conocen como "opciones de shell". Estas se establecen y se anulan mediante el comando shopt
donde shopt -s nombreopciónestablece la opción nombreopción, y shopt -u nombreopción
anula la opción. El comando shopt nombreopción visualiza el estado actual de la opción,
mientras que solo shopt visualiza todas las opciones de la shell. Algunas de las opciones de shell
más fáciles de entender están listadas en el cuadro siguiente.

Table 1. Opciones de la shell bash

Opción Efecto
cdspell Intenta corregir palabras mal escritas de los nombres de directorios cuando
utiliza el comando incorporado cd.
expand_aliases Habilita alias de shell
extglob Habilita sintaxis coincidente de patrones de comodines extendidos
nocaseglob No considera el caso cuando se aplican comodines de archivo.

Lo anterior se presenta a manera de ejemplos. Revise la página de manual de bash(1) para


obtener una lista completa. A continuación, madonna examina el estado de la opción de shell
cdspell, lo habilita y luego el de cd en el directorio /etc con un deletreo descuidado.

[madonna@station madonna]$ shopt cdspell


cdspell off
[madonna@station madonna]$ shopt -s cdspell
[madonna@station madonna]$ cd /ect
/etc

Una vez allá, descubre que la opción de shell solo efectúa el comando interno de cd. El comando
ls, por ejemplo, que no es un incorporado de shell, no se afecta por esta opción. Después de
observar este hecho, madonna, inhabilita la opción cdspell.

[prince@station prince]$ touch ogg/*/playlist


touch: creating `ogg/*/playlist': No such file or directory

180
Se estará preguntando cómo recordar todas estas opciones y cómo recordar cuáles se modifican
con set y cuáles con shopt. La respuesta es que no es necesario. Recuerde sin embargo, que hay
dos mecanismos para establecer banderas de shell y opciones de shell (set y shopt,
respectivamente) y recuerde dónde buscar información sobre cada una (el comando help y la
página de manual bash(1)).

Ejemplos

Alias predeterminados en Red Hat Enterprise Linux

La configuración predeterminada en Red Hat Enterprise Linux proporciona varios usos ilustrativos
de alias. Tras iniciar sesión en el comando alias se revela lo siguiente.

[madonna@station madonna]$ alias


alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

El primer alias, l., se utiliza para listar todos los archivos ocultos (aquellos que comienzan por ".")
en el directorio actual.

[madonna@station madonna]$ l.
. .bash_profile .gconfd .gnome-desktop .xauthxLTmDk
.. .bashrc .gnome .gtkrc
.bash_history .fonts.cache-1 .gnome2 .kde
.bash_logout .gconf .gnome2_private .viminfo

Observe que la shell bash ejecuta la expansión de nombre de ruta después de expandir el alias,
para que .* sea remplazado por cada archivo en el directorio local que comienza con ".".

El segundo alias, ll, provee una forma más fácil para invocar el comando ls con su opción de línea
de comando más usada -l. El tercer alias, ls, en efecto cambia la conducta por defecto del
comando ls, para que cada invocación de ls incluya la opción de línea de comandos --color=tty.

Si consideramos cómo bash evalúa alias, alguna redundancia se descubre. Cuando un usuario
ejecuta ll, bash expande el alias a ls -l --color=tty. La shell de bash luego examina la primera
palabra de la expansión, ls, la cual es en sí misma un alias. La expansión de alias resulta en ls
--color=tty -l --color=tty. Puesto que el alias ls se expandió al comando cuya primera palabra fue
otra vez ls, bash no intenta otras expansiones de alias. Sin embargo, la expansión resultante ll
especifica dos veces --color=tty.

La bandera de shell bash "x" es útil para descubrir estos tipos de problemas. Cuando sea
habilitado, cada comando se imprime en pantalla (con un prefijo "+") después de que todos los
alias y expansiones se hayan aplicado.

181
íneas [madonna@station madonna]$ set -x
++ echo -ne '\033]0;madonna@station:~\007'
[madonna@station madonna]$ ll
+ ls --color=tty -l --color=tty
total 12
drwx------ 2 madonna madonna 4096 Aug 26 16:23 bin
-rw-rw-r-- 1 madonna madonna 76 Aug 26 16:10 hello.c
drwxr-xr-x 4 madonna madonna 4096 Jul 21 17:05 networking
++ echo -ne '\033]0;madonna@station:~\007'
[madonna@station madonna]$ set +x
+ set +x
[madonna@station madonna]$

Infortunadamente, al habilitar la bandera "x" de la shell genera líneas complejas reflejando la


generación de cada intérprete de comandos, pero expandido totalmente el ls --color=tty -l
--color=tty se ve con claridad que es en realidad ejecutado como resultado del comando ll.

El cuarto alias, vi, se utilliza para reasignar un comando empleado para una implementación
alterna. Uno de los editores más comunes de Linux (y Unix) es el editor vi. Red Hat Enterprise
Linux se distribuye con una versión mejorada de vi, conocida como vim (para "Vi IMproved"). Con
el fin de hacer uso transparente del editor mejorado, el comando más utilizado vi ha sido
reasignado.

El último alias crea un delimitador para el comando which, para que los alias también sean
reportados como sitios de archivos ejecutables hallados en la ruta de un usuario.

Uso de alias para crear comandos rm, mv, y cp más seguros

El examen de los usos de las opciones de los comandos rm, mv y cp revela que todos comparten
la opción -i que se utiliza para invocar un modo interactivo. Cuando se utiliza, estos comandos le
pedirán al usuario confirmación antes de ejecutar una operación que causaría la pérdida de
información (tal como los comandos comodines cp o mv de un archivo de destino ya existente o
cualquier uso del comando rm). El uso de la opción -i se ilustra a continuación.

[madonna@station madonna]$ date > a


[madonna@station madonna]$ date > b
[madonna@station madonna]$ cp -i a b
cp: overwrite `b'? y
[madonna@station madonna]$ mv -i a b
mv: overwrite `b'? y
[madonna@station madonna]$ rm -i b
rm: remove regular file `b'? y

Muchos administradores de sistemas establecen alias por defecto para estos comandos, para que
cada invocación de estos comandos sea una invocación interactiva.

182
[madonna@station madonna]$ alias cp="cp -i" mv="mv -i" rm="rm -i"
[madonna@station madonna]$ alias cp mv rm
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
[madonna@station madonna]$ date > a
[madonna@station madonna]$ date > b
[madonna@station madonna]$ cp a b
cp: overwrite `b'? y
[madonna@station madonna]$ rm a b
rm: remove regular file `a'? y
rm: remove regular file `b'? y

En Red Hat Enterprise Linux, la cuenta de root tiene dichos alias establecidos por defecto. Sin
embargo, los usuarios estándar, pueden configurar estas protecciones por su cuenta si así lo
desean.

Cada uno de estos comandos también viene con la opción -f para "forzar" la conducta requerida.
Dado que la opción -f anula la opción -i y puede emplearse para evitar la aburridora interrogación
al suprimir un gran número de archivos.

Uso de alias para crear marcadores de tiempo

La usuaria madonna quiere saber cuál de sus archivos y directorios "ocultos" en su directorio de
inicio son creados o modificados por aplicaciones que ella ejecuta. Quisiera saber una forma fácil
de controlar cuáles archivos se crean o cambian antes o después de ciertas operaciones. Ella sabe
que el comando find implementa un criterio -newer, el cual listará todos los archivos que han sido
modificados antes que un archivo especificado. Desearía crear dos alias. El primero llamado

Para crear el primer alias, primero dedica un poco de su tiempo a la lectura de la página de manual
date(1) y determina que el siguiente comando generará el nombre de archivo apropiado para el
archivo marcador de tiempo.

[madonna@station madonna]$ date +timestamp.%H:%M:%S


timestamp.19:30:23

Para crear los alias, agrega las dos líneas siguientes a su directorio ~/.bashrc. Observe el uso de la
sustitución de comandos para determinar el tiempo actual en el primer alias.

alias ts="touch $(date +timestamp.%H:%M:%S)"


alias tsc="find . -newer"

Abre una nueva shell (para que el .bashrc modificado tenga efecto), y ensaya sus nuevos alias.
Primero utiliza ts para crear un archivo marcador de tiempo.

[madonna@station madonna]$ ts
[madonna@station madonna]$ ls
bin hello.c networking timestamp.19:39:18

183
El alias ts parece funcionar, creando el archivotimestamp.19:39:18. Luego hace clic derecho en la
ventana secundaria del escritorio Gnome y elige "Nuevo Folder" desde el menu emergente. Un
folder recién creado untitled folder aparece en su ventana del escritorio. A continuación ejecuta el
alias tsc especificando su archivo marcador de tiempo recién creado como el archivo con el que se
compara.

[madonna@station madonna]$ tsc timestamp.19:39:18


./.gnome-desktop
./.gnome-desktop/untitled folder
./.nautilus/metafiles
./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna%2F.gnome-desktop.xml

Como se esperaba, el alias lista todos los archivos que han sido modificado más recientemente
que el archivo marcador de tiempo especificado. Observando que un archivo titulado untitled folder
fue creado en un subdirectorio llamado .gnome-desktop, madonna asume (correctamente) que el
directorio ~/.gnome-desktop contiene todos los elementos que se muestran en el escritorio de
Gnome.

Ella quiere sondear un poco más, esta vez explorando la conducta de la papelera. Decide crear un
nuevo archivo marcador de tiempo, mover su nueva carpeta a la papelera y luego buscar archivos
modificados relativos a sus nuevo archivo marcador de tiempo.

[madonna@station madonna]$ ts
[madonna@station madonna]$ ls
bin hello.c networking timestamp.19:39:18

Asombrada, madonna no ve su nuevo archivo. Examina la hora modificada del archivo original
ejecutando un ls -l.

[madonna@station madonna]$ ls -l timestamp.19:39:18


-rw-rw-r-- 1 madonna madonna 0 Sep 1 19:42
timestamp.19:39:18

Extrañamente, la hora modificada del archivo implica que se ha modificado aproximadamente tres
minutos después de su tiempo de creación hallado en el nombre del archivo. Explorando aún más
madonna confirma el alias ts.

[madonna@station madonna]$ alias ts


alias ts='touch timestamp.19:39:18'

Ahora madonna entiende el problema. Vuelve a llamar la línea desde su directorio ~/.bashrc donde
definió el alias ts:

alias ts="touch $(date +timestamp.%H:%M:%S)"

184
Aunque intentó la sustitución de comandos date para que se produjera cada vez que se invocara el
alias

Para confirmar sus instintos, edita su archivo~/.bashrc, renombrando el alias ts ts_incorrect y


agregando la siguiente línea.

alias ts_correct='touch $(date +timestamp.%H:%M:%S)'

Esta vez, el alias se define mediante comillas sencillas, evitando que la sustitución de comandos
sea evaluada al crearse el alias. Después de comenzar una nueva shell (para que ~/.bashrc surta
efecto), madonna confirma sus definiciones de alias.

[madonna@station madonna]$ alias ts_incorrect ts_correct


alias ts_incorrect='touch timestamp.19:47:18'
alias ts_correct='touch $(date +timestamp.%H:%M:%S)'

Ahora, al utilizar ts_correct, la sustitución de comandos se realiza cuando se invoca el alias


(contrario a cuando éste se define). Esta es la conducta que madonna deseaba. Luego sigue
explorando para saber qué archivos se modifican al utilizar la aplicación de la papelera Nautilus.

[madonna@station madonna]$ ts_correct


[madonna@station madonna]$ ls
bin hello.c networking timestamp.19:39:18 timestamp.19:48:12

Después de arrastrar el icono untitled folder del escritorio al icono basura, busca de nuevo archivos
modificados.

[madonna@station madonna]$ tsc timestamp.19:48:12


./.gnome-desktop
./.nautilus/metafiles
./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna%2F.gnome-desktop.xml
./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna%2F.Trash.xml
./.Trash

Aparentemente, la carpeta fue removida del directorio .gnome-desktop a la carpeta .Trash, (el
archivo untitled folder no es listado, porque el hecho de mover un archivo de un directorio a otro no
afecta la hora modificada del archivo, sólo las horas modificadas de los directorios.)

Ejercicios en línea Lab Exercise Objetivo: laboratorio de práctica Tiempo estimado: 15 minutos.

Especificaciones

Edite su archivo ~/.bashrc para que las shellsbash recién creadas tengan las siguientes
propiedades.

185
1. El alias dir ejecuta el comando ls -l.
2. El alias globoff inhabilita la expansión de nombre de ruta (habilitando la bandera de shell
apropiada).
3. El alias complementario globon habilita la expansión del nombre de ruta (inhabilitando la
bandera de shell apropiada).
4. Al redireccionar la salida a un archivo, la shell bash no sobrescribirá un archivo existente.
5. La shell tiene la opción de shell cdspell habilitada.
6. El comando rm es un alias para rm -i.

Ejercicio de desafio

El siguiente ejercicio debe completarse como un ejercicio de desafio. No será calificado por el
script automático de calificación.

Configure el intérprete primario para que contenga el número de historial y el código de salida del
comando previamente ejecutado, separado por un : (sin espacios). La coma debería ser la única
coma incluida en el intérprete.

Si está bien configurado, el intérprete debería tener una conducta igual a la siguiente. Observe con
cuidado la conducta del intérprete de comandos después de un comando con éxito, después de un
comando fallido, y cómo se relaciona con el número de historial del comando previamente
ejecutado.

[madonna@station madonna] 40:0 $ ls -d /tmp


/tmp
[madonna@station madonna] 41:0 $ ls -d /TMP
ls: /TMP: No such file or directory
[madonna@station madonna] 42:1 $ history
...
41 ls -d /tmp
42 ls -d /TMP
43 history
[madonna@station madonna] 43:0 $ !42
ls -d /TMP
ls: /TMP: No such file or directory
[madonna@station madonna] 44:1 $

Deliverables A title Question 1

Un archivo ~/.bashrc bien configurado, de tal forma que shells bash recién iniciadas tengan las
siguientes características.

1. El alias dir ejecuta ls -l


2. El alias globoff inhabilita las expansiones de nombre de ruta.
3. El alias globon habilita expansiones del nombre de ruta.
4. Al redireccionar la salida, la shell no sobrescribirá los archivos existentes.
5. La shell tiene habilitada la opción de shell cdspell.
6. Un alias rm, el cual ejecuta el comando rm -i.

186
Lectura de scripts de shell e inicialización de shell

Conceptos clave

• Los scripts de shell son leídos con el comando source o con ..


• Todos los scripts de shell se ejecutan en la misma shell que lee el script.
• Las shells bash pueden ser tanto shells de inicio como de no inicio.
• Las shells bash pueden ser tanto shells interactivas como no-interactivas.
• /etc/profile, archivos dentro del directorio /etc/profile.d y ~/.bash_profile leídos en el
arranque de cada shell de inicio de sesión.
• /etc/bashrc y ~/.bashrc se leen en el arranque de cada shell de inicio.
• ~/.bash_logout es leída por cada salida de shell de inicio de sesión.

Discussion

Hasta el momento en este cuaderno, hemos estado utilizando el archivo ~/.bashrc como si fuera el
único archivo que pudiera ser usado para personalizar la shell bash. Esto nos ha permitido
enfocarnos en temas, tales como los alias y expansiones de shell, sin complicarnos con detalles de
scripts e inicialización de shell, a riesgo de dejar al estudiante con la impresión de que el archivo
~/.bashrc es el único que puede utilizarse para personalizar la shell bash. Si esta es la impresión
que se ha dado, el propósito de esta lección es cambiar esa idea.

En esta lección, discutiremos cómo se pueden leer los scripts de shell y cuáles scripts se leen por
defecto en el arranque con Red Hat Enterprise Linux. El saber qué scripts son leídos en el
arranque, le permite a los usuarios aplicar automáticamente muchas de las personalizaciones
aprendidas en lecciones anteriores.

Lectura de scripts

La shell bash permite a los usuarios coleccionar múltiples comandos dentro de un sólo archivo y
luego ejecutar los comandos como si fueran tecleados directamente en ese intérprete. Esto se
conoce como leer el archivo. De modo apropiado, el comando usado para leer un archivo es el
comando interno de shell source.

Como ejemplo, blondie desearía explorar diferentes estilos de intérpretes de shell. Para ayudar a
comparar, utiliza un editor para crear un archivo de texto llamado prompts.script. Agrega varias
líneas, cada una proporcionando una definición diferente para la variable PS1. Por último, comenta
todo menos la primera línea.

[blondie@station blondie]$ cat prompts.script


PS1="whadda you want? "
#PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ "
#PS1="[\u@\h \W]\$ "

Con el fin de ensayar el primer intérprete, lee el archivoprompts.script.

[blondie@station blondie]$ source prompts.script


whadda you want?

187
Tras originar el archivo, la variable PS1 se modifica como si el contenido del script fuera tecleado
en la línea de comando. Este punto importante merece repetición: cuando se originan los scripts de
shell, el contenido del script se ejecuta (y puede modificarse) dentro de la shell actual.

Luego, blondie edita prompts.script, comentando la primera línea y sin comentar la segunda. Luego
lee el script otra vez.

whadda you want? cat prompts.script


#PS1="whadda you want? "
PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ "
#PS1="[\u@\h \W]\$ "
whadda you want? source prompts.script
blondie@station.example.com 2003-09-02 05:55:35 [15] $

Edita de nuevo el archivo, comentando la segunda línea y dejando de comentar la última (que
restaura su intérprete al predeterminado de Red Hat Enterprise Linux).

blondie@station.example.com 2003-09-02 05:57:07 [16] $ cat


prompts.script
#PS1="whadda you want? "
#PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ "
PS1="[\u@\h \W]\$ "

Como un atajo, la shell bash también tiene un comando interno llamado ., el cual es un sinónimo
para el comando source. Esta vez, blondie hace uso de su atajo al originar el archivo.

blondie@station.example.com 2003-09-02 05:57:09 [17] $ . prompts.script


[blondie@station blondie]$

(Algo confuso, la palabra . adquiere diferentes significados en diferentes contextos. Cuando .


aparece como la primera palabra en la línea, es sinónimo del comando source. Cuando . aparece
en cualquier otra parte, es el directorio de inicio actual)

Inicialización de bash

Shells de Inicio, no inicio, interactivas y no interactivas

Habiendo aprendido cómo leer scripts de shell de modo arbitrario, ahora volvemos la atención a la
inicialización de bash, la cual tiende a ser un tema demasiado complicado. Después de describir la
secuencia de arranque, el proceso será resumido en una forma más sucinta. Para comenzar a
distinguir sutilmente entre diferente tipos de shells: shells deinicio y no-inicio, y shells interactivasy
no-interactivas.

Como el nombre lo dice, las shells de inicio de sesión son la primera shell que usted ve cuando
inicia sesión en una máquina. Cuando usted inicia utilizando la consola virtual o dentro de una
máquina remota, su primera shell interactiva es una shell de inicio. Cuando inicie mediante el
entorno gráfico X, la shell no vista utilizada para empezar su inicialización X es una shell de inicio
de sesión.

188
Cada shell de por medio se conoce como una shell de no-inicio de sesión. ¿Con qué frecuencia ve
shells de no-inicio de sesión? Por todas partes. Obviamente, si usted fuera a iniciar manualmente
una subshell, ésta sería una shell de no-inicio. Cada vez que usted abre una nueva terminal en un
entorno gráfico X, la shell es una shell de no-inicio. Cada vez que usted usa la sustitución de
comandos o comandos de grupo entre paréntesis, o ejecuta scripts de shell (como se describirá en
la siguiente lección), se crea una nueva shell de inicio de sesión.

Además, las shells pueden ser interactivas o no-interactivas. Usualmente, las subshells iniciadas
de forma manual o las shells en terminales X recién abiertas, son shells interactivas. Las shells
invocadas como resultado de una sustitución de comandos y similares son shells no-interactivas. El
siguiente cuadro ayudará a distinguir los diferentes tipos de shells.

Table 1. Diferentes tipos de shells bash

Contexto ¿Shell de inicio de ¿Shell


sesión? interactiva?
Shells de inicio de sesión desde consolas virtuales Si Si
Shells de inicio de sesión cuando se inicie dentro de Si Si
una máquina a través de la red
Shell de inicialización X Si Si
Shell de terminal X No Si
subshell iniciada al ejecutar manualmente bash No Si
subshell utilizada en sustitución de comandos No No
subshell utilizada para comandos agrupados en () No No
subshell utilizada al ejecutar scripts No No

El cuadro de arriba lista los predeterminados para Red Hat Enterprise Linux. Diferentes conductas
pueden invocarse al especificar explícitamente ciertas opciones de línea de comandos. Vea la
página del manual de bash(1) para obtener mayor información.

Scripts bash de arranque

¿Cuál es la diferencia entre una shell de inicio de sesión y una shell de no-inicio de sesión? o entre
una shell interactiva y una no-interactiva? Principalmente, las shells difieren en qué archivos de
inicialización se leen tras el inicio. A continuación, se indicará el bash de inicialización de shell
como se presenta en Red Hat Enterprise Linux.

Shells de inicio de sesión

Tras el arranque, las shells de inicio de sesión primero leen el archivo /etc/profile. En Red
Hat Enterprise Linux, este archivo inicializa varias variables de entorno tales como PATH,
USER, HOSTNAME, y HISTSIZE. El script /etc/profile luego origina todos los archivos
coincidentes al patrón /etc/profile.d/*.sh. [1]

Luego, la shell bash busca una serie de archivos en el directorio de inicio del usuario, y lee
la primera que existe. En Red Hat Enterprise Linux, el archivo por defecto es
~/.bash_profile. La version por defecto de este archivo apenas agrega $HOME/bin al PATH
del usuario, y busca y origina el archivo~/.bashrc descrito a continuación.

189
Shells de no-inicio de sesión (interactivas)

En lo que concierne al programa bash, el único archivo utilizado para personalizar shells
de no-inicio de sesión es el archivo ~/.bashrc hallado en el directorio de inicio del usuario.
En la configuración por defecto de Red Hat Enterprise Linux, la única personalización que
este archivo realiza es buscar y leer el archivo /etc/bashrc.

El archivo global /etc/bashrc realiza varias operaciones, incluso establece la usmask por
defecto del usuario y define la variable PS1 (la cual define el prompt de shell).

Shells de no-inicio de sesión (no interactivas)

Las shells no-interactivas de no-inicio de sesión no leen por defecto ninguno de los
archivos de arranque (aunque esta conducta puede cambiarse estableciendo la variable de
entorno BASH_ENV. Para mayor información ver la página de manual bash(1)).

Figure 1. Archivos de configuración de arranque bash

¿Por qué hay shells de inicio de sesión y shells de no inicio de sesión?

¿Por qué tanta complejidad? Al arrancar, los varios scripts de arranque leídos por shells de inicio
tienden a emplear mucho tiempo personalizando variables de entorno (tales como el PATH,
HISTSIZE del usuario, etc). No obstante, cuando las subsehells se inician, no se necesita repetir
todo este trabajo. Siempre que un proceso hijo es generado por la shell de inicio de sesión, sea
ésta una subshell u otro caso, las variables de entorno se copian automáticamente en el hijo (por el
kernel de Linux). Si la subshell luego lee los mismos scripts de arranque como su shell de inicio del
padre, el esfuerzo de inicializar variables de entorno se duplicaría sin necesidad. Por lo tanto, con
el fin de agilizar los tiempos de arranque, las shells de no-inicio intentan acortar el proceso. Otras
personalizaciones de shell, principalmente los alias, son conceptos específicos de bash, no de nivel
de kernel y deben reinicializarse cada vez que se inicie una nueva shell.

Al examinar los scripts de arranque listados arriba, observe que los archivos /etc/profile y
~/.bash_profile son leídos śolo por las shells de inicio de sesión, mientras que los archivos

190
~/.bashrc y /etc/bashrc son leídos por todas las shells (de inicio y no-inicio). Los dos archivos
anteriores suelen utilizarse para configurar variables de entorno, porque sólo tienen que ser
inicializadas una vez. Mientras que los dos últimos archivos se utilizan para personalizaciones
específicas de la shell tales como alias y opciones de shell.

Observe la simetría. Para la configuración de variables de entorno, hay un archivo de arranque


global (/etc/profile) y un archivo de arranque local (~/.bash_profile). El primero puede utilizarse por
el administrador del sistema para establecer la configuración de todo el sistema. El último lo
pueden utilizar usuarios individuales para personalizar su propio entorno. Una situación parecida se
presenta con /etc/bashrc y ~/.bashrc.

Table 1. Archivos de configuración de arranque bash

Archivo Tipo de shell Uso previsto


/etc/profile Shells de inicio de Variables de entorno globalmente útiles
sesión
/etc/profile.d/*.sh Shells de inicio de Variables de entorno de paquetes específicos
sesión
~/.bash_profile Shells de inicio de Variables de entorno de usuarios específicos
sesión
~/.bashrc Todas las shells Alias de usuario específico, funciones de shell y
interactivas opciones de shell
/etc/bashrc Todas las shells Alias globales, funciones de shell y opciones de
interactivas shell

¿Por qué hay shells interactivas y no-interactivas?

Las shells no-interactivas son shells iniciadas como resultado de ejecutar un script (ver la siguiente
lección), usando paréntesis para agrupar comandos o usando sustitución de comandos. Con el fin
de evitar posibles efectos secundarios del script de arranque, las shells no-interactivas no leen
scripts de arranque tras el inicio.

Salida de las shells de inicio de sesión: ~/.bash_logout

Tras la salida, las shells de inicio de sesión leerán el archivo ~/.bash_logout si existe. En Red Hat
Enterprise Linux, el archivo simplemente ejecuta el comando clear para que la pantalla se limpie
de información tras la salida.

Ejemplos

El comando su revisitado

En un cuaderno anterior, presentamos el comando su como una forma de cambiar el userid


(cambiar el id del usuario). En ese momento, introdujimos dos modos de usar el comando su. El
primero era simplemente su nombredeusuario, el cual inicia una nueva shell de no-inicio como el
nuevo usuario. El segundo es ejecutar su - nombredeusuario, el cual inicia una shell de inicio de
sesión como el nuevo usuario.

Con el fin de explorar las implicaciones de estos dos modos haremos que blondie agregue la
siguiente línea a su archivo ~/.bash_profile.

Del mismo
echo modo, agrega la siguiente
"~/.bash_profile línea a su archivo ~/.bashrc.
sourcing"

191
echo "~/.bashrc sourcing"

Ahora haremos que el usuario elvis haga su en blondie usando ambas formas.

[elvis@station elvis]$ su blondie


Password:
~/.bashrc sourcing
[blondie@station elvis]$ exit
exit
[elvis@station elvis]$ su - blondie
Password:
~/.bashrc sourcing
~/.bash_profile sourcing

En el primer caso, sólo el archivo ~/.bashrc fue leído. En el segundo caso, tanto ~/.bash_profile
como ~/.bashrc son leídos.

De modo explícito, ejecutando source en /etc/profile y ~/.bash_profile

A menudo en este cuaderno y en las direcciones de Linux (y Unix), en general, se les pide a los
usuarios "salir e ingresar otra vez" para que los cambios de configuración surtan efecto. Esto suele
darse porque al instalar un nuevo software o algún otro cambio se han alterado los archivos de
configuración del usuario (o del sistema) bash y las direcciones desearían que el usuario reiniciara
la shell para que los archivos de arranque sean leídos otra vez.

A menudo, los usuarios pueden evitarlo releyendo los archivos clave de configuración en su lugar.
Por ejemplo, si blondie sospecha que un cambio ha ocurrido en el sistema de archivos de arranque
bash, podría leer de modo manual el archivo /etc/profile.

[blondie@station blondie]$ . /etc/profile

De otro modo, si blondie sospecha que sus archivos de arranque locales bash han cambiado,
entonces puede leer su archivo de configuración local bash manualmente.

[blondie@station blondie]$ . ~/.bash_profile

(Observe que esto no funcionaría para todos los cambios de configuración, sino sólo para aquellos
relacionados con la shell bash. Por ejemplo, si una membresía de grupo de usuarios ha cambiado,
entonces el usuario sí tiene que salir e ingresar otra vez para que los cambios surtan efecto)

Ejercicios en línea Lab Exercise Objetivo: Configurar los scripts de arranque bashEstimated
Time: 10 mins.

Especificaciones

1. Agregue la siguiente línea a su archivo de arranque ~/.bashrc.

192
echo "sourcing ~/.bashrc"

2. Agregue la siguiente línea a su archivo de arranque ~/.bashrc.

echo "sourcing ~/.bash_profile"

3. Agregue la siguiente línea a su archivo ~/.bash_logout.

rm -fr ~/.Trash/*

content_view let_
Deliverables A title Question 1

1. Una shell bash que tras el arranque de una shell de no-inicio de sesión emita el mensaje
sourcing ~/.bashrc
2. Una shell bash que tras el arranque de una shell de inicio de sesión emita los mensajes
sourcing ~/.bashrc y sourcing ~/.bash_profile.
3. Una shell bash que tras la salida de una shell de inicio de sesión suprima el contenido (no-
oculto) de la papelera de Nautilus.

193
Standar I/O and Pipes

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 <.

Discussion

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.

194
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 START TIME COMMAND
root 1 0.0 0.0 1380 76 ? S Jun02 0:04 init [
root 2 0.0 0.0 0 0 ? SW Jun02 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Jun02 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Jun02 0:00 [ksoftirqd_CPU0]
root 9 0.0 0.0 0 0 ? SW Jun02 0:00 [bdflush]
root 5 0.0 0.0 0 0 ? SW Jun02 0:00 [kswapd]
root 6 0.0 0.0 0 0 ? SW Jun02 0:00 [kscand/DMA]
root 7 0.0 0.0 0 0 ? SW Jun02 0:37 [kscand/Normal]
root 8 0.0 0.0 0 0 ? SW Jun02 0:00 [kscand/HighMem]

195
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 START TIME COMMAND
root 1 0.0 0.0 1380 76 ? S Jun02 0:04 init [
root 2 0.0 0.0 0 0 ? SW Jun02 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Jun02 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Jun02 0:00 [ksoftirqd_CPU0]
root 9 0.0 0.0 0 0 ? SW Jun02 0:00 [bdflush]
root 5 0.0 0.0 0 0 ? SW Jun02 0:00 [kswapd]
root 6 0.0 0.0 0 0 ? SW Jun02 0:00 [kscand/DMA]
root 7 0.0 0.0 0 0 ? SW Jun02 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.

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 sluggish" sysadmin@example.com

Hey sysadmin...

I'm sending a list of processes that were running when the computer was running
in a separate email.

Thanks! --elvis
.

Cc:

196
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 /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.

197
[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.

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


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 >/tmp/foo

198
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
lrwx------ 1 elvis elvis 64 Sep 13 07:05 2 -> /dev/pts/1
lr-x------ 1 elvis elvis 64 Sep 13 07: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/foo

[1]+ Stopped cat </etc/termcap >/tmp/foo


[elvis@station elvis]$ ps
PID TTY TIME CMD
1368 pts/1 00:00:00 bash
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 07:07 0 -> /etc/termcap
l-wx------ 1 elvis elvis 64 Sep 13 07:07 1 -> /tmp/foo
lrwx------ 1 elvis elvis 64 Sep 13 07: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/foo


[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.

199
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
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".

200
[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.

201
[blondie@station student]$ ftp ftp.kernel.org
Connected to ftp.kernel.org (204.152.189.116).
220 ProFTPD [ftp.kernel.org]
Name (ftp.kernel.org:blondie): anonymous
331 Anonymous login ok, send your complete email address 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 list
drwxr-s--- 2 korg mirrors 4096 May 21 2001 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 list
drwxrws--- 2 korg korg 4096 Mar 18 04:05 RCS
-r--r--r-- 1 korg korg 1963 Oct 4 2001 README
-r--r--r-- 1 korg korg 578 Mar 18 04:04 README_ABOUT_BZ2_FILES
drwxrwsr-x 4 korg korg 4096 Oct 26 2000 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 Kbytes/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, blondie@example.com).

202
[blondie@station blondie]$ cat getreadme.ftp
anonymous
blondie@example.com
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 < getreadme.ftp


Password:Name (ftp.kernel.org:blondie):
?Invalid command
drwxr-s--- 2 korg mirrors 4096 May 21 2001 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 2001 README
-r--r--r-- 1 korg korg 578 Mar 18 04:04 README_ABOUT_BZ2_FILES
drwxrwsr-x 4 korg korg 4096 Oct 26 2000 dist
-r--r--r-- 1 korg korg 1507 Oct 11 2001 index.html
drwxrwsr-x 8 korg korg 4096 Jan 21 2002 linux
drwxrwsr-x 3 korg korg 4096 Mar 24 17:46 scm
drwxrwsr-x 3 korg korg 4096 Oct 11 2001 site
drwxrwsr-x 11 korg korg 4096 Jan 1 2002 software
[blondie@station blondie]$ ls -l README
-rw-rw-r-- 1 blondie blondie 1963 Jun 3 17: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 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.

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

203
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 blondie@example.com

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.ftp


==> .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 < getreadme.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.

204
[madonna@station madonna]$ vmstat 1 60 > stats.txt
[madonna@station madonna]$ head stats.txt
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" with 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

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

205
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.gnuplot

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 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).

206
[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 EDT 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.

Deliverables A title 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":

[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

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 dumb

... 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.

207
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
>&

Discussion

Error estándar (stderr)

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.

208
[elvis@station elvis]$ ls -F /etc/rc.d/
init.d/ rc0.d/ rc2.d/ rc4.d/ rc6.d/ rc.sysinit*
rc* rc1.d/ rc3.d/ rc5.d/ rc.local* rc.sysinit.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.

[elvis@station elvis]$ head -1 /etc/rc.d/* > rcsummary.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

209
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> rcsummary.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

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> rcsummary.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

210
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/* > rcsummary.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/* > rcsummary.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
==> /etc/rc.d/rc.sysinit.rpmsave <==
#!/bin/bash

211
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/* > rcsummary.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/* >& rcsummary.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.

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.

212
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 denied
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> /tmp/foo


/var/spool/mail/elvis

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> /dev/null


/var/spool/mail/elvis

213
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 05: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.

[elvis@station elvis]$ cat /etc/X11/*


cat: /etc/X11/applnk: Is a directory
cat: /etc/X11/desktop-menus: Is a directory
cat: /etc/X11/fs: Is a directory
cat: /etc/X11/gdm: Is a directory
cat: /etc/X11/lbxproxy: Is a directory
#!/bin/sh

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
...

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


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

Deliverables A title Question 1

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/*.

214
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.

Discussion

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>/dev/null


/etc/termcap
/etc/gconf/gconf.xml.defaults/schemas/desktop/gnome/interface/%gconf.xml
/etc/gconf/gconf.xml.defaults/schemas/apps/mailcheck_applet/prefs/%gconf.xml
/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.

215
[prince@station prince]$ find /etc -size +100k 2>/dev/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/gnomemeeting/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
/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
...

216
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 templates | 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/bash
grep: /etc/passwd-: Permission denied
grep: /etc/passwd.lock: Permission denied
...
grep: /etc/sudoers: Permission denied
/etc/termcap:# From: John Doe <jd@princeton.edu>
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".

217
[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/bash
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 Sep22 0:00 /usr/sbin/httpd
apache 907 0.0 0.5 18436 1320 ? S Sep22 0:00 /usr/sbin/httpd
apache 913 0.0 0.7 18436 1952 ? S Sep22 0:00 /usr/sbin/httpd
apache 914 0.0 0.5 18436 1332 ? S Sep22 0:00 /usr/sbin/httpd
apache 1979 0.0 0.5 18360 1524 ? S Sep22 0:00 /usr/sbin/httpd
apache 1980 0.0 0.8 18388 2140 ? S Sep22 0:00 /usr/sbin/httpd
apache 1981 0.0 0.5 18360 1524 ? S Sep22 0:00 /usr/sbin/httpd
prince 4905 0.0 0.2 3572 640 pts/1 S 06:19 0:00 grep httpd

Búsqueda eficaz en el historial de comandos

218
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>/dev/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 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.

219
...
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.

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 //"


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
...

220
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
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.

221
[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 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

222
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. Final del formulario

Limpieza

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

223
String Processing Tools

Herramientas para procesamiento de cadenas de texto

Conteo de palabras y codificación de texto

Conceptos clave

• When storing text, computers transform characters into a numeric representation. This
process is referred to as encoding the text.
• In order to accommodate the demands of a variety of languages, several different encoding
techniques have been developed. These techniques are represented by a variety of
character sets.
• La técnica de codificación más prevalente y antigua se conoce como el conjunto de
caracteres ASCII, el cual sirve aún como el denominador menos común entre otras
técnicas.
• El comando wc cuenta el número de caracteres, palabras y líneas en un archivo. Cuando
se aplica a datos estructurados, el comando wc puede convertirse en una herramienta
versátil de conteo.
• El comando cat tiene opciones que permiten la representación de caracteres de no
impresión tal como el caracter NEWLINE.
• Los comandos head y tail tienen opciones que le permiten imprimir sólo un cierto número
de líneas o un cierto número de bytes de un archivo, (un byte suele correlacionarse con un
caracter).

Discussion

En este cuaderno, comenzamos examinando varias herramientas de búsqueda, clasificación y


manipulación de texto. Puesto que Linux (antes Unix), tiene una tradición muy fuerte de
almacenamiento de datos en formatos legibles por humanos, estas herramientas deberían
considerarse no sólo como ayuda de redacción sino de manipulación de datos en general.

Archivos

¿Qué son archivos?

Linux, like most operating systems, stores information that needs to be preserved outside of the
context of any individual process in files. (In this context, and for most of this Workbook, the term
file is meant in the sense of regular file). Linux (and Unix) files store information using a simple
model: information is stored as a single, ordered array of bytes, starting from at first and ending at
the last. The number of bytes in the array is the length of the file. [1]

What type of information is stored in files? Here are but a few examples.

• The characters that compose the book report you want to store until you can come back
and finish it tomorrow are stored in a file called (say) ~/bookreport.txt.
• The individual colors that make up the picture you took with your digital camera are stored
in the file (say) /mnt/camera/dcim/100nikon/dscn1203.jpg.

224
• The characters which define the usernames of users on a Linux system (and their home
directories, etc.) are stored in the file /etc/passwd.
• The specific instructions which tell an x86 compatible CPU how to use the Linux kernel to
list the files in a given directory are stored in the file /bin/ls.

What is a Byte?

At the lowest level, computers can only answer one type of question: is it on or off? What is it?
When dealing with disks, it is a magnetic domain which is oriented up or down. When dealing with
memory chips, it is a transistor which either has current or doesn't. Both of these are too difficult to
mentally picture, so we will speak in terms of light switches that can either be on or off. To your
computer, the contents of your file is reduced to what can be thought of as an array of (perhaps
millions of) light switches. Each light switch can be used to store one bit of information (is it on, or is
it off).

Using a single light switch, you cannot store much information. To be more useful, an early
convention was established: group the light switches into bunches of 8. Each series of 8 light
switches (or magnetic domains, or transistors, ...) is a byte. More formally, a byte consists of 8 bits.
Each permutation of ons and offs for a group of 8 switches can be assigned a number. All switches
off, we'll assign 0. Only the first switch on, we'll assign 1; only the second switch on, 2; the first and
second switch on, 3; and so on. How many numbers will it take to label each possible permutation
for 8 light switches? A mathematician will quickly tell you the answer is 2^8, or 256. After grouping
the light switches into groups of eight, your computer views the contents of your file as an array of
bytes, each with a value ranging from 0 to 255.

Data Encoding

In order to store information as a series of bytes, the information must be somehow converted into a
series of values ranging from 0 to 255. Converting information into such a format is called data
encoding. What's the best way to do it? There is no single best way that works for all situations.
Developing the right technique to encode data, which balances the goals of simplicity, efficiency (in
terms of CPU performance and on disk storage), resilience to corruption, etc., is much of the art of
computer science.

As one example, consider the picture taken by a digital camera mentioned above. One encoding
technique would divide the picture into pixels (dots), and for each pixel, record three bytes of
information: the pixel's "redness", "greenness", and "blueness", each on a scale of 0 to 255. The
first three bytes of the file would record the information for the first pixel, the second three bytes the
second pixel, and so on. A picture format known as "PNM" does just this (plus some header
information, such as how many pixels are in a row). Many other encoding techniques for images
exist, some just as simple, many much more complex.

Codificación de texto

Perhaps the most common type of data which computers are asked to store is text. As computers
have developed, a variety of techniques for encoding text have been developed, from the simple in
concept (which could encode only the Latin alphabet used in Western languages) to complicated
but powerful techniques that attempt to encode all forms of human written communication, even
attempting to include historical languages such as Egyptian hieroglyphics. The following sections
discuss many of the encoding techniques commonly used in Red Hat Enterprise Linux.

ASCII

225
One of the oldest, and still most commonly used techniques for encoding text is called ASCII
encoding. ASCII encoding simply takes the 26 lowercase and 26 uppercase letters which compose
the Latin alphabet, 10 digits, and common English punctuation characters (those found on a
keyboard), and maps them to an integer between 0 and 255, as outlined in the following table.

Table 1. ASCII Encoding of Printable Characters

Integer Range Caracter


33-47 Puntuación: !"#$%&;*(*+,-./
48-57 Los dígitos de 0 a 9
58-64 Puntuación: :;<=?>@
65-90 Letras mayúsculas de la A hasta la Z
91-96 Puntuación: [\]^_`
97-122 Letras minúsculas de la a hasta la z
123-126 Puntuación: {|}~

What about the integers 0 - 32? These integers are mapped to special keys on early teletypes,
many of which have to do with manipulating the spacing on the page being typed on. The following
characters are commonly called "whitespace" characters.

Table 2. Codificación ASCII de caracteres de espacio en blanco

Número entero Caracter Nombre común Representación común


8 BS Backspace '\b'
9 HT Tab '\t'
10 LF Nueva línea '\n'
12 FF Form Feed '\f'
13 CR Carriage Return '\r'
32 SPACE Space Bar
127 DEL Delete

Others of the first 32 integers are mapped to keys which did not directly influence the "printed
page", but instead sent "out of band" control signals between two teletypes. Many of these control
signals have special interpretations within Linux (and Unix).

Table 3. ASCII Encoding of Control Signals

Número entero Caracter Nombre común Representación común


4 EOT End of Transmission
7 BEL Campana audible de terminal '\a'
27 ESC Escape
Generating Control Characters from the Keyboard
Control and whitespace characters can be generated from the terminal keyboard
directly using the CTRL key. For example, an audible bell can be generated
using CTRL-G, while a backspace can be sent using CTRL-H, and we have
already mentioned that CTRL-D is used to generate an "End of File" (or "End of
Transmission"). Can you determine how the whitespace and control characters
are mapped to the various CTRL key combinations? For example, what CTRL
key combination generates a tab? What does CTRL-J generate? As you explore
various control sequences, remember that the reset command will restore your
terminal to sane behavior, if necessary.

226
What about the values 128-255? ASCII encoding does not use them. The ASCII standard only
defines the first 128 values of a byte, leaving the remaining 128 values to be defined by other
schemes.

ISO 8859 and Other Character Sets

Other standard encoding schemes have been developed, which map various glyphs (such as the
symbol for the Yen and Euro), diacritical marks found in many European languages, and non Latin
alphabets to the latter 128 values of a byte which the ASCII standard leaves undefined. The
following table lists a few of these standard encoding schemes, which are referred to as character
sets. The following table lists some character sets which are supported in Linux, including their
informal name, formal name, and a brief description.

Table 1. Some ISO 8859 Character Sets supported in Linux

Nombre informal Nombre formal Descripción


Latín-1 ISO 8859-1 West European languages
Latin-2 ISO 8859-2 Central and East European languages
Árabe ISO 8859-6 Latin/Arabic
Griego ISO 8859-7 Latín/Griego
Latín-9 ISO 8859-15 West European languages

All of these character encoding schemes use a common technique. They preserve the first 128
values of a byte to encode traditional ASCII, and use the remaining 128 values to encode glyphs
unique to the particular encoding. For example, ISO 8859-1 (Latin-1) uses the value 196 to encode
a Latin capital A with an umlaut (), while ISO-8859-7 (Greek) uses the value 196 to encode the
Greek capital letter Delta (), but both use the value 101 to encode a Latin lowercase e.

Notice a couple of implications about ISO 8859 encoding.

1. Each of the alternate encodings map a single glyph to a single byte, so that the number of
letters encoded in a file equals the number of bytes which are required to encode them.
2. Choosing a particular character set extends the range of characters that can be encoded,
but you cannot encode characters from different character sets simultaneously. For
example, you could not encode both a Latin capital A with a grave and a Greek letter Delta
simultaneously.

Unicode (UCS)

In order to overcome the limitations of ASCII and ISO 8859 based encoding techniques, a Universal
Character Set has been developed, commonly referred to as UCS, or Unicode. The Unicode
standard acknowledges the fact that one byte of information, with its ability to encode 256 different
values, is simply not enough to encode the variety of glyphs found in human communication.
Instead, the Unicode standard uses 4 bytes to encode each character. Think of 4 bytes as 32 light
switches. If we were to again label each permutation of on and off for 32 switches with integers, the
mathematician would tell you that you would need 4,294,967,296 (over 4 billion) integers. Thus,
Unicode can encode over 4 billion glyphs (nearly enough for every person on the earth to have their
own unique glyph; the user prince would approve).

What are some of the features and drawbacks of Unicode encoding?

Scale

227
The Unicode standard will easily be able to encode the variety of glyphs used in human
communication for a long time to come.

Simplicidad

The Unicode standard does have the simplicity of a sledgehammer. The number of bytes
required to encode a set of characters is simply the number of characters multiplied by 4.

Desperdicio

While the Unicode standard is simple in concept, it is also very wasteful. The ability to
encode 4 billion glyphs is nice, but in reality, much of the communication that occurs today
uses less than a few hundred glyphs. Of the 32 bits (light switches) used to encode each
character, the first 20 or so would always be "off".

ASCII Non-compatibility

For better or for worse, a huge amount of existing data is already ASCII encoded. In order
to convert fully to Unicode, that data, and the programs that expect to read it, would have to
be converted.

The Unicode standard is an effective standard in principle, but in many respects it is ahead of its
time, and perhaps forever will be. In practice, other techniques have been developed which attempt
to preserve the scale and versatility of Unicode, while minimizing waste and maintaining ASCII
compatibility. What must be sacrificed? Simplicity.

Formato de transformación Unicode (UTF-8)

UTF-8 encoding attempts to balance the flexibility of Unicode, and the practicality and
pervasiveness of ASCII, with a significant sacrifice: variable length encoding. With variable length
encoding, each character is no longer encoded using simply 1 byte, or simply 4 bytes. Instead, the
traditional 127 ASCII characters are encoded using 1 byte (and, in fact, are identical to the existing
ASCII standard). The next most commonly used 2000 or so characters are encoded using two
bytes. The next 63000 or so characters are encoded using three bytes, and the more esoteric
characters may be encoded using from four to six bytes. Details of the encoding technique can be
found in the utf-8(7) man page. With full backwards compatibility to ASCII, and the same functional
range of pure Unicode, what is there to lose? ISO 8859 (and similar) character set compatibility.

UTF-8 attempts to bridge the gap between ASCII, which can be viewed as the primitive days of text
encoding, and Unicode, which can be viewed as the utopia to aspire toward. Unfortunately, the
"intermediate" methods, the ISO 8859 and other alternate character sets, are as incompatible with
UTF-8 as they are with each other.

Additionally, the simple relationship between the number of characters that are being stored and the
amount of space (measured in bytes) it takes to store them is lost. How much space will it take to
store 879 printed characters? If they are pure ASCII, the answer is 879. If they are Greek or Cyrillic,
the answer is closer to twice that much.

Text Encoding and the Open Source Community

In the traditional development of operating systems, decisions such as what type of character
encoding to use can be made centrally, with the possible disadvantage that the decision is wrong
for some community of the operating system's users. In contrast, in the open source development

228
model, these types of decisions are generally made by individuals and small groups of contributers.
The advantages of the open source model are a flexible system which can accommodate a wide
variety of encoding formats. The disadvantage is that users must often be educated and made
aware of the issues involved with character encoding, because some parts of the assembled
system use one technique while others parts use another. The library of man pages is an excellent
example.

When contributors to the open source community are faced with decisions involving potentially
incompatible formats, they generally balance local needs with an appreciation for adhering to widely
accepted standards where appropriate. The UTF-8 encoding format seems to be evolving as an
accepted standard, and in recent releases has become the default for Red Hat Enterprise Linux.

The following paragraph, extracted from the utf-8(7) man page, says it well:

It can be hoped that in the foreseeable future, UTF-8 will replace


ASCII and ISO 8859 at all levels as the common character encoding on
POSIX systems, leading to a significantly richer environment for han-
dling plain text.

It can be hoped that in the foreseeable future, UTF-8 will replace


ASCII and ISO 8859 at all levels as the common character encoding on
POSIX systems, leading to a significantly richer environment for han-
dling plain text.

Internacionalización (i18n)

As this Workbook continues to discuss many tools and techniques for searching, sorting, and
manipulating text, the topic of internationalization cannot be avoided. In the open source
community, internationalization is often abbreviated as i18n, a shorthand for saying "i-n with 18
letters in between". Applications which have been internationalized take into account different
languages. In the Linux (and Unix) community, most applications look for the LANG environment
variable to determine which language to use.

At the simplest, this implies that programs will emit messages in the user's native language.

[elvis@station elvis]$ echo $LANG


en_US.UTF-8
[elvis@station elvis]$ chmod 666 /etc/passwd
chmod: changing permissions of `/etc/passwd': Operation not permitted
[elvis@station elvis]$ export LANG=de_DE.utf8
[elvis@station elvis]$ chmod 666 /etc/passwd
chmod: Beim Setzen der Zugriffsrechte fr /etc/passwd: Die Operation ist
nicht erlaubt

The LANG environment variable

The LANG environment variable is used to define a user's language, and possibly the default
encoding technique as well. The variable is expected to be set to a string using the following syntax:

LL_CC.enc

229
The variable context consists of the following three components.

Table 1. Components of LANG environment variable

Componente Función
LL Código de lenguaje ISO 639 de dos letras
CC (Optional) Two letter ISO 3166 Country Code
enc (Optional) Character Encoding Code Set

The locale command can be used to examine your current configuration (as can echo $LANG),
while locale -a will list all settings currently supported by your system. The extent of the support for
any given language will vary.

The following tables list some selected language codes, country codes, and code set specifications.

Table 2. Códigos de lenguaje seleccionados ISO 639

Código Lenguaje
de Alemán
el Griego
en Inglés
es Español
fr Francés
ja Japonés
zh Chino

Table 3. Selected ISO 3166 Country Codes

Código País
CA Canadá
CN China
DE Alemania
ES España
FR Francia
GB Britain (UK)
GR Grecia
JP Japón
NG Nigeria
US Estados Unidos

Table 4. Selected Character Encoding Code Sets

Código País
utf8 UTF-8
iso88591 ISO 8859-1 (Latín 1)
iso885915 ISO 8859-15 (Latín 10)
iso88596 ISO 8859-6 (Árabe)
iso88592 ISO 8859-2 (Latín 2)

See the gettext info pages (info gettext, or pinfo gettext) for a complete listing.

230
¿Necesito saber todo esto?

We have tried to introduce the major concepts and components which affect how text is encoded
and stored within Linux. After reading about character sets and language codes, one might be led to
wonder, do I really need to know about all of this? If you are using simple text, restricted to the Latin
alphabet of 26 characters, the answer is no. If you are asking the question 10 years from now, the
answer will hopefully be no. If you do not fit into one of these two categories, however, you should
have at least an acquaintance with the concept of internationalization, character sets, and the role
of the LANG environment variable.

Hopefully, as the open source community converges on a single encoding technique (currently
UTF-8 seems the most likely), most of these issues will disappear. Until then, these are some key
points to remember.

1. Un archivo ASCII ya es válido en uno de los conjuntos de caracteres ISO 8559.


2. Un archivo ASCII ya es válido en UTF-8.
3. A file encoded in one of the ISO 8559 character sets is not valid in UTF-8, and must be
converted.
4. Using UTF-8, There is a one to one mapping between characters and bytes if and only if all
of the characters are pure ASCII characters.

If you are interested in more information, several man pages provide a more detailed introduction to
the concepts outlined above. Start with charsets(7), and then follow with ascii(7), iso_8859_1(7),
unicode(7) and utf-8(7). Additionally, the iconv command can be used to convert text files from
one form of encoding to another.

Volviendo a cat, head y tail

Retomando cat

Hemos estado utilizando el comando cat para simplemente mostrar el contenido de archivos. Por
lo general, el comando cat genera una copia fiel de su entrada, sin modificaciones o conversiones.
Sin embargo, cuando se llama el comando cat con una de las siguientes opciones indicará la
presencia de tabulaciones, avances de línea y otras secuencias de control por medio de las
siguientes convenciones.

Table 1. Opciones para el comando cat

Opción Efecto
-E muestra avances de línea (ASCII 10) como $
-T muestra tabulaciones (ASCII 9) como ^I
-v muestra espacio en blanco y caracteres de control como ^n, con n indicando la secuencia
para el caracter de no impresión CTRL.
-A Muestra "todo", lo mismo que -vET
-t Muestra "todo" excepto avances de línea, lo mismo que -vT
-e Muestra "todo" excepto tabulaciones, lo mismo que -vE

A manera de ejemplo, a continuación el comando cat se utiliza para visualizar el contenido del
archivo de configuración /etc/hosts.

231
[student@station student]$ cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost station.example.com
127.0.0.1 rha-server
192.168.0.1 station1 station1.example.com www1 www1.example.com
192.168.0.51 station51 station51.example.com
192.168.129.201 z

Al utilizar la opción -A, la estructura de espacio en blanco del archivo se hace evidente, al
remplazar las tabulaciones por ^I y los avances de línea son representados por$.

[student@station student]$ cat -A /etc/hosts


# Do not remove the following line, or various programs$
# that require network functionality will fail.$
127.0.0.1^Ilocalhost.localdomain^Ilocalhost station.example.com $
127.0.0.1^Irha-server$
192.168.0.1^Istation1 station1.example.com www1 www1.example.com$
192.168.0.51^Istation51 station51.example.com$
192.168.129.201^Iz$

Retomando head y tail

Los comandos head y tail se han utilizado para visualizar las primeras y úĺtimas líneas de un
archivo, respectivamente. Pero, ¿de qué consta una línea? Imagínese trabajando en una máquina
de escribir: ¡clic! ¡clac! ¡clic! ¡clac! ¡clac! ¡sssiin! En lugar del ¡sssiin! del carro de la máquina al final
de cada línea se selecciona el caracter de avance de línea (ASCII 10) para marcar el final de
líneas.

Hoy en día no se comparte entre todos los sistemas operativos dominantes en uso una sóla
convención para marcar el final de una línea. Linux (y Unix) utilizan el caracter de avance de línea
(ASCII 10, a menudo representado \n), mientras que los sistemas operativos de Macintosh utilizan
el caracter de retorno de carro (ASCII 13, a menudo representado \r o ^M) y los sistemas
operativos de Microsoft utilizan un par de retorno de carro/avance de línea (ASCII 13, ASCII 10).

Por ejemplo, el siguiente archivo contiene una lista de cuatro músicos.

[student@station student]$ cat -A musicians


elvis$
blondie$
prince$
madonna$

Si este archivo fuese creado en un sistema operativo de Microsoft o Macintosh y copiado dentro de
Linux, los archivos se verían de la siguiente manera.

232
[student@station student]$ cat -A musicians.dos
elvis^M$
blondie^M$
prince^M$
madonna^M$
[student@station student]$ cat -A musicians.mac
elvis^Mblondie^Mprince^Mmadonna^M[student@station student]$

Los archivos de texto de Linux (y Unix) por lo general se adhieren a la convención de que el último
caracter del archivo debe ser un avance de línea para la última línea de texto. Siguiendo el cat del
archivo musicians.mac, que no contiene ninguno de los caracteres convencionales de avance de
línea de Linux, el intérprete de comandos bash no se visualiza en el sitio acostumbrado.

Table 1. Opciones para el comando head

Opción Efecto
-N, -nN Muestra las primeras líneas N del archivo.
-cN Muestra los primeros N bytes del archivo.

Table 2. Opciones para el comando tail

Opción Efecto
-N, -nN Muestra las dos últimas líneas N del archivo. Si N se antepone a un + muestra el archivo
restante que comienza en la cuarta línea.
-cN Muestra los primeros N bytes del archivo.

El comando wc (Conteo de palabras)

Forma fácil de conteo

¿Alguna vez ha tratado de contestar un test de “25 palabras o menos”? ¿Alguna vez ha tenido que
escribir un ensayo de 1.500 palabras?

Con wc puede verificar fácilmente que su aporte cumpla con los criterios.

El comando wc cuenta el número de caracteres, palabras y líneas. Tomará su entrada ya sea de


archivos llamados en su línea de comandos o desde su entrada estándar. A continuación verá una
forma de línea de comandos para el programa wc:

Figure 1. Uso del comando wc

Opción Resultados
-c Conteo de caracteres de cómputo.
-l Conteo de línea de cómputo.
-w Conteo de palabras de cómputo.
filename El nombredearchivo que se va a contar. Si no se especifica ningún nombredearchivo,
entonces el texto se leerá desde la entrada estándar. Para mayor claridad, el
nombredearchivo será escrito como la última línea de cada informe de conteo, incluso si
sólo se utiliza sólo un nombredearchivo.

233
Cuando se utiliza sin opciones, wc reportará el número de caracteres, líneas y palabras. Las
opciones pueden combinarse para retornar cualquier combinación de conteo de caracteres, de
líneas o de palabras.

¿Cómo reconocer un caracter real?

Los archivos de texto están compuestos por un alfabeto de caracteres. Algunos caracteres son
visibles, tales como números y letras. Algunos caracteres se utilizan para distancia horizontal tales
como espacios y caracteres TAB. Algunos caracteres se utilizan para movimiento vertical tales
como retornos de carro y avances de línea.

Una línea en un archivo de texto es una serie de cualquier caracter diferente a un caracter
NEWLINE (avance de línea). Las líneas adicionales en el archivo siguen inmediatamente la
primera línea.

Aunque un computador representa caracteres como números, el valor exacto utilizado para cada
símbolo varía dependiendo del alfabeto que se escoja. El alfabeto más utilizado por los hablantes
de inglés es ASCII, también llamado “Latín-1”. Otras lenguas son representadas por reglas de
codificación diferentes, para que el valor numérico exacto para un determinado caracter dependa
del lenguaje humano que se está registrando.

Entonces, ¿qué es una palabra?

Una palabra es un grupo de caracteres de impresión tales como letras y dígitos, rodeados por un
espacio en blanco, tales como caracteres de espacio o caracteres horizontales TAB.

Observe que la definición de una palabra no incluye ninguna noción de “significado”. Sólo la forma
de la palabra es importante, no su semántica. En lo que respecta a Linux, una línea tal como:

Ahora es el momento para que todos utilicen foogle.

contiene 10 palabras perfectamente buenas: caracteres de impresión rodeados por un espacio en


blanco o puntuación.

Ejemplos

Caracteres de conteo

Para contar los caracteres en un archivo ejecute wc -c:

[student@station student]$ echo hello | wc -c


6

Además de las cinco letras en la palabra, la línea también tiene un caracter NL al final.

Los caracteres invisibles también son importantes.

Los caracteres que usted no puede ver también ocupan espacio en un archivo.

234
[student@station student]$ echo Hello, World! > greetings
[student@station student]$ wc -c greetings
14

Tenga en mente también que los espacios y TABs se cuentan como caracteres. ¿Recuerda la
analogía con la máquina de escribir? Tanto el espaciador como el TABULADOR se deben pulsar, a
cada caracter en un archivo de texto le corresponde el golpe de una tecla de una máquina de
escribir.

¿Cuál es mi línea?

Ejecute el comando wc -l para contar las líneas en un archivo:

[student@station student]$ echo First line > foo


[student@station student]$ echo Second line >> foo
[student@station student]$ echo Third line >> foo
[student@station student]$ wc -l foo
3 foo

Las quiero todas

Al utilizar wc sin ningún argumento todo cuenta: caracteres, palabras y líneas:

[student@station station]$ echo one > x


[student@station student]$ echo two words >> x
[student@station student]$ echo three more words >> x
[student@station student]$ wc x
3 6 31 x

Archivos Linux, Dos y Macintosh

¿Cómo manejaría el comando wc los tres archivos de los músicos mencionados anteriormente
(uno escrito en una máquina de Linux, uno en una máquina Microsoft y otro en una Macintosh)?

[student@station student]$ wc musicians*


4 4 29 musicians
4 4 33 musicians.dos
0 4 29 musicians.mac
8 12 91 total

Para el archivo musicians.mac, que no contenía ningun avance de línea convencional de


caracteres Linux, el número de líneas se reporta como 0.

En la salida anterior, ¿por qué el archivo musicians.dos tiene 33 caracteres mientras que musicians
y musicians.mac tienen sólo 29?

Conteo de usuarios

235
El comando wc suele utilizarse para contar el número de cosas, no sólo líneas, palabras y
caracteres. Por ejemplo, el comando users genera una lista de usuarios que están actualmente en
la máquina. La siguiente línea crearía un alias denominado nusers, el cual reportaría el número de
usuarios actualmente en la máquina.

[student@station student]$ alias nusers='users | wc -w'


[student@station student]$ users
student student student student root
[student@station student]$ nusers
5

Procesos de conteo

Al examinar la salida de un comando tal como ps aux, el cual imprime en pantalla información
sobre un proceso por línea, el comando wc -l puede utilizarse para contar el número de procesos
ejecutándose en una máquina. Sin embargo, al examinar la salida de ps aux, la línea inicial que
contiene los títulos en columna debe suprimirse de la cuenta.

[student@station student]$ ps aux


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1384 76 ? S Sep28 0:04 init [
root 2 0.0 0.0 0 0 ? SW Sep28 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Sep28 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Sep28 0:00
[ksoftirqd_CPU0]
...

El comando tail, con su habilidad para imprimir el remanente de un archivo iniciando a partir de
una línea especificada, puede suprimirse de la línea de encabezado.

[student@station student]$ ps aux | tail +2


root 1 0.0 0.0 1384 76 ? S Sep28 0:04 init [
root 2 0.0 0.0 0 0 ? SW Sep28 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Sep28 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN Sep28 0:00
[ksoftirqd_CPU0]
root 9 0.0 0.0 0 0 ? SW Sep28 0:00 [bdflush]
...

El siguiente script corto combina ps aux, tail +2 y wc para crear un nuevo comando llamado
nprocs. Cuando se hace ejecutable y se coloca en el directorio ~/bin (el cual es parte de una
búsqueda estándar ejecutable PATH), el script queda disponible desde la línea de comandos.

236
[student@station student]$ cat nprocs
#!/bin/bash

ps aux | tail +2 | wc -l
[student@station student]$ mkdir bin
[student@station student]$ mv nprocs bin
[student@station student]$ chmod a+x bin/nprocs
[student@station student]$ nprocs
86

Ejercicios en línea Lab Exercise Objetivo: Usar el comando wc como herramienta de conteo.
Estimated Time: 10 mins.

Especificaciones

1. Cree el archivo ~/gplwords.txt que contenga el número de palabras (como fue reportado
por el comando wc) en el archivo /usr/share/doc/redhat-release-4ES/GPL como su única
palabra.
2. Cree el archivo ~/localusers.txt, el cual contiene el número de usuarios localmente
definidos como su única palabra.
3. Las bibliotecas compiladas estáticamente de modo convencional se encuentran en el
directorio/usr/lib y tienen nombres que comienzan por lib y terminan en la extensión .a.
Cree el archivo ~/usrlibs.txt que contenga el número de los archivos cuyo nombre siga esta
convención en el directorio /usr/lib como su única palabra (no incluya subdirectorios).
4. Crear un script ejecutable llamado~/bin/nrecent. El script debería esperar un solo
argumento, el cual es un nombre de un directorio. Tras la ejecuación, el script debería
retornar un solo número, el cual es el número de archivos en el directorio modificados en
las últimas 24 horas. El script no debería generar mensajes de error de los directorios en el
flujo de error estándar.

Si usted ha implementado los ejercicios de modo correcto, debería poder reproducir una salida
semejante a la siguiente (no se preocupe si sus números reales difieren de los listados abajo).

[student@station student]$ head *.txt


==> gplwords.txt <==
2009

==> localusers.txt <==


89

==> usrlibs.txt <==


216
[student@station student]$ nrecent /var/log

Deliverables A title Question 1

1. Un archivo llamado ~/gplwords.txt que contiene el número de palabras halladas en el


archivo /usr/share/doc/redhat-release-4ES/GPL.
2. Un archivo llamado ~/localusers.txt que contiene el número de los usuarios localmente
definidos en el sistema de Linux.

237
3. Un archivo llamado ~/usrlibs.txt que contiene el número de archivos que comienzan por lib
y terminados en .a que se encuentran en el directorio /usr/lib.
4. Un script ejecutable llamado ~/bin/nrecent, que espera el nombre de un directorio como su
único argumento. Tras la ejecución, el script devolvería un solo número el cual es el
número de archivos bajo el directorio especificado modificados en las últimas 24 horas. El
script no debe retornar mensajes de error sobre directorios en el flujo de error estándar.

Ayudas

Para el archivo ~/localusers.txt recuerde que los usuario locales están definidos en el archivo
/etc/passwd, un usuario por línea.

Para el script ~/bin/nrecent recuerde que $1 desreferencia un argumento del script bash. Considere
el utilizar el comando find para generar una lista de archivos coincidentes con los criterios y luego
cuente el número de líneas (o palabras) en la salida. Usted podría desear utilizar los directorios /etc
o /var/log para probar su script.

238
Búsqueda de Texto: grep

Conceptos clave

• grep es un comando que imprime en pantalla líneas coincidentes con un patrón de una
cadena de texto especificado.
• grep suele utilizarse como filtro para reducir salida a sólo lo deseado.
• grep -r buscará de modo recursivo bajo un directorio determinado.
• grep -v imprime líneas NO coincidentes con una cadena o patrón de texto.
• Muchas de las opciones permiten a los usuarios especificar el formato de salida de grep.

Discussion

Búsqueda de contenido de archivo de texto con el comando grep

En una lección anterior, vimos cómo el programa wc puede utilizarse para contar los caracteres,
palabras y líneas en archivos de texto. En esta lección presentamos el programa grep, una
herrramienta útil para la búsqueda de palabras específicas o secuencias de caracteres en el
contenido de archivo de texto.

El nombre grep representa en inglés general regular expression parser. Usted puede preguntarse,
¿qué es una expresión regular y ¿por qué razones usted quisiera analizar una expresión regular
sintácticamente? Daremos una definición más formal de las expresiones regulares en una lección
posterior, pero por ahora es suficiente saber que una expresión regular es simplemente una forma
de describir un patrón o plantilla, para hacer coincidir con alguna secuencia de caracteres. Una
expresión regular sencilla sería “Hello”, la cual coincide exactamente con cinco caracteres: “H”, “e”,
dos caracteres consecutivos “l” y un caracter “o” final. Patrones de búsqueda de mayor alcance son
posibles y los examinaremos en la siguiente sección.

La figura de abajo da una idea general de la línea de comandos grep:

Figure 1. Forma de los comandos grep

Hay en realidad tres nombres diferentes para la herramienta grep [1]:

fgrep

Hace una búsqueda rápida de patrones simples. Utilice este comando para localizar
rápidamente patrones sin caracteres comodines, útil para buscar una palabra común.

grep

Búsqueda de patrones con expresiones regulares comunes.

egrep

239
Búsqueda de patrones con expresiones regulares extendidas de gran alcance.

El argumento del patrón proporciona caracteres de plantillas que grep debe buscar. Se espera que
el patrón sea un solo argumento, por lo tanto si el patrón contiene espacios u otros caracteres
especiales de la shell, usted debe encerrar el patrón entre comillas para evitar que la shell lo
expanda o lo divida.

El cuadro a continuación resume algunas de las opciones más utilizadas de grep. Consulte la
página del manual grep(1) (o invoque grep --help) para mayor información.

Table 1. Opciones para el comando grep

Opción Efecto
-c Imprime un conteo de las líneas coincidentes únicamente.
-h Suprime prefijos de nombres de archivos.
-e Utiliza expresión como un patrón de búsqueda, (útil para especificar varios patrones
expresión alternos).
-i Ignora las mayúsculas o minúsculas al determinar coincidencias.
-l Imprime nombres de archivos que contienen solo un patron coincidente.
-n Incluye números de línea a lo largo de las líneas coincidentes.
-q "Quieto" No escriba nada a la salida estándar. En su lugar, salga con un estatus de
salida cero si encuentra algún archivo coincidente.
-r Busca todos los archivos de modo recursivo a través de directorios.
-w Sólo coincide con palabras completas.
-C Incluye dos líneas de contexto antes y después de la línea coincidente.

Muestra todas las ocurrencias de una cadena de texto en un archivo

En Linux, hay varias formas de realizar la misma tarea. Por ejemplo, para ver si un archivo contiene
la palabra “even”, podría tan solo examinar visualmente el archivo:

[student@station student]$ cat file


This file has some words.
It also has even more words.

Al leer el archivo, vemos que sí contiene las letras “even”. Al emplear este método en un archivo
grande se sufre porque podemos fácilmente perder una palabra en un archivo de varios miles o
incluso cientos de miles de palabras. Podemos utilizar la herramienta grep para que nos busque el
archivo de una forma automática:

[student@station student]$ grep even file


It also has even more words.

Aquí buscamos una palabra con su deletreo exacto. En lugar de buscar una cadena de texto literal,
el argumento del patrón puede también ser una plantilla general para coincidir con secuencias de
caracteres más complicadas, eso lo veremos con detenimiento en una próxima lección.

Búsqueda de varios archivos al mismo tiempo

240
Una forma fácil para buscar varios archivos es nombrarlos en la línea de comandos grep:

[student@station student]$ echo Every cat has one more tail than no cat.
> general
[student@station student]$ echo No cat has nine tails. > specific
[student@station student]$ echo Therefore, every cat has ten tails. >
fallacy
[student@station student]$ grep cat general specific fallacy
general:Every cat has one more tail than no cat.
specific:No cat has nine tails.
fallacy:Therefore, every cat has ten tails.

Quizás estemos más interesados en descubrir el archivo que menciona la palabra “nine” que en ver
la línea misma. Al añadir la opción -l a la línea grep hace justo eso:

[student@station student]$ grep -l nine general specific fallacy


specific

Búsqueda de directorios de modo recursivo

Grep también puede buscar con un solo comando todos los archivos en un árbol de directorio
completo. Esto puede ser útil si trabajamos con un gran número de archivos.

La forma más fácil de entender esto es verlo en acción. En el directorio /etc/sysconfig hay tres
archivos de texto que contienen mucha de la información de configuración del sistema de Linux. El
nombre Linux para el primer dispositivo de red de Ethernet en un sistema es “eth0”, usted puede
buscar qué archivo contiene la configuración para eth0 al permitirle al comando grep -r hacer la
búsqueda por usted[1]:

[student@station student]$ grep -r eth0 /etc/sysconfig 2>/dev/null


/etc/sysconfig/network-scripts/ifup-aliases:# Specify multiple ranges
using \
multiple files, such as ifcfg-eth0-range0 and
/etc/sysconfig/network-scripts/ifup-aliases:# ifcfg-eth0-range1, etc. In
these \
files, the following configuration variables
/etc/sysconfig/network-scripts/ifup-aliases:# The above example values
create \
the interfaces eth0:0 through eth0:253 using
/etc/sysconfig/network-scripts/ifup-ipv6:# Example: \
IPV6TO4_ROUTING="eth0-:f101::0/64 eth1-:f102::0/64"
/etc/sysconfig/network-scripts/ifcfg-eth0:DEVICE='eth0'
/etc/sysconfig/networking/devices/ifcfg-eth0:DEVICE='eth0'
/etc/sysconfig/networking/profiles/default/ifcfg-eth0:DEVICE='eth0'

Cada archivo en /etc/sysconfig que mencione eth0 aparece en los resultados.

Podemos más adelante limitar los archivos listados a sólo aquellos que se refieran al dispositivo
real, filtrando la salida de grep -r a través de un grep DEVICE:

241
[student@station student]$ grep -r eth0 /etc/sysconfig 2>/dev/null |
grep DEVICE
/etc/sysconfig/network-scripts/ifcfg-eth0:DEVICE='eth0'
/etc/sysconfig/networking/devices/ifcfg-eth0:DEVICE='eth0'
/etc/sysconfig/networking/profiles/default/ifcfg-eth0:DEVICE='eth0'

Esto muestra un uso común de grep como filtro para simpl¡ficar las salidas de otros comandos.

Si solamente los nombres fueran de interés, la salida podría simplificarse con la opción -l.

[student@station student]$ grep -rl eth0 /etc/sysconfig 2>/dev/null


/etc/sysconfig/network-scripts/ifup-aliases
/etc/sysconfig/network-scripts/ifup-ipv6
/etc/sysconfig/network-scripts/ifcfg-eth0
/etc/sysconfig/networking/devices/ifcfg-eth0
/etc/sysconfig/networking/profiles/default/ifcfg-eth0

Inversión de grep

La herramienta grep muestra por defecto sólo las líneas coincidentes con el patrón de búsqueda.
Esto suele ser lo deseado, pero algunas veces se puede tener interés en las líneas no coincidentes
con el patrón. En estas instancias, la opción -v invierte el funcionamiento de grep.

[student@station student]$ head -n 4 /etc/passwd


root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin
adm:x:3:4:adm:/var/adm:
[student@station student]$ grep -v root /etc/passwd | head -n 3
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin:
adm:x:3:4:adm:/var/adm:

Obtención de números de línea

Usted puede estar buscando con frecuencia un archivo grande que tiene varias ocurrencias del
patrón. Grep listará cada línea que contiene una o más coincidencias, ¿pero cómo se hace para
localizar aquellas líneas en el archivo original? Utilizando el comando grep -n también listará el
número de cada línea coincidente.

El archivo /usr/share/dict/words contiene una lista de palabras comunes de diccionario. Identifique


qué línea contiene la palabra “dictionary”:

[student@station student]$ fgrep -n dictionary /usr/share/dict/words


12526:dictionary

242
También podría querer combinar la opción -n con la opción-r al buscar en los siguientes archivos
de directorio:

[student@station station]$ fgrep -nr dictionary /usr/share/dict


linux.words:12526:dictionary
words:12526:dictionary

Límite de coincidencias con palabras completas

¿Recuerda el archivo anterior que contenía nuestra rima infantil?

[student@station student]$ cat rhyme


The cat
sat on
the mat
at home.

Suponga que queremos recuperar todas las líneas que contienen la palabra “at”. Si ensayamos el
comando:

[student@station student]$ fgrep at rhyme


The cat
sat on
the mat
at home.

¿Ve lo que sucedió? Hicimos coincidir con la cadena de texto“at” ya sea que fuera una palabra
aislada o parte de una palabra más grande. El comando grep proporciona la opción -w para
implicar que el patrón especificado sólo debería coincidir con palabras enteras.

[student@station student]$ grep -w at file


at home.

La opción -w considera como una palabra a una secuencia de letras, números y caracteres de
subrayado, rodeados por cualquier otra cosa.

Ignorar mayúsculas o minúsculas

La cadena “Bob” tiene un significado bastante diferente a la cadena “bob”. Sin embargo, algunas
veces queremos encontrar cualquiera sin importarnos si la palabra está en mayúsculas o no. El
comando grep -i resuelve justo este problema.

Examinemos otra vez nuestra rima infantil:

243
[student@station student]$ cat rhyme
The cat
sat on
the mat
at home.

Vea si el archivo que contiene la palabra “the”, está todo en minúsculas:

[student@station student]$ grep the rhyme


the mat

Ahora observe qué líneas contienen las letras “t”, “h” y “e” en cualquier combinación de letras
mayúsculas y minúsculas:

[student@station student]$ grep -in the rhyme


1:The cat
3:the mat

Observe que también utilizamos la opción -n para agregar los números de línea a la salida.

Ejemplos

Búsqueda de cadenas sencillas de caracteres

Verifique que su computador tenga la cuenta del sistema “lp”, utilizada por la línea de herramientas
de impresión. Ayuda: el archivo /etc/passwd contiene una línea por cada cuenta de usuario en el
sistema.

[student@station student]$ grep lp /etc/passwd


lp:x:4:7:lp:/var/spool/lpd:

En esa clase de letra

Búsqueda de una copia exacta del patrón:

[student@station student]$ grep LP /etc/passwd


[student@station student]$

Nada coincidió debido a que el patrón no coincidió con el tipo de letra para el nombre de cuenta.
Busque de nuevo ignorando las mayúsculas y minúsculas:

[student@station student]$ grep -i LP /etc/passwd


lp:x:4:7:/var/spool/lpd:

244
Palabras completas coincidentes

Hemos visto que grep coincidirá con el patrón siempre que el patrón esté situado, incluso en medio
de palabras. Busque el patrón“honey” en el diccionario de palabras del sistema
/usr/share/dict/words:

[student@station student]$ grep honey /usr/share/dict/words


honey
honeybee
honeycomb
honeycombed
honeydew
honeymoon
honeymooned
honeymooner
honeymooners
honeymooning
honeymoons
honeysuckle
Mahoney

Es evidente que el diccionario contiene varias palabras con la cadena “honey” como una palabra
root. Podemos limitarnos a hacer coincidir un montón de palabras utilizando el comando grep -w.
El comando grep considera que una palabra es un grupo de letras, dígitos o caracteres de
subrayado rodeados por cualquier otra cosa. El comienzo y fin de una línea también clasifica como
“cualquier otra cosa”, por lo tanto la primera y última palabra en una línea se reconoce
correctamente. De nuevo, trate de buscar“honey” en el diccionario:

[student@station student]$ grep -w honey /usr/share/dict/words


honey

A falta de una mejor palabra: perfecto.

Combinar grep y xargs

Suponga que se le ha encargado de mantener la documentación del archivo de ayuda para el


editor vim. Mientras navega a través de los archivos existentes, observa que en algunos archivos
de ayuda se utilizan las dos palabras línea de comandos y en otros sitios una sola palabra
líneadecomandos. Usted quisiera que sus archivos de ayuda sean consistentes y decide que la
anterior es la correcta.

Usted desearía ahora buscar cada ocurrencia del textocommandline y cambiarla por command line.
Comienza por identificar los archivos que contienen el texto commandline.

245
[student@station student]$ grep -ril commandline /usr/share/doc/vim*
/usr/share/doc/vim-common-6.1/docs/message.txt
/usr/share/doc/vim-common-6.1/docs/options.txt
/usr/share/doc/vim-common-6.1/docs/os_risc.txt
/usr/share/doc/vim-common-6.1/docs/tags
/usr/share/doc/vim-common-6.1/docs/todo.txt
/usr/share/doc/vim-common-6.1/docs/various.txt
/usr/share/doc/vim-common-6.1/docs/version5.txt

Usted desearía abrir cada uno de estos archivos en el editor de texto gedit para hacer sus
modificaciones. Entuba los resultados de su búsqueda en el comando gedit.

[student@station student]$ grep -ril commandline /usr/share/doc/vim* | gedit

El editor gedit se abre, pero con un buffer vacío llamado"sin título". ¡Esto no es lo que quería!
Usted quería que gedit abriera los nombres de archivo provistos por el comando grep en la
entrada estándar, no la entrada estándar misma. Sin embargo, así funciona gedit. gedit (al igual
que la mayoría de los editores de texto) espera que los nombres de archivo estén provistos de
argumentos en la línea de comandos, no mediante la entrada estándar.

Afortunadamente, existe la utilidad estándar de Linux (y Unix): xargs, la cual ayuda justo en
situaciones como éstas. El comando xargs leerá la entrada estándar y añadirá las palabras
encontradas en la línea de comandos provista, a manera de argumentos adicionales. Esperemos
que el siguiente ejemplo lo aclare. Con su conocimiento acerca del comando xargs modifique su
método anterior.

[student@station student]$ grep -ril commandline /usr/share/doc/vim* |


xargs gedit

Ahora, el editor gedit se abre con múltiples memorias inmediatas, una para cada salida de archivo
con el comando grep.

Figure 1. Uso de xargs para convertir la entrada estándar en argumentos para gedit

Observe que nunca ha tenido que teclear nombres de archivos individuales. Las palabras provistas
en la entrada estándar fueron intercambiadas por argumentos en la línea de comandos, para esto
sirve el nombre xargs. ¡Muy útil!

Ejercicios en línea Lab Exercise Objetivo: Usar el comando grep para buscar ocurrencias de
texto específico. Estimated Time: 10 mins.

Especificaciones

1. Crear el archivo ~/bashusers.txt que contenga las líneas del archivo /etc/passwd que
contengan el texto /bin/bash.
2. Crear el archivo~/nostdhome.txt que contenga sólo líneas desde el archivo /etc/passwd
que no contengan el texto home (implicando que el usuario asociado tiene un directorio de
inicio no estándar).

246
3. Crear el archivo ~/ansiterms.txt que contenga cada línea del archivo /etc/termcap que
contenga el texto ansi, utilizando una búsqueda insensible a las mayúsculas y minúsculas,
(en otras palabras, ansi, ANSI, Ansi y AnSi todas coincidirían).
4. Crear el archivo ~/mayhemnum.txt que contenga el número de la línea de la palabra
mayhem del archivo /usr/share/dict/words como su única palabra.
5. Crear el archivo ~/firstredhat.txt que contenga un listado clasificado en orden alfabético de
todos los archivos bajo el directorio /usr/share/firstboot (y sus subdirectorios) que
contengan el texto redhat, utilizando una búsqueda que no tenga en cuenta las mayúsculas
y minúsculas. Los archivos deben listarse uno por línea mediante referencias absolutas.

Deliverables A title Question 1

1. El archivo ~/bashusers.txt que contenga líneas del archivo /etc/passwd que contengan el
texto /bin/bash.
2. El archivo ~/nostdhome.txt que contenga líneas del archivo /etc/passwd que no contengan
el textohome.
3. El archivo ~/ansiterms.txt que contenga cada línea del archivo /etc/termcap que contenga
el texto ansi, mediante una búsqueda sin tener en cuenta las mayúsculas y minúsculas.
4. El archivo ~/mayhemnum.txt que contenga el número de línea de la palabra mayhem del
archivo /usr/share/dict/words como su única palabra.

247
Introducción a las expresiones regulares

Conceptos clave

• Las expresiones regulares son una sintaxis estándar de Unix para especificar los patrones
de texto.
• Las expresiones regulares son entendidas por muchos comandos incluyendo grep, sed, vi
y varios lenguajes de escritura.
• Dentro de las expresiones regulares, . y [] se utilizan para coincidir caracteres.
• Dentro de las expresiones regulares, +, * y? especifican un número de ocurrencias
consecutivas.
• Dentro de las expresiones regulares ^ y $ especifican el comienzo y el final de una línea.
• Dentro de las expresiones regulares, (, ) y| especifican grupos alternativos.
• La página del manual regex (7) proporciona detalles completos.

Discussion

Introducción de expresiones regulares

En el capítulo anterior se describió grep para coincidir una parte o toda una palabra. Esto de por sí
es poderoso especialmente junto con otros argumentos como -i y -v, pero no es apropiado para
todos los escenarios de búsqueda. A continuación se presentan algunos ejemplos de búsquedas
que la herramienta grep que hemos estudiado hasta el momento no puede realizar:

Primero, suponga que usted tuviera un archivo como éste:

[biafra@station]$ cat people_and_pets.txt


==========================
Name: Joe Green
Age: 36
Pets:
Name: Aida
Age: 5
Species: Cat
------------
Name: Hawn
Age: 1
Species: Goldfish

==========================
Name: Sarah Jane
Age: 29
Pets:
Name: Orfeus
Age: 7
Species: Dog
-------------
Name: Euridice
Age: 8
Species: Dog

248
¿Qué sucedería si quisiera sacar únicamente los nombres de las personas en
people_and_pets.txt? Un comando como grep -w Name: coincidiría con el 'Name:' línea para cada
persona, pero también el 'Name:' línea para cada mascota de las personas. ¿Cómo podríamos
hacer coincidir sólo el 'Name:' líneas para las personas? Observe que las líneas para nombres de
mascotas tienen todas sangría, lo que significa que esas líneas comienzan por caracteres de
espacio en blanco en lugar de texto. Entonces, podríamos realizar una meta si tuviéramos una
forma de decir "Muéstreme todas las líneas comenzadas por 'Name:'".

Otro ejemplo: suponga que usted y un amigo suyo vieron un accidente de auto. Ambos vieron el
número de la placa del auto que se escapó, sin embargo, cada uno recuerda el número con
algunas diferencias. Usted leyó el número de la placa como "4I35VBB", pero su amigo leyó
"413SV88". Parece que usted leyó como una 'I' el segundo caracter y su amigo lo leyó como un '1'.
Diferencias similares aparecen en sus interpretaciones de otras partes de la placa como '5' en lugar
de 'S' y 'BB' en lugar de '88'. Habiendo tomado ambas declaraciones, la policía necesita ahora
acortar la lista de los sospechosos consultando su base de datos con las placas que puedan
coincidir con las que ustedes vieron.

Una solución podría ser realizar peticiones por separado para "4I35VBB" y "413SV88", pero al
hacer esto se asume que uno de ustedes estaba en lo cierto. ¿Qué sucedería si el número de la
placa del causante del accidente fuera realmente "4135VB8"? En otras palabras, qué sucedería si
usted tuviera algunos caracteres correctos, pero su amigo tuviera otros correctos? Sería más
efectivo si la policía pudiera preguntar por un patrón que efectivamente dijera: "Muéstreme todos
los números comenzados por un '4', seguidos por una 'I' o por un '1', seguido por un '3', seguido
por un '5' o una 'S', seguido por una 'V', seguido por dos caracteres que sean una 'B' o un '8'".

Escenarios como estos se pueden resolver utilizando expresiones regulares. Aunque los científicos
informáticos algunas veces utilizan el término "expresión regular " (o "regex" para acortar) para
describir cualquier método de descripción de patrones complejos, en Linux y muchos lenguajes de
programación, el término se refiere a un conjunto de caracteres muy específico utilizado para
resolver problemas como el anterior. Las expresiones regulares son compatibles con un gran
número de herramientas incluyendo grep, vi, find y sed.

Para introducir el uso de expresiones regulares, veamos algunas soluciones a dos problemas
descritos anteriormente. No se preocupe si estos parecen un poco complicados, el resto de la
unidad comenzará desde el principio y cubrirá expresiones regulares detalladamente.

Una regex que pueda resolver el primer problema, donde queríamos decir "Muéstreme todas las
líneas que comienzan por 'Name:'" podría verse así:

[biafra@station]$ grep '^Name:' people_and_pets.txt


Name: Joe Green
Name: Sarah Jane

...eso es! Las expresiones regulares tienen que ver con el uso de caracteres especiales llamados
metacaracteres para representar parámetros de búsqueda avanzada. El acento circunflejo ("^"),
como se muestra aquí significa "Líneas que comienzan por...". A propósito, observe que la
expresión regular está en comillas sencillas. Es un buen hábito entrar pronto porque así se evita
que bash interprete caracteres especiales destinados para grep.

Está bien, ¿entonces qué pasa con el segundo problema? Este último involucra una pregunta un
poco más compleja: "Muéstreme todos los números de placas que comienzan por '4', seguido por
una 'I' o un '1', seguido por un '3', seguido por un '5' o una 'S', seguida por una 'V', seguido por dos
caracteres que sean una 'B' o un '8'". Esto podría representarse con una expresión regular así:

249
4[I1]3[5S]V[B8]{2}

¡Oh! es bastante corta si consideramos el tiempo que nos tomó escribir lo que estamos buscando!
Hay sólo dos tipos de metacaracteres regex utilizados aquí: los paréntesis cuadrados ('[]') y los
paréntesis curvos ('{}'). Cuando dos o más caracteres se muestran dentro de paréntesis significa
"cualquiera de estos". Entonces '[B8]' cerca del final de la expresión significa "'B' u '8'". Cuando un
número se muestra sin ningún paréntesis curvo significa "estos cuantos del caracter anterior". Por
lo tanto, '[B8]{2}' significa "dos caracteres que sean una 'B' o un '8'". ¡Un argumento bastante
convincente!

Ahora que sabe el significado y la utilidad de las expresiones regulares, comencemos desde el
principio y cubrámoslas a fondo.

Expresiones Regulares, expresiones regulares extendidas y comando grep

Como la implementación de sintaxis de expresiones regulares de Unix ha evolucionado, se han


introducido nuevos caracteres. Con el fin de preservar compatibilidad con los anteriores, los
comandos suelen escoger implementar las expresiones regulares o expresiones regulares
extendidas. Con el fin de no estancarse con las diferencias, esta lección describirá la sintaxis
extendida, resumiendo las diferencias al final de la discusión.

Uno de los usos más comunes para expresiones regulares es especificar patrones de búsqueda
para el comando grep. Como lo mencionamos en una lección anterior, hay tres versiones del
comandogrep. Reiterando, los tres difieren en la manera de interpretar expresiones regulares.

fgrep

El comando fgrep está diseñado para ser un grep "rápido". El comando fgrep no soporta
expresiones regulares, pero en su lugar interpreta cada caracter en un patrón de búsqueda
especificado literalmente.

grep

El comando grep interpreta cada patrón mediante la sintaxis básica original de expresión
regular.

egrep

El comando egrep interpreta cada patrón mediante la sintaxis expresión regular extendida.

Dado que no estamos distinguiendo entre una sintaxis de expresión regular básica y una
extendida, el comando egrep debería utilizarse cada vez que el patrón de búsqueda contenga
expresiones regulares.

Anatomía de una expresión regular

En nuestra discusión de la familia de programas de grep, se nos introdujo la idea de utilizar un


patrón para identificar el contenido del archivo de interés. Nuestros ejemplos fueron
cuidadosamente construídos para que el patrón contuviera exactamente el texto que estábamos
buscando. Fuimos cautelosos al utilizar sólo caracteres literales en sus expresiones regulares; un
caracter literal coincide únicamente consigo mismo. Entonces cuando utilizamos un “hello” como

250
una expresión regular, estábamos utilizando una expresión regular de cinco caracteres. Aunque
esto nos permitió concentrarnos en cómo operar el programa grep, no nos permitió obtener una
apreciación completa del poder de las expresiones regulares. Antes de ver las expresiones
regulares, primero deberíamos ver cómo están construídas.

Una expresión regular es una secuencia de:

Caracteres literales

Los caracteres literales coinciden únicamente con ellos mismos. Las letras, dígitos y la
mayoría de los caracteres son ejemplos de caracteres literales (vea a continuación las
excepciones).

Comodines

Los caracteres comodines coinciden con cualquier caracter. Dentro de una expresión, un
punto (“.”) coincide con cualquier caracter, ya sea un espacio, una letra, un dígito,
puntuación, cualquier cosa.

Modificadores

Un modificador altera el significado del caracter patrón precedente inmediato. Por ejemplo,
la expresión “ab*c” coincide con cadenas de texto “ac”, “abc”, “abbc”, “abbbc” y así
sucesivamente porque el asterisco (“*”) es un modificador que significa “cualquier número
de (incluyendo cero)”. De esta manera, nuestro patrón significa coincidir con cualquier
secuencia de caracteres que conste de una “a”, (posiblemente vacía) un conjunto de
caracteres “b” y un caracter final “c”.

Anclas

Las anclas establecen el contexto para el patrón tal como "el comienzo de una línea" o "el
final de una palabra". Por ejemplo, la expresión “cat” coincidiría con cualquier ocurrencia
de las tres letras mientras que “^cat” sólo coincidirían con las líneas que comienzan por
“cat”.

Cada una de éstas se tratará en más detalle en las siguientes secciones.

Interpretación de los caracteres literales de modo literal

Los literales son directos porque cada caracter literal en una expresión regular coincide con una y
sólo con una copia de sí mismo en el texto examinado. Los caracteres en mayúsculas se
distinguen de los caracteres en minúsculas para que “A” no coincida con “a”.

Comodines

El comodín "punto"

El caracter “.” se utiliza como un marcador para coincidir con algún caracter. En el siguiente
ejemplo, el patrón coincide con cualquier ocurrencia de los caracteres literales “x” y “s” separados
exactamente por dos caracteres.

251
[student@station student]$ grep "x..s" /usr/share/dict/words | head -5
antitoxins
axers
axles
axons
boxers

Expresiones entre paréntesis: intervalo de caracteres literales

Normalmente un caracter literal en un patrón regex coincide exactamente con una ocurrencia de sí
mismo en el texto examinado. Suponga que queremos buscar una cadena de texto “hello” sin
importar las mayúsculas: queremos hacer coincidir “Hello” y “HeLLo” también. ¿Cómo podríamos
hacer esto?

Una característica de regex llamada una expresión entre paréntesis resuelve el problema
claramente. Una expresión de paréntesis es un intervalo de literales encerrados entre paréntesis
cuadrados (“[” y “]”). Por ejemplo, el patrón regex “[Hh]” es una variedad de caracteres que
coinciden exactamente con uno: ya sea en “H” mayúscula o o en “h” minúscula. Observe que no
importa qué tan grande es el conjunto de caracteres dentro de un intervalo, el conjunto coincide
exactamente con un caracter, si éste coincide con alguno. Una expresión entre paréntesis
coincidente con el conjunto de vocales en minúsculas podría escribirse “[aeiou]” y coincidiría
exactamente con una vocal.

En el siguiente ejemplo, las expresiones entre paréntesis se utilizan para buscar palabras desde el
archivo /usr/share/dict/words. En el primer caso, las primeras cinco palabras que contienen tres
vocales consecutivas (en minúsculas) son impresas en pantalla. En el segundo caso, se imprimen
las primeras 5 palabras que contengan minúsculas en el patrón de vocal-consonante-vocal-
consonante-vocal-consonante.

Si el primer caracter de una expresión entre paréntesis es “^”, la interpretación se invierte y la


expresión entre paréntesis coincidirá con cualquier ocurrencia de un caracter no incluido en el
intervalo. Por ejemplo, la expresión “[^aeiou]” coincidiría con cualquier caracter que no sea una
vocal. El siguiente ejemplo primero lista palabras que consten de tres vocales consecutivas y luego
lista palabras que consten de tres consonantes-vocales.

[student@station student]$ egrep '[aeiou][aeiou][aeiou]'


/usr/share/dict/words
| head -5
absenteeism
Achaean
Achaeans
acquaint
acquaintance
[student@station student]$ egrep '[aeiou][^aeiou][aeiou][^aeiou][aeiou]
[^aeiou]'
/usr/share/dict/words | head -5
abased
abasement
abasements
abases
abasing

252
Intervalo de expresiones versus clases de caracteres: vieja y nueva escuela

Otra forma de expresar un intervalo de caracteres es dar letras de arranque y final de la secuencia
de esta forma: “[a-d]” coincidiría con cualquier caracter del conjunto a, b, c o d. Un uso típico de
esta forma sería “[0-9]” para representar cualquier dígito sencillo o “[A-Z]” para representar todas
las letras mayúsculas.

¿Cómo se ordenan los caracteres? Por ejemplo, ¿la“C” mayúscula, va antes o después de “b”
minúscula? Recuerde la discusión acerca del caracter de codificación en la primera lección. El
valor codificado de la letra se utiliza para determinar si un caracter es "menor" o "mayor" que otro.
Mientras el conjunto de caracteres que define la codificación sea ordenado correctamente, como
en el caso de ASCII, todo está bien. Pero, ¿qué pasa con el conjunto de caracteres latino -1
(ISO-8859-1) ? ¿Es verdad que “” va después de “z”?

Como una alternativa a estos dilemas, la expresión regular moderna hace uso de las clases de
caracter. Las clases de caracter coinciden con cualquier caracter sencillo, utilizando convenciones
específicadas de lenguaje para decidir si determinado caracter es letra mayúscula o minúscula o si
debería considerarse como parte del alfabeto o como puntuación. El siguiente cuadro lista algunas
de las clases de caracteres y la expresión equivalente en el intervalo ASCII donde es apropiado.

Table 1. Clases de caracteres de expresiones regular

Expresión Clase de caracter Intervalo ASCII


equivalente
[:alnum:] alfanumérico A-Za-z0-9
[:alpha:] caracter alfabético A-Za-z
[:blank:] espacio o tabulación
[:digit:] dígito numérico 0-9
[:lower:] Letras minúsculas a-z
[:punct:] caracteres imprimibles, excluyendo espacios y
alfanuméricos
[:space:] caracter de espacio en blanco
[:upper:] letra mayúscula A-Z

Las clases de caracteres evitan problemas que se encuentran al usar expresiones regulares en
sistemas que utilizan diferentes esquemas de codificación de caracteres en donde las letras son
ordenadas de modo diferente. Por ejemplo, suponga que usted fuera a ejecutar el comando:

[elvis@station]$ grep '[A-Z]' /usr/share/dict/words

En un sistema de Red Hat Enterprise Linux, cada palabra coincidiría en el archivo, pero no sólo
aquellas que contengan mayúsculas como puede asumirse. Esto se debe a que en unicode (utf-8),
el esquema de codificación de caracteres que RHEL utiliza, están ordenados alfabéticamente sin
importar las mayúsculas o minúsculas para que [A-Z] sea equivalente a [AaBbCc...etc]. Sin
embargo, en sistemas menos recientes se utiliza un sistema de esquema de codificación de
caracteres diferente en donde el orden alfabético dado es sensible a las mayúsculas y minúsculas.
En dichos sistemas [A-Z] sería equivalente a [ABC...etc]. Las clases de caracteres evitan este
error. Usted puede ejecutar:

[elvis@station]$ grep '[[:upper:]]' /usr/share/dict/words

253
en cualquier sistema sin importar el esquema de codificación que se esté utilizando y sólo
coincidiría con las líneas que contengan mayúsculas.

Para mayor información acerca de los intervalos de expresiones predefinidas consulte la página
grep del manual. Para mayor información en esquemas de codificación de caracteres bajo Linux,
refiérase al capítulo 8.3. Si quiere aprender acerca de cómo se utilizan los esquemas de
codificación de caracteres para soportar otros idiomas en Red Hat Enterprise Linux, comience por
la página del manual locale.

Caracteres modificadores comunes

Vimos un uso común del modificador regex en nuestro ejemplo reciente “ab*c” para coincidir con
un caractera y c con algún número de letras b intermedias. El caracter “*” cambió la interpretación
del caracter literal b de coincidir exactamente con una letra a coincidir con cualquier número de b.

Listado de algunos de los caracteres modificadores comunes:

b?

El signo de interrogación final (“?”) significa “uno o ninguno”: el caracter literal se considera
como opcional en el texto examinado. Por ejemplo, el patrón regex “ab?c” coincide con las
cadenas de texto “ac” y “abc”, pero no con “abbc”.

b*

El modificador asterisco (“*”) significa “cualquier número (incluyendo cero)” del caracter
literal precedente. El patrón regex “ab*c” coincide con las cadenas de texto “ac”, “abc”,
“abbc” y así sucesivamente.

b+

El modificador más (“+”) significa “uno o más”, por lo tanto el patrón regex “b+” coincide
con una secuencia de no-espacio vacío de b. El patrón regex “ab+c” coincide con las
cadenas de texto “abc” y “abbc” pero no coincide con “ac”.

b{m,n}

El modificador de paréntesis se utiliza para especificar un intervalo entre las ocurrencias m


y n del caracter precedente. El patrón regex “b{2,4}” coincidiría con “abbc” y “abbbc” y
“abbbbc”, pero no con “abc” o “abbbbbc”.

b{n}

Con sólo un número entero, el modificador de paréntesis se utiliza para especificar


exactamente n occurrencias para el caracter precedente.

En el siguiente ejemplo, egrep imprime líneas desde /usr/share/dict/words que contienen patrones
que comienzan con una (letra mayúscula o minúscula) “a”, luego podría o no tener una
“b”(minúscula), pero luego sin duda, seguida por una “a” (minúscula).

254
[student@station student]$ egrep '[Aa]b?a' /usr/share/dict/words | head
-5
Aarhus
Aaron
Ababa
aback
abaft

El siguiente ejemplo imprime líneas que contienen patrones que comienzan por“al”, luego usan el
comodín “.” para especificar 0 o más ocurrencias de cualquier caracter, seguidas por el patrón
“bra”.

[student@station student]$ egrep 'al.*bra' /usr/share/dict/words | head


algebra
algebraic
algebraically
algebras
calibrate
calibrated
calibrates
calibrating
calibration
calibrations

Observe que hallamos variaciones en las palabras algebra y calibrate. Para la anterior, la expresión
.* coincidió con “ge” mientras que la última coincidió con la letra “i”.

La expresión “.*”, la cual se interpreta como "0 o más de cualquier caracter", aparece a menudo en
patrones regex, actuando como la "goma elástica " dentro de dos patrones importantes.

Notemos que los caracteres modificadores son ambiciosos: siempre quieren coincidir con la
cadena de texto más larga posible. Por ejemplo, dado el patrón regex:

t.*e

y el flujo de salida:

ahora es el momento

nuestro patron coincide con:

el tiempo

En lugar de sólo “the”. Cuando se utiliza para búsquedas tales como grep, la diferencia suele ser
insignificante. Sin embargo, cuando las expresiones regulares se utilizan para buscar y remplazar
operaciones, como se hace con muchos editores, la diferencia se vuelve importante.

255
Búsquedas de anclaje

Cuatro modificadores de caracteres de búsqueda disponibles:

^foo

Un acento circunflejo (“^”) coincide con el comienzo de una línea. Nuestro ejemplo, “^foo”
coincide con la cadena de texto“foo” sólo cuando está al comienzo de la línea.

foo$

Un signo de dólar (“$”) coincide con el final de una línea. Nuestro ejemplo “foo$” coincide
con la cadena de texto “foo” sólo al final de la línea inmediatamente antes del caracter
newline.

\<foo\>

Solos, los signos menor que (“<”) y mayor que (“>”) son literales. Al usar el caracter de
barra invertida para escaparlos significan “primero de una palabra ”y “fin de una palabra”,
respectivamente. De esta manera el patrón “\>cat\<” coincide con la palabra “cat”, pero no
con la palabra “catalog”.

Usted verá con frecuencia tanto^ como$ utilizados juntos. El patrón regex “^foo$” coincide con una
línea entera que contiene sólo “foo” y no coincidiría con la línea si ésta contuviera espacios.

\< y \> también suelen utilizarse como pares.

En el siguiente ejemplo, la primera búsqueda lista todas las líneas que contienen las letras “ion” en
cualquier parte de la línea. La segunda, lista sólo líneas que terminen en “ion”.

[student@station student]$ egrep ion /usr/share/dict/words | head -5


abbreviation
abbreviations
abduction
abductions
aberration
[student@station student]$ egrep 'ion$' /usr/share/dict/words | head -5
abbreviation
abduction
aberration
abjection
ablation

Aceptación de la agrupación Regex

De la misma manera que usted utiliza los paréntesis para agrupar términos dentro de una
expresión matemática, también utiliza paréntesis para recopilar especificadores de patrones de
expresiones regulares dentro de grupos. Esto le permite a los caracteres modificadores “?”, “*” y “+”

256
aplicarse a los grupos de especificadores de regex en lugar de sólo inmediatamente al
especificador anterior.

Suponga que necesitamos una expresión regular para coincidir ya sea con “foo” o “foobar”.
Podríamos escribir la regex como “foo(bar)?” y obtener los resultados esperados. Esto le permite al
modificador “?” aplicar toda la cadena de texto “bar” en lugar de únicamente al caracter precedente
“r”.

La agrupación de especificadores regex mediante paréntesis se hace aún más flexible cuando se
utiliza el símbolo de tubería (“|”) para separar patrones alternativos. Al utilizar alternativas,
podemos volver a escribir nuestro ejemplo anterior como “(foo|foobar)”. Escribir esto como “foo|
foobar” es más sencillo y funciona de la misma manera, porque al igual que en matemáticas, los
especificadores regex tienen prioridad. Mientras usted esté aprendiendo, siempre encierre los
grupos entre paréntesis.

En el siguiente ejemplo, el primero busca lineas impresas en el archivo /usr/share/dict/words, el


cual contiene cuatro vocales consecutivas (compare la sintaxis con la utilizada anteriormente al
presentar el intervalo de expresiones). La segunda búsqueda encuentra palabras que contengan
una doble “o”o, una doble “e”, seguida (en alguna parte) de una doble “e”.

[student@station student]$ egrep '[aeiou]{4}' /usr/share/dict/words |


head -5
aqueous
dequeue
dequeued
dequeues
dequeuing
[student@station student]$ egrep '(o|e){2}.*ee' /usr/share/dict/words
bookkeeper
bookkeepers
bookkeeping
Chattahoochee
doorkeeper
freewheel
Greentree

Escape de Metacaracteres

Algunas veces usted necesita coincidir un caracter que comúnmente sería interpretado como un
comodín para una expresión regular o un caracter modificador. Para inhabilitar temporalmente el
significado especial de estos caracteres, simplemente escápelos mediante el caracter de barra
inversa (“\”). Por ejemplo, el patrón regex “cat.” coincidiría con las letras “cat” seguidas por
cualquier caracter: “cats” o “catchup”. Para coincidir sólo con las letras “cat.” al final de una oración,
utilice el patrón regex “cat\.” para inhabilitar el periodo de interpretación como un caracter comodín.

Observe una molesta excepción a esta regla. Cuando el caracter de barra inversa precede a “<” o
al caracter “>”, éste habilita la interpretación especial (fijando el comienzo o el final de una palabra)
en lugar de inhabilitar la interpretación especial. ¡Ni pensar en lo que pasará! Pero puede ser peor-
vea la nota de pie de página en la parte inferior del siguiente cuadro.

Resumen de la sintaxis de expresiones regulares de Linux

257
El cuadro siguiente resume la sintaxis de expresiones regulares e identifica los componentes
hallados en la sintaxis de expresión regular básica y en la sintaxis de expresiones regulares
extendidas.

Table 1. Resumen de la sintaxis de expresiones regulares de Linux

Caracter Función Sintaxis RegexInterpretación


. comodín básico coincide con cualquier caracter
[abc], [a-z] intervalo de básico coincide con cualquier caracter incluido en
inclusión un intervalo
[^abc], [^a- intervalo de básico coincide con cualquier caracter no incluido
z] exclusión en el intervalo
? modificador extendido coincide con 0 ó 1 del término precedente
* modificador básico coincide con 0 o más del término
precedente
+ modificador extendido coincide con 1 o más del término anterior
{m,n} modificador extendido coincide con ocurrencias dentro dem y n
(inclusive) del término precedente
{n} modificador extendido coincide exactamente con ocurrencias n
del término precedente
^ ancla básico señala el comienzo de una línea
$ ancla básico marca el final de una línea
\< ancla básico señala el comienzo de una palabra
\> ancla básico señala en final de una palabra
(...) agrupación básico permite a los modificadores actuar en un
grupo de caracteres
(... | ...) agrupación extendido permite que los patrones alternos sean
especificados
\ escapa [a] extendido escapa (o permite) la interpretación
(básico) especial del caracter siguiente.
[a]
Cuando se utilizan las expresiones regulares extendidas, la barra inversa suele quitar la
interpretación especial del caracter siguiente. Red Hat Enterprise Linux utiliza extensiones
GNU cuando analiza sintácticamente las expresiones básicas regulares, pero utiliza la barra
inversa para permitir interpretaciones ampliadas del caracter siguiente. Por ejemplo, la
expresión “e\{3\}” coincidiría con “eee” cuando se utilicen expresiones regulares. ¡Da
escalofrío!

Las expresiones regulares NO son comodines de archivos

Al encontrar expresiones regulares por primera vez se entiende que los estudiantes confundan las
expresiones regulares con la expansión del nombre de ruta (comodín de archivos). Ambos se
utilizan para hacer coincidir patrones en texto. Ambas comparten metacaracteres similares (“*”, “?”,
“[...])”, etc.). Sin embargo, son bien diferentes. El siguiente cuadro compara y contrasta expresiones
regulares y comodines de archivos.

Table 1. Comparación y contraste de expresiones regulares y comodines de archivo

Expresiones regulares Comodines de archivo


Implementado dentro de la búsqueda, busca y Implementado por la shell bash para coincidir
remplaza utilidades tales comogrep, vi, sed y nombres de archivos y disminuir la extensión
muchos lenguajes de escritura tales como se encuentra en algunas aplicaciones y
perl, python, etc. lenguajes de escritura.
Utiliza la expresión “.*” para goma elaśtica. Utiliza la expresión “*” para goma elaśtica.

258
Utiliza la expresión “.” para coincidir Utiliza la expresión “?” para coincidir
exactamente con cualquier caracter. exactamente con cualquier caracter.

En el siguiente ejemplo, el primer argumento es una expresión regular especificando texto que
comienza por “l” y terminando en “.conf”, mientras que el segundo argumento es un comodín de
archivo que especifica todos los archivos en el directorio /etc cuyo nombre de archivo comienza por
“l” y termina en “.conf”.

[student@station student]$ egrep 'l.*\.conf' /etc/l*.conf


/etc/ldap.conf:# @(#)$Id: 087_warning.dbk,v 1.2 2004/01/07 16:39:53 bowe
Exp $
/etc/libuser.conf:# Set this only if it differs from the default in
/etc/krb5.conf.
/etc/ltrace.conf:; ltrace.conf

Observe de cerca la segunda línea de salida. ¿Por qué fue emparejada por la expresión regular
especificada?

En un esfuerzo similar en vano, al especificar las expresiones regulares en la línea de comandos


bash, se debe tener cuidado al poner entre comillas o escapar los metacaracteres regex no sea
que se expandan por medio de la shell bash con resultados inesperados. En todos los ejemplos de
este análisis, el primer argumento al comando egrep está protegido con comillas justo por esta
razón.

En dónde encontrar mayor información sobre las expresiones regulares

Apenas hemos tocado el tema de la utilidad de las expresiones regulares. La explicación provista
será adecuada a sus necesidades diarias, pero aún así, las expresiones regulares ofrecen mucho
más poder, al facilitar búsquedas de texto aún mas complicadas.

Para mayor información en línea sobre las expresiones regulares consulte:

• La página de manual regex(7).


• La página de manual grep(1).

Ejemplos

Búsquedas literales

Ahora que entendemos las expresiones regulares en mayor detalle volvamos a ver algunos
ejemplos anteriores con una nueva perspectiva.

Dado el archivo rhyme que contiene el texto:

[student@station student]$ cat rhyme


The cat sat on the mat at home.

La expresión regular “at” coincide con:

259
• el at en “cat” y
• el at en “mat” y
• el at en “at”.

La expresión regular “\<at\>” sólo coincide con la palabra individual “at”.

Intervalo de expresiones

Un intervalo de expresiones coincide exactamente con una instancia de cualquiera de los


caracteres listados por el intervalo de expresión.

[student@station student]$ echo bar > file


[student@station student]$ echo car >> file
[student@station student]$ echo far >> file
[student@station student]$ echo are >> file
[student@station student]$ grep '[cf]ar' file
car
far

El intervalo de expresión “[cf]ar” coincide con una c o con una f seguida por “ar”.

Modificadores REGEX

Los modificadores controlan cuántas ocurrencias del especificador anterior regex coinciden:

[student@station student]$ echo ac > file


[student@station student]$ echo abc >> file
[student@station student]$ echo abbc >> file
[student@station student]$ echo abbbc >> file

El signo de interrogación (?) coincide exactamente con una ocurrencia del especificador
precedente, si éste existe.

[student@station student]$ egrep 'ab?c' file


ac
abc

El signo más (+) coincide con uno o más de los especificadores precedentes:

[student@station station]$ egrep 'ab+c' file


abc
abbc
abbbc

El asterisco (*) coincide con cualquier número, incluyendo cero, de ocurrencias del especificador
precedente:

260
[student@station student]$ egrep 'ab*c' file
ac
abc
abbc
abbbc

Búsquedas de anclaje

Las búsquedas de anclaje se utilizan para hallar coincidencias entre el comienzo y el final de la
línea de entrada.

[student@station student]$ echo "i am sam" > file


[student@station student]$ echo "sam i am" >> file
[student@station student]$ echo "am i sam" >> file
[student@station student]$ echo "sam" >> file
[student@station student]$ cat file
i am sam
sam i am
am i sam
sam
[student@station student]$ egrep '^sam' file
sam i am
[student@station student]$ egrep 'sam$' file
i am sam
am i sam
sam
[student@station student]$ egrep '^sam$' file
sam

Donde ^ y $ se fijan a las líneas, las anclas \< y \> coinciden con el comienzo y el final de las
palabras:

[student@station student]$ egrep '\<am\>' file


i am sam
sam i am
am i sam

Agrupación del término REGEX

Utilice paréntesis para agrupar varios especificadores regex dentro de una sóla unidad. Utilice el
símbolo de tubería (“|”) para indicar alternativas.

Suponga que estamos escribiendo una carta en inglés. Podríamos escribir una expresión regular
para coincidir con la línea de saludo como esta:

^Dear (Dr|Mr|Ms)\.

261
Esto coincidiría con las líneas:

Dear Dr. Smith


Dear Mr. Smith
Dear Ms. Smith

pero no coincidirían con un saludo tal como:

Dear Miss Smith

Quizás el saludo no coincidió porque olvidamos agregar el punto después de la abreviatura. Este
patrón regex coincidiría de la siguiente manera:

^Dear (Dr|Mr|Ms)\.?

Ya sea que el punto esté presente o no.

¿Está elvis en la casa?

La usuaria blondie quisiera crear un guión que revise si alguien está definido como un usuario local
en un sistema Linux. El guión toma un argumento, el cual se espera sea un nombre de usuario.
Ella podría utilizar el comando id para confirmar si existe un usuario llamado username, pero el
comando id incuiría usuarios que podrían definirse por un servidor NIS o algún otro tipo de base de
datos de acceso a la red, en lugar de la máquina local. Ella en su lugar, decide examinar
directamente la base de datos local del usuario (el archivo/etc/passwd).

Crea el siguiente script.

[blondie@station blondie]$ cat inhouse


#!/bin/bash

if [ ! $# == '1' ]; then
echo "usage: inhouse USERNAME"
exit 1
fi

if grep -q "^$1:" /etc/passwd; then


echo "$1 is in the house."
else
echo "$1 is not in the house."
fi

En esta estanza, el script asegura que se haya pasado exactamente un argumento.


Esta línea contiene la expresión regular de interés. El comando grep buscará la línea que
comienza con el argumento rastreado por “:”. Recordando la estructura del archivo
/etc/passwd, los nombres de usuario cumplen estas condiciones.

262
Al grabar el archivo y hacerlo ejecutable, blondie ensaya el guión en el usuario elvis (existente) y
en el usuario barney (no existente).

[blondie@station blondie]$ mv inhouse bin/


[blondie@station blondie]$ chmod a+x bin/inhouse
[blondie@station blondie]$ inhouse elvis
elvis is in the house.
[blondie@station blondie]$ inhouse barney
barney is not in the house.

Búsqueda de números telefónicos

La combinación de expresiones regulares y el comando grep crea una herramienta de gran


alcance para extraer las deseadas pepitas de oro de las grandes cantidades de información. A
continuación, elvis recuerda haber visto un número telefónico en alguna parte del directorio
/usr/share/doc, pero no recuerda dónde. Comienza un proceso de búsqueda por todos los números
telefónicos dentro del directorio /usr/share/doc (que en este caso contiene cerca de 12.000
archivos).

Comienza por observar el hecho que los número de los Estados Unidos tienen al menos 7 dígitos,
por convención escritos con los primeros tres dígitos separados de los últimos cuatro ya sea con un
“-” o con un espacio, tal como 555-1212 o 555 1212. Comienza por buscar dicho patrón de modo
recursivo a través de todos los archivos en el directorio /usr/share/doc.

[elvis@station doc]$ egrep -r '[[:digit:]]{3}(-| )[[:digit:]]{4}' .


./hwdata-0.75/COPYING: 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
./hwdata-0.75/COPYING: Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
./libart_lgpl-2.3.11/COPYING: 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
...

Después de observar las primeras pocas líneas, elvis nota que su patrón regex es demasiado
general. Está buscando todos los códigos postales como también los números telefonónicos.
Refina su patrón de búsqueda especificando que cualquier caracter precedente o de rastro no debe
ser un número.

[elvis@station doc]$ egrep -r '[^[:digit:]][[:digit:]]{3}(-| )[[:digit:]]{4}


[^[:digit:]]' .
./libjpeg-6b/README:642-4900, or from Global Engineering Documents at (800) 854-
7179. (ANSI
./libjpeg-6b/README: phone (408) 944-6300, fax (408) 944-6314
./bash-2.05b/article.ms:\f(CRgnu@prep.ai.mit.edu\fP or call \f(CR+1-617-876-3296\fP
./esound-0.2.28/esound.ps:7 w(5)p Black 0 TeXcolorgray 795 1077 a Fm(esd)p Black
./esound-0.2.28/esound.ps:7 w(5)p Black 0 TeXcolorgray 795 1168 a(esdctl)p Black
./esound-0.2.28/esound.ps:0 TeXcolorgray 596 1554 a Fk(4.)20
b(Miscellaneous)d(Information)p
./esound-0.2.28/esound.ps:7 w(9)p Black 0 TeXcolorgray 795 1665 a Fm(New)k(Featu
r)o(es)p
...

263
Esta vez, la búsqueda de elvis precede mucho mejor, hasta que él toque el archivo esound.ps.
Este archivo contiene PostScript, el cual por rutina utiliza números escritos en texto ASCII para
especificar coordenadas. Al saber que no estaba examinando un archivo PostScript, elvis diseña
una forma de excluir todos los archivos terminados en la extensión .ps desde su búsqueda.
Primero utiliza el comando find para listar cada archivo en el directorio. Luego la salida de grep a
todos los archivos no terminados en .ps. Entonces utiliza el comando xargs para alimentar estos
nombres de archivos dentro de su comando original grep como argumentos. Puesto que sus
archivos están siendo especificados de modo individual la línea de comandos ya no necesita
utilizar grep de modo recursivo.

[elvis@station doc]$ find . | egrep -v '\.ps$' | xargs egrep


'[^[:digit:]][[:digit:]]{3}(-| )[[:digit:]]{4}[^[:digit:]]'
./libjpeg-6b/README:642-4900, or from Global Engineering Documents at (800) 854-
7179. (ANSI
./libjpeg-6b/README: phone (408) 944-6300, fax (408) 944-6314
./bash-2.05b/article.ms:\f(CRgnu@prep.ai.mit.edu\fP or call \f(CR+1-617-876-3296
\fP
./gawk-3.1.1/README_d/README.solaris:# P.O. Box 354 Home Phone: +972
8 979-0381 Fax: +1 603 761-6761
./gawk-3.1.1/README_d/README.solaris:Columbus, Ohio 43210-1174 1-614
-292-5310 (Office/Answering Device)
...
Después de observar unas cuanta líneas más de la salida, elvis se da cuenta que debería también
excluir de su búsqueda los archivos terminados en .figy .pdf, ya que pueden contener muchos
números ASCII y estan bloqueando su salida. Al modificar la expresión regular en su primer
comando grep, elvis repite su búsqueda.

[elvis@station doc]$ find . | egrep -v '\.(ps|fig|pdf)$' |


xargs egrep -h -C2 '[^[:digit:]][[:digit:]]{3}(-| )[[:digit:]]{4}
[^[:digit:]]'
...

Ahora que la búsqueda parece ir bien, elvis revisa la salida formateando y pidiéndole a grep no
mostrar los nombres de archivos y dar 2 líneas de contexto alrededor de cada número telefónico.

264
[elvis@station doc]$ find . | egrep -v '\.(ps|pdf|fig)$' |
xargs egrep -h -C2 '[^[:digit:]][[:digit:]]{3}(-| )[[:digit:]]{4}[^[:digit:]]'
it's much cheaper and includes a great deal of useful explanatory material.)
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
doesn't take credit card orders, but Global does.) It's not cheap: as of
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
--
1778 McCarthy Blvd.
Milpitas, CA 95035
phone (408) 944-6300, fax (408) 944-6314
A PostScript version of this document is available by FTP at
ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
--
The Free Software Foundation sells tapes and CD-ROMs
containing Bash; send electronic mail to
\f(CRgnu@prep.ai.mit.edu\fP or call \f(CR+1-617-876-3296\fP
for more information.
.PP
--
# --
# Aharon (Arnold) Jones arnold@sleeve.com [ <<=== NOTE: NEW
ADDRESS!! ]
# P.O. Box 354 Home Phone: +972 8 989-0381 Fax: +1 603 761-6761
# Nof Ayalon Cell Phone: +972 51 227-545 (See www.efax.com)
# D.N. Shimshon 97784 Laundry increases exponentially in the
--
The Ohio State University http://www.math.ohio-state.edu/~nevai/
231 West Eighteenth Avenue http://www.math.ohio-state.edu/~jat/
Columbus, Ohio 43210-1174 1-614-292-5310 (Office/Answering Device)
The United States of America 1-614-292-1479 (Math Dept Fax)

--

,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,
Joe Farwell | phone 610-843-6020 | Platinum technology
Systems Administrator | vmail 800-123-9096 x7512 | 620 W. Germantown Pike
joe@platinum.com | fax 610-872-6021 | Plymouth Meeting,Pa,19462
'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'
delay needs to be calibrated using outside sources.
...

Observe que los nombres y números han sido alterados en esta salida.

Elvis termina con 289 " coincidencias " las cuales puede revisar en un tiempo razonable.

Ejercicios en línea Lab Exercise Objetivo: Usar expresiones regulares para buscar patrones de
texto.Tiempo estimado: 45 minutos.

Especificaciones

1. Crear un ejecutable pequeño de un script bash llamado ~/bin/ispython, que espera un


argumento sencillo, el cual es un nombre de archivo. Si la primera línea del nombre de
archivo proporcionada es exactamente“#!/usr/bin/python” (nada más, nada menos), el

265
script debería imprimir en pantalla el número 1. De lo contrario, el script debería imprimir en
la pantalla el número 0.
2. Usted está buscando archivos en el directorio /etc (pero no en subdirectorios) que
contengan un número estándar de larga distancia en los Estados Unidos, escrito mediante
el patrón 1-###-###-####, donde cada # es remplazado por un dígito numérico. Recopile
los nombres de archivos de cada archivo en el directorio /etc que contenga dicho patrón de
números y colóquelos en el archivo ~/etcphone.txt, un archivo por línea, clasificado en
orden alfabético, usando referencias absolutas.
3. El archivo /usr/share/doc/bash-*/NEWS contiene muchas listas detalladas, con los
elementos de la lista marcados por líneas cuyos caracteres sean una serie de una o más
letras, seguidas por un punto y un espacio como a continuación:

y. New prompting expansions: \a, \e, \H, \T, \@, \v, \V.

z. Variable expansion in prompt strings is now controllable via a shell


option (shopt prompt vars).

aa. Bash now defaults to using command-oriented history.

bb. The history file ($HISTFILE) is now truncated to $HISTFILESIZE after


being written.

 Crear los siguientes archivos, cada uno conteniendo el número que contesta la pregunta
especificada como su palabra única.

filename pregunta
newsitems.txt ¿Cuántas líneas comienzan por una serie de una o máś letras seguidas por un
punto?
newsitems23.txt ¿Cuántas líneas comienzan por una serie de dos o tres letras seguidas por un
punto?
newsitems2.txt ¿Cuántas líneas comienzan por una serie exacta de dos letras seguidas por un
punto?
newsitems3.txt ¿Cuántas líneas comienzan por una serie exacta de tres letras, seguidas por un
punto?

4. El archivo /usr/share/dict/words contiene una colección de palabras de diccionario


comunes, almacenadas una por línea. Tanto las palabras comunes como los nombres
propios están incluidos, cada uno en mayúsculas.

Al utilizar el comando egrep, determine qué palabras comienzan con una letra mayúscula
seguida únicamente por vocales. No incluya palabras de una sola letra., (para propósitos de este
ejercicio, considere las vocales como sólo las letras A, E, I, O o U tanto en mayúsculas como en
minúsculas.)

Liste estas palabras, una por línea y clasifíquelas en orden alfabético en el archivo ~/vowel2.txt.

content_view let_
Deliverables A title Question 1

1. Un script llamado ~/bin/ispython, que al ejecutarse con un solo nombre de archivo como
argumento, imprimirá en pantalla 1 si la primera línea del archivo es exactamente #!/usr/bin/
python. De lo contrario, el scripts imprimiría 0 (ayuda: esto puede realizarse combinando los

266
comandos head ygrep).
2. El archivo ~/etcphone.txt, que contiene una lista de todos los archivos en el directorio /etc
(no en subdirectorios) que contienen el patrón 1-###-###-####, donde cada # se remplaza
por un número digital. Los archivos deberían listarse como referencias absolutas, una por
línea en orden alfabético.
3. Los archivos ~/newsitems.txt, ~/newsitems23.txt, ~/newsitems2.txt y ~/newsitems3.txt, cada
uno de los cuales contiene un solo número como su única palabra. El número debería ser
la respuesta a la pregunta respectiva acerca del archivo /usr/share/doc/bash-*/NEWS en el
cuadro anterior.

4. El archivo ~/vowel2.txt, que contiene un listado clasificado en orden alfabético de todas las
palabras en /usr/share/dict/words que comienzan con una mayúscula y seguidas de solo
vocales (excluya las palabras de una sola letra).

267
Ordenando todo: sort y uniq

Conceptos clave

• El comando sort clasifica datos en orden alfabético.


• sort -n ordena numéricamente.
• sort -u clasifica y suprime duplicados.
• sort -k y -t clasifica en un campo específico en datos en patrones.

Discussion

En cuadernos anteriores hemos presentado el comando sort en su forma más sencilla: una
herramienta para ordenarr las líneas de un archivo o salida desde un comando en orden alfabético.
Esta lección presentará el comando sort en más detalle.

El comando sort

Clasificación básica

La clasificación es el proceso de arreglar los registros en una secuencia específica. Ejemplos de


clasificación sería el arreglar una lista de nombres de usuario dentro de un orden alfabético o una
serie de archivos de diferentes tamaños en orden numérico.

En su forma más simple, el comando sort clasificará en orden alfabético líneas (incluyendo
cualquier espacio en blanco o caracteres de control hallados). El comando sort utiliza la definición
local de locale (definición de lenguaje) para determinar el orden de caracteres (conocido como
orden de recopilación). En el siguiente ejemplo, madonna muestra primero el contenido del archivo
/etc/sysconfig/mouse tal como está, y luego, clasifica el contenido del archivo en orden alfabético.

[madonna@station madonna]$ cat /etc/sysconfig/mouse


FULLNAME="Generic - 2 Button Mouse (PS/2)"
MOUSETYPE="ps/2"
XEMU3="yes"
XMOUSETYPE="PS/2"
DEVICE=/dev/psaux
[madonna@station madonna]$ sort /etc/sysconfig/mouse
DEVICE=/dev/psaux
FULLNAME="Generic - 2 Button Mouse (PS/2)"
MOUSETYPE="ps/2"
XEMU3="yes"
XMOUSETYPE="PS/2"

Si se llama con argumentos, los argumentos se interpretan (en lo posible) como nombres de
archivos para ser clasificados. Si se llama sin argumento, el comando sort clasificará lo que lea de
la entrada estándar.

Modificación del orden de clasificación

268
Por defecto, el comando sort clasifica líneas en orden alfabético. El siguiente cuadro lista las
opciones que pueden utilizarse para modificar el orden de clasificación predeterminado.

Table 1. Opciones para especificar el orden de clasificación

Opción Efecto
-b, --ignore-leading-blanks Ignora espacios y tabulaciones al comienzo de una línea.
-d, --dictionary-order Considere solamente los caracteres en blanco y los alfanuméricos.
-f, --ignore-case Trate a todos los caracteres como mayúsculas.
-g, --general-numeric-sort Compare palabras como números de punto flotante.
n, --numeric-sort Compare palabras como números enteros.
-r, --reverse Clasifique en orden descendente en vez de en orden ascendente.

A manera de ejemplo, madonna está examinando los tamaños de archivo de todos los archivos
que comienzan por unam en el directorio /var/log.

[madonna@station madonna]$ ls -s1 /var/log/m*


20 /var/log/maillog
3104 /var/log/maillog.1
1552 /var/log/maillog.2
1952 /var/log/maillog.3
1236 /var/log/maillog.4
4 /var/log/messages
384 /var/log/messages.1
636 /var/log/messages.2
216 /var/log/messages.3
560 /var/log/messages.4

Luego clasifica la salida con el comando sort.

[madonna@station madonna]$ ls -s /var/log/m* | sort


1236 /var/log/maillog.4
1552 /var/log/maillog.2
1952 /var/log/maillog.3
20 /var/log/maillog
216 /var/log/messages.3
3104 /var/log/maillog.1
384 /var/log/messages.1
4 /var/log/messages
560 /var/log/messages.4
636 /var/log/messages.2

Sin habérsele dicho, el comando sort clasificó las líneas en orden alfabético (con 1.952 saliendo
antes de 20). Al darse cuenta que esto no era lo que buscaba, madonna agrega la opción -n.

269
[madonna@station madonna]$ ls -s /var/log/m* | sort -n
4 /var/log/messages
20 /var/log/maillog
216 /var/log/messages.3
384 /var/log/messages.1
560 /var/log/messages.4
636 /var/log/messages.2
1236 /var/log/maillog.4
1552 /var/log/maillog.2
1952 /var/log/maillog.3
3104 /var/log/maillog.1

Mejor pero madonna preferiría invertir el orden para que los archivos más grandes estén primero.
Agrega la opción -r.

[madonna@station madonna]$ ls -s /var/log/m* | sort -nr


3104 /var/log/maillog.1
1952 /var/log/maillog.3
1552 /var/log/maillog.2
1236 /var/log/maillog.4
636 /var/log/messages.2
560 /var/log/messages.4
384 /var/log/messages.1
216 /var/log/messages.3
20 /var/log/maillog
4 /var/log/messages

¿Por qué ls -1?

¿Por qué la opción -1 fue dada al comando ls en el primer ejemplo, pero no en los otros? Por
defecto, cuando el comando ls está utilizando una terminal para la salida estándar, éste
agrupará los nombres de archivo en múltiples comandos para una lectura fácil. Sin embargo,
cuando el comando ls está utilizando una tubería o archivo para salida estándar, imprimirá
los archivos, uno por cada línea. La opción también fuerza esta conducta para la salida de la
terminal.

Especificar teclas de clasificación

En los ejemplos anteriores, el comando sort realizó su clasificación con base en los primeros
caracteres buscados en una línea. A menudo, la información formateada no se arregla de modo tan
conveniente. Afortunadamente, el comando sort permite a los usuarios especificar qué columna de
datos tabulares utilizar para determinar el tipo de orden o de un modo más formal, qué columna
debería utilizarse como la tecla de clasificación.

El siguiente cuadro de opciones puede utilizarse para determinar la tecla de clasificación.

Table 1. Opciones para especificar teclas de clasificación

Opción Efecto
-k, --key=POS Utilice la tecla en POS para determinar el orden de clasificación.
-t, --field- Utilice el caracter o caracteres SEP para separar campos (en lugar de un

270
separator=SEP espacio en blanco).

Clasificar salida por una columna en particular

A manera de ejemplo, suponga que madonna quisiera volver a examinar sus archivos de registro
utilizando el formato largo del comando ls. Ella trata simplemente de clasificar su salida de modo
numérico.

[madonna@station madonna]$ ls -l /var/log/m* | sort -n


-rw------- 1 root root 1260041 Sep 14 04:05 /var/log/maillog.4
-rw------- 1 root root 1581750 Sep 28 06:15 /var/log/maillog.2
-rw------- 1 root root 1993522 Sep 22 10:16 /var/log/maillog.3
-rw------- 1 root root 216885 Sep 22 10:22 /var/log/messages.3
-rw------- 1 root root 31187 Oct 5 06:05 /var/log/maillog
-rw------- 1 root root 3172217 Oct 5 04:05 /var/log/maillog.1
-rw------- 1 root root 387345 Oct 5 04:07 /var/log/messages.1
-rw------- 1 root root 567049 Sep 14 04:08 /var/log/messages.4
-rw------- 1 root root 644859 Sep 28 06:22 /var/log/messages.2
-rw------- 1 root root 651 Oct 5 05:40 /var/log/messages

Ahora que los tamaños ya no se reportan al comienzo de la línea, se le dificulta. En su lugar, repite
la clasificación con la opción -k para ordenar su salida por la quinta columna obteniendo la salida
esperada.

[madonna@station madonna]$ ls -l /var/log/m* | sort -n -k5


-rw------- 1 root root 651 Oct 5 05:40 /var/log/messages
-rw------- 1 root root 31187 Oct 5 06:05 /var/log/maillog
-rw------- 1 root root 216885 Sep 22 10:22 /var/log/messages.3
-rw------- 1 root root 387345 Oct 5 04:07 /var/log/messages.1
-rw------- 1 root root 567049 Sep 14 04:08 /var/log/messages.4
-rw------- 1 root root 644859 Sep 28 06:22 /var/log/messages.2
-rw------- 1 root root 1260041 Sep 14 04:05 /var/log/maillog.4
-rw------- 1 root root 1581750 Sep 28 06:15 /var/log/maillog.2
-rw------- 1 root root 1993522 Sep 22 10:16 /var/log/maillog.3
-rw------- 1 root root 3172217 Oct 5 04:05 /var/log/maillog.1

Especificar teclas de clasificación múltiples

Luego, madonna está examinando el archivo /etc/fdprm, el cual presenta parámetros de formato a
nivel bajo para los controladores de disquete. Utiliza el comando grep para extraer la información
del archivo, eliminando los comentarios y las líneas en blanco.

271
[madonna@station madonna]$ grep "^[[:alnum:]]" /etc/fdprm
360/360 720 9 2 40 0 0x2A 0x02 0xDF 0x50
1200/1200 2400 15 2 80 0 0x1B 0x00 0xDF 0x54
360/720 720 9 2 40 1 0x2A 0x02 0xDF 0x50
720/720 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
720/1440 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
360/1200 720 9 2 40 1 0x23 0x01 0xDF 0x50
720/1200 1440 9 2 80 0 0x23 0x01 0xDF 0x50
1440/1440 2880 18 2 80 0 0x1B 0x00 0xCF 0x6C
1440/1200 2880 18 2 80 0 ???? ???? ???? ???? # ?????
1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ?????
cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E
800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E

Luego clasifica los datos en forma numérica utilizando la quinta columna como su tecla.

[madonna@station madonna]$ grep "^[[:alnum:]]" /etc/fdprm | sort -n -k5


360/1200 720 9 2 40 1 0x23 0x01 0xDF 0x50
360/360 720 9 2 40 0 0x2A 0x02 0xDF 0x50
360/720 720 9 2 40 1 0x2A 0x02 0xDF 0x50
1200/1200 2400 15 2 80 0 0x1B 0x00 0xDF 0x54
1440/1200 2880 18 2 80 0 ???? ???? ???? ???? # ?????
1440/1440 2880 18 2 80 0 0x1B 0x00 0xCF 0x6C
1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ?????
720/1200 1440 9 2 80 0 0x23 0x01 0xDF 0x50
720/1440 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
720/720 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E
cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E

La información ha sido clasificada con éxito utilizando la quinta columna, con los formatos que
especifican 40 pistas agrupadas en la parte superior y 80 pistas agrupadas en la parte inferior. Sin
embargo, dentro de estos grupos madonna desearía clasificar la información por la tercera
columna. Ella agrega una opción adicional -k al comandosort especificando la tercera columna
como su tecla secundaria.

[madonna@station madonna]$ grep "^[[:alnum:]]" /etc/fdprm | sort -n -k5 -k3


360/1200 720 9 2 40 1 0x23 0x01 0xDF 0x50
360/360 720 9 2 40 0 0x2A 0x02 0xDF 0x50
360/720 720 9 2 40 1 0x2A 0x02 0xDF 0x50
720/1200 1440 9 2 80 0 0x23 0x01 0xDF 0x50
720/1440 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
720/720 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E
cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E
1200/1200 2400 15 2 80 0 0x1B 0x00 0xDF 0x54
1440/1200 2880 18 2 80 0 ???? ???? ???? ???? # ?????
1440/1440 2880 18 2 80 0 0x1B 0x00 0xCF 0x6C
1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ?????

272
Ahora que los datos han sido clasificados por la quinta columna. Para filas con columnas quintas
idénticas, la tercera columna se ha utilizado para determinar el orden final. Un número arbitrario de
teclas puede especificarse al agregar más opciones -k.

Especificación del separador de campo

Los ejemplos anteriores han demostrado cómo clasificar información con un campo especificado
como una tecla de clasificación. En todos los ejemplos, los campos se separaron por un espacio en
blanco (i.e., una serie de espacios o tabulaciones). Examine, el ejemplo del archivo /etc/passwd.

[madonna@station madonna]$ head /etc/passwd


root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/etc/news:

Las líneas están estructuradas en siete campos cada una, pero los campos están separados con
un “:” en lugar de espacios en blanco. Con la opción -t se puede dar instrucciones al comando sort
para utilizar algún caracter especificado (tal como “:”) para separar campos.

A continuación, madonna utiliza el comando sort con la opción -t para clasificar las primeras 10
líneas del archivo /etc/passwd por el directorio de inicio (el sexto campo).

[madonna@station madonna]$ head /etc/passwd | sort -t: -k6


bin:x:1:1:bin:/bin:/sbin/nologin
news:x:9:13:news:/etc/news:
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
daemon:x:2:2:daemon:/sbin:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

La usuaria bin, con un directorio de inicio de /bin, está ahora en la parte superior y la usuaria mail
con un directorio de inicio de /var/spool/mail, está en la parte inferior.

Resumen

En resumen, hemos visto que el comando sort puede utilizarse para clasificar datos estructurados,
mediante la opción -k para especificar el campo de clasificación(quizás más de una vez) y la
opción -t para especificar el delimitador del campo.

273
La opción -k puede recibir argumentos más sofisticados, los cuales sirven para especificar
posiciones de caracteres dentro de un campo o personalizar opciones de clasificación para campos
individuales. Ver la página de manual sort(1) para mayor información.

El comando uniq

El programa uniq se utiliza para identificar, contar o suprimir registros duplicados en la información
clasificada. Si se dan argumentos de línea de comandos, se interpretan como nombres de archivo
para los archivo en los cuales operar. Si no se proporcionan argumentos, el comandouniq opera
en la entrada estándar. Dado que el comando uniq sólo funciona en información ya clasificada,
casi siempre se utiliza junto con el comandosort.

El comando uniq utiliza las siguientes opciones para clasificar su conducta.

Table 1. Argumentos de linea de comando para uniq

-c, --count Línea prefijo con el número de sus ocurrencias, esta es la longitud
de“run”.
-d, --repeated Imprime en pantalla sólo las líneas duplicadas.
-f, --skip-fields=n Evita comparar los primeros campos n, delimitados por un espacio en
blanco.
-i, --ignore-case Ignora mayúsculas o minúsculas
-s, --skip-charsn Salta los primeros n caracteres.
-u, --unique Imprime sólo líneas únicas.
-w, --check- No compara más de n caracteres en cada línea.
chars=n

Para poder entender el comportamiento del comando uniq, necesitamos datos repetitivos en los
cuales operar. El siguiente script python simula el lanzamiento de tres dados de seis caras, al
escribir la suma de 100 funciones una por línea. La usuaria madonna hace el script ejecutable y
luego graba la salida en un archivo llamado trial1.

[madonna@station madonna]$ cat three_dice.py


#!/usr/bin/python

from random import randint


for i in range(100): print randint(1,6)+randint(1,6)+randint(1,6)
[madonna@station madonna]$ chmod 755 three_dice.py
[madonna@station madonna]$ ./three_dice.py > trial1
[madonna@station madonna]$ wc trial1
100 100 260 trial_run
[madonna@station madonna]$ head trial1
10
10
10
13
8
8
10
10
8
6

274
Reducción de datos a enteros únicos

Ahora, trial1 quisiera analizar la información. Comienza por clasificar la información y entubar la
salida a través del comando uniq.

[madonna@station madonna]$ sort -n trial1 | uniq


4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Sin ninguna opción el comando uniq ha suprimido entradas reduciendo los datos de 100 a sólo 15
líneas. Fácilmente, madonna observa que la información es razonable: la suma de cada
combinación para los tres dados de seis caras es representada, a excepción de 3. Puesto que sólo
una combinación de dados podría producir una suma de 3 (todos unos), madonna espera que sea
una ocurrencia relativamente poco frecuente.

Conteo de instancias de datos

Una opción particularmente conveniente para el comando uniq es -c o --count. Esto hace que el
comando uniq cuente el número de ocurrencias de un registro particulars anteponiendo el
resultado al registro en la salida.

En el siguiente ejemplo, madonna utiliza el comando uniq para reproducir su salida anterior, esta
vez anteponiendo el número de ocurrencias de cada entrada en el archivo.

[madonna@station madonna]$ sort -n trial1 | uniq -c


1 4
4 5
6 6
10 7
10 8
13 9
13 10
9 11
13 12
4 13
8 14
4 15
1 16
2 17
2 18

275
Como es de esperarse (al menos por un experto en estadísticas), los números más grandes y los
más pequeños tienen relativamente pocas ocurrencias, mientras que los números intermedios se
presentan en mayor cantidad. La primera columna puede sumarse hasta 100 para confirmar que el
comando uniq identifique cada ocurrencia.

Identificación única o datos repetidos con uniq

Algunas veces, la gente está solo interesada en identificar datos únicos o repetidos. Las opciones -
d y -u permiten al comando hacer justo eso. En el primer caso, madonna identifica las
combinaciones de dados que se presentan sólo una vez. En el segundo caso, identifica las
combinaciones repetidas al menos una vez.

[madonna@station madonna]$ sort -n trial0 | uniq -u


4
16
[madonna@station madonna]$ sort -n trial1 | uniq -d
5
6
7
8
9
10
11
12
13
14
15
17
18

Ejemplos

Clasificación de la salida de ps aux

La usuaria madonna está examinando los procesos que están ejecutándose en su máquina local.
Está familiarizada con el comando ps aux que presenta la información sobre cada proceso en
ejecución.

[madonna@station madonna]$ ps aux | head -4


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1380 76 ? S 02:05 0:04 init [
root 2 0.0 0.0 0 0 ? SW 02:05 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW 02:05 0:00 [kapmd]

El siguiente cuadro identifica las columnas seleccionadas.

Table 1. Columnas seleccionadas desde el comando ps aux

Número de Título Función


columna

276
1 USER El usuario propietario del proceso.
2 PID El ID del proceso
3 %CPU Utilización de la CPU relativa del proceso
4 %MEM La utilización relativa de la memoria del proceso
5 VSZ El "tamaño virtual " del proceso o cuánta memoria ha solicitado el
proceso
6 RSS El "tamaño residente" del proceso o cuánta memoria real está
consumiendo.

La usuaria madonna desearía ordenar los procesos en términos de algunos de estos parámetros.
Primero, ordena los procesos por tamaño de memoria virtual, clasificándolos en orden numérico y
listándolos en orden descendente. Observe el uso del comando tail +2 para suprimir el
encabezado de la lista de procesos.

[madonna@station madonna]$ ps aux | tail +2 | sort -rn -k5 | head


gdm 1074 0.0 5.2 37828 13396 ? S 02:06 0:01
/usr/bin/gdmgreeter
madonna 1844 0.0 0.2 19436 632 pts/0 S 03:42 0:00 sort -rn -k5
apache 909 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 908 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 907 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 906 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 905 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 904 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 903 0.0 0.5 18320 1464 ? S 02:06 0:00 /usr/sbin/httpd
apache 902 0.0 0.5 18320 1468 ? S 02:06 0:00 /usr/sbin/httpd

El comando gdmgreeter(que administra registros para el entorno gráfico X) y el demonio httpd


(que implementa el servidor de red Apache) son los procesos más grandes en la memoria de la
máquina de madonna, en términos de cantidad de memoria que están solicitando, (observe
también que el comando sort aparece).

Luego, madonna clasifica la salida por la sexta columna, que presenta los tamaños de los procesos
residentes en la memoria.

[madonna@station madonna]$ ps aux | tail +2 | sort -rn -k6 | head


gdm 1074 0.0 5.2 37828 13396 ? S 02:06 0:01 /usr/bin/gdmgreet
root 1066 0.0 2.5 17836 6444 ? R 02:06 0:00 /usr/X11R6/bin/X
root 914 0.0 1.2 9916 3140 ? S 02:06 0:00 cupsd
xfs 978 0.0 0.9 4816 2512 ? S 02:06 0:00 xfs -droppriv
elvis 1664 0.0 0.7 6768 2020 ? S 03:31 0:00 /usr/sbin/sshd
madonna 1748 0.0 0.7 6768 2008 ? S 03:31 0:00 /usr/sbin/sshd
root 1662 0.0 0.6 6716 1736 ? S 03:31 0:00 /usr/sbin/sshd
root 1746 0.0 0.6 6716 1724 ? S 03:31 0:00 /usr/sbin/sshd
madonna 1752 0.0 0.5 4388 1472 pts/2 S 03:31 0:00 -bash
root 885 0.0 0.5 18248 1468 ? S 02:06 0:00 /usr/sbin/httpd

Curiosamente una colección de procesos ocupa la parte superior de la lista incluyendo el servidor
X y varias instancias del demonio sshd (que implementa el servicio de Secure Shell). Se presume
que estos son los procesos activos en el momento.

277
Luego, madonna clasifica por la tercera columna, la actividad relativa de laCPU.

[madonna@station madonna]$ ps aux | tail +2 | sort -rn -k3 | head


elvis 1744 33.8 0.1 3408 400 pts/1 R 03:31 6:01 cat /dev/
zero
elvis 1745 33.7 0.1 3412 400 pts/1 R 03:31 6:00 cat /dev/
zero
blondie 1826 33.3 0.1 3412 400 pts/2 R 03:32 5:45 cat /dev/
zero
xfs 978 0.0 0.9 4816 2512 ? S 02:06 0:00 xfs
-droppriv
smmsp 864 0.0 0.0 5732 4 ? S 02:06 0:00 sendmail:
Queue
rpc 586 0.0 0.0 1548 4 ? S 02:05 0:00 portmap
root 914 0.0 1.2 9916 3140 ? S 02:06 0:00 cupsd
root 9 0.0 0.0 0 0 ? SW 02:05 0:00 [bdflush]
root 894 0.0 0.0 1572 172 ? S 02:06 0:00 crond
root 885 0.0 0.5 18248 1468 ? S 02:06 0:00
/usr/sbin/httpd

Su máquina no está viendo mucha actividad actual, a excepción de tres procesos diferentes cat
que parecen dividir de modo uniforme su CPU.

Uso de sort y uniq para recopilar información de procesos en ejecución

Al seguir examinando los procesos en ejecución en su máquina, madonna utiliza el comando ps


con la opción -e, la cual especifica listar cada proceso y la opción -o que toma un listado de
nombres en la columna como un argumento. La opción -o le permite a madonna listar solo la
información que le interesa. madonna encuentra las entradas en un cuadro de especificadores de
formato en la página de manual ps(1).

Table 1. Especificadores de formato seleccionados para el comandops

Tag Especifica
cmd El nombre corto del comando
pid El ID del proceso
estado El estado actual del proceso (R=en ejecución, S=dormido)
user El usuario propietario del proceso

Como algunos ejemplos al utilizar la opción -o, madonna presenta los procesos con su propio ID de
proceso, el usuario propietario del proceso y el comando ejecutándose.

[madonna@station madonna]$ ps -e -o pid,user,cmd | head -5


PID USER CMD
1 root init [
2 root [keventd]
3 root [kapmd]
4 root [ksoftirqd_CPU0]

278
Luego, hace un cuadro del id del proceso y el estado.

[madonna@station madonna]$ ps -e -o pid,state| head -5


PID S
1 S
2 S
3 S
4 S

Ahora que se ha familiarizado un poco con el comando ps y la opción -o, está lista para comenzar
a hacer algunas preguntas. Primero desea saber quién está ejecutando procesos en la máquina y
cuántos procesos están ejecutándose, listando únicamente el nombre de usuario propietario del
proceso. Luego pasa la salida a través de sort y uniq -c. Observe de nuevo el uso del comando
tail +2 para eliminar el encabezado desde la salida del comando ps.

[madonna@station madonna]$ ps -e -o user | tail +2 | sort | uniq -c


8 apache
2 blondie
1 daemon
3 elvis
1 gdm
5 madonna
48 root
1 rpc
1 smmsp
1 xfs

Ella preferiría que la salida fuera clasificada por lo tanto agrega uno o más sort al final de la
tubería.

[madonna@station madonna]$ ps -e -o user | tail +2 | sort | uniq -c |


sort -rn
48 root
8 apache
6 madonna
3 elvis
2 blondie
1 xfs
1 smmsp
1 rpc
1 gdm
1 daemon

Ahora blondie ve con facilidad que el root y apache están ejecutando la mayor parte de los
procesos (presumiblemente demonios en segundo plano), seguidos por madonna, elvis, y blondie
(presumiblemente usuarios interactivos). ¿Cuántos de estos proceso están ejecutándose y cuántos

279
están dormidos? Mediante un truco similar, pero esta vez listando el estado de los procesos del
usuario propietario, ella sale con esta respuesta.

[madonna@station madonna]$ ps -e -o state | tail +2 | sort | uniq -c |


sort -rn
73 S
5 R

La mayoría de los procesos en su máquina (73) están durmiendo, mientras que relativamente
pocos (5) están ejecutándose (lo que implica que están utilizando la CPU de modo activo).

Ejercicios en línea Lab Exercise Objetivo: Utilizar sort y uniq para administrar informacion de
modo eficiente. Tiempo estimado: 45 minutos.

Especificaciones

1. El archivo /etc/fstab se utiliza para predefinir puntos de montaje en su sistema. La tercera


columna del archivo especifica el tipo de sistema de archivo del dispositivo que va a ser
montado.

Clasifique el contenido del archivo en orden alfabético ascendente, mediante la tercera


columna como su tecla primaria. Almacene la salida en el archivo recién creado
~/fstab.byfs.

2. El archivo /proc/modules lista los módulos cargados en el kernel junto con el tamaño del
módulo (la segunda columna) y un uso de conteo actual (tercera columna).

Clasifique el contenido de este archivo en orden numérico descendente, con el uso de


conteo (tercera columna) como una tecla primaria y el tamaño de módulo (segunda
columna) como su tecla secundaria. Almacene los resultados en el archivo~/modules.byuc.

3. Clasifique el archivo /etc/passwd en orden alfabético ascendente mediante la shell de inicio


del usuario como la tecla primaria. Almacene los resultados en el archivo recién creado
passwd.bylogin.
4. El comandostat utiliza la opción --format para especificar su formato de salida. Como se
vio en la página de manual stat(1) (o stat --help), la siguiente línea de comandos listará
los permisos en un archivo de notación octal.

[student@station student]$ stat --format="%a" /etc/passwd


644

Utilice el comando para listar los permisos en todos los archivos (y directorios, etc) en el directorio /
etc/ (pero no en subdirectorios). Utilice los comandos sort y uniq para reducir esta información a
un sencillo cuadro, con la primera para el número de veces que se presenta el modo octal
especificado en la segunda columna. El cuadro debería clasificarse en orden numérico

280
descendente, utilizando el número de ocurrencias (la primera columna) como su tecla primaria.
Almacene el cuadro en un archivo recién creado llamado ~/etcmodes.txt.

Si se ha completado correctamente, su cuadro debería tener una forma parecida a la siguiente (no
se preocupe si los valores reales del cuadro difieren).

[student@station student]$ cat etcmodes.txt


127 644
63 755
16 600
15 777
6 640
5 664
3 444
2 400
1 775
1 750
1 440

5. El comando df lista las particiones de disco montadas actualmente junto con uso actual del
disco. La cuarta columna de esta salida del comando lista la cantidad de espacio
disponible en bloques.

Crea un script ejecutable llamado ~/bin/avail. Cuando sea ejecutado el script debería listar
las particiones disponibles (la salida del comando df), clasificada en orden numérico
descendente. La línea del encabezado generada a partir del comando df debería
eliminarse de la salida.

content_view let_
Deliverables A title Question 1

1. El archivo fstab.byfs que incluye el contenido de un archivo /etc/fstab clasificado en orden


alfabético ascendente, usando la tercera columna como la tecla primaria.
2. El archivo modules.byuc que incluye el contenido del archivo /proc/modules clasificado en
orden numérico descendente con la tercera columna como la tecla primaria y la segunda
columna como la tecla secundaria.
3. El archivo passwd.bylogin que incluye el contenido del archivo /etc/passwd clasificado en
orden alfabético ascendente con la shell de inicio del usuario como la tecla primaria.
4. El archivo etcmodes.txt que presenta los permisos octales (modos) de todos los archivos en
el directorio /etc. La segunda columna del cuadro debería ser el modo octal y la primera
columna el número de archivos a los cuales el modo aplica. Los cuadros deberían
clasificarse en orden numérico descendente, con la primera columna como una tecla
primaria.
5. Elscript ejecutable ~/bin/avail, que al ejecutarse (sin argumentos) muestra la salida del
comando df clasificado en orden numérico descendente, mediante la cuarta columna como
su tecla primaria. La línea del encabezado producida por el comando df debería eliminarse
de la salida.

Si ha realizado los ejercicios correctamente, debería poder generar salida similar a la siguiente. No
se preocupe si sus valores actuales difieren.

281
282
Extraer y reunir texto: cut y paste

Conceptos clave

• El comando cut extrae textos de archivos de texto, basados en columnas especificadas


por bytes, caracteres o campos.
• El comando paste fusiona dos archivos de texto por línea.

Discussion

En esta lección, exploramos dos comandos utilizados para extraer columnas de un flujo de texto, o
reunir columnas en un flujo más ancho: cut y paste.

El comando cut

Extracción del texto con cut

El comando cut extrae columnas de texto desde un archivo de texto o flujo. Imagine que toma una
hoja de papel que lista filas de nombres, direcciones de correo-e y números telefónicos. Rasgue la
página verticalmente dos veces para que cada columna sea un pedazo separado. Quédese con la
parte del medio que contiene las direcciones de correo-e y bote las otras dos. Esta es la
mentalidad detrás del cut.

El comando cut interpreta cualquier argumento de línea de comandos como nombres de archivo
en los cuales operan u opera el flujo de entrada estándar si ninguno es provisto. Para especificar
cuáles bytes, caracteres, o campos se cortan, el comando cut debe llamarse con una de las
siguientes opciones.

Table 1. "Obligatorio" Opciones para el comando cut.

Opción Efecto
-b Extrae bytes especificados en lista
lista
-c Extrae caracteres especificados en lista
lista
-f lista Extrae campos especificados en lista

Los argumentos de listado son en realidad una lista separada por comas de intervalos. Cada
intervalo puede tomar una de las siguientes formas.

Table 2. Especificaciones de intervalo

N Solo el número del elemento N.


N- Elementos N a través del final de la línea.
N- Elementos N a través de M (inclusive)
M
-M Desde el comienzo de la línea a través del número del elemento M (inclusive).
- Todos los elementos desde el comienzo de la línea hasta el final de la línea.

Extracción de texto por posición de caracter con cut -c

283
Con la opción -c, la list especifica una posición de caracter en una línea de texto, donde el primer
caracter es el primer caracter número 1. A manera de ejemplo, el archivo /proc/interrupts lista
controladores de dispositivo, la solicitud de interrupción (IRQ) a la cual se añaden y el número de
interrupciones ocurridas en la línea IRQ, (no se preocupe si no está familiarizado con los conceptos
de un controlador de dispositivo o línea IRQ. Enfóquese en la manera como cut se utiliza para
manipular la información).

[student@rosemont student]$ cat /proc/interrupts


CPU0
0: 4477340 XT-PIC timer
1: 25250 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 7344 XT-PIC ehci-hcd
5: 310187 XT-PIC usb-uhci, ohci1394
8: 1 XT-PIC rtc
10: 166 XT-PIC usb-uhci, eth1
11: 6575295 XT-PIC usb-uhci, eth0, Audigy
12: 544632 XT-PIC PS/2 Mouse
14: 80379 XT-PIC ide0
15: 341407 XT-PIC ide1
NMI: 0
ERR: 0

Debido a que los caracteres en el archivo se formatean en columnas, el comando cut puede
extraer regiones particulares de interés. Si sólo la línea IRQ y los números de interrupciones fueran
de interés, el resto del archivo podría ser cut, como en el siguiente ejemplo (observe el uso del
comando grep para reducir primero el archivo únicamente a las líneas pertenecientes a líneas de
interrupción.)

[student@rosemont student]$ grep '[[:digit:]]:' /proc/interrupts | cut -c1-15


0: 4512997
1: 27954
2: 0
3: 7344
5: 312095
8: 1
10: 166
11: 6629756
12: 545523
14: 81025
15: 344239

De forma alterna, si únicamente los controladores de dispositivos se unen a líneas IRC de interés
particulares, podrían especificarse intervalos múltiples de caracteres.

284
[student@rosemont student]$ grep '[[:digit:]]:' /proc/interrupts | cut
-c1-5,34-
0: timer
1: keyboard
2: cascade
3: ehci-hcd
5: usb-uhci, ohci1394
8: rtc
10: usb-uhci, eth1
11: usb-uhci, eth0, Audigy
12: PS/2 Mouse
14: ide0
15: ide1

Si las especificaciones de caracteres se invirtieran, ¿podría utilizarse el comando cut para


reorganizar el orden de la información?

[student@rosemont student]$ grep '[[:digit:]]:' /proc/interrupts | cut


-c34-,1-5
0: timer
1: keyboard
2: cascade
...

La respuesta es no. El texto aparecerá sólo una vez, en el mismo orden de aparición en la fuente,
incluso si las especificaciones de intervalos están superponiéndose o reordenanándose.

Extracción de campos de texto con cut -f

El comando cut también sirve para extraer texto que no está estructurado por la posición de
caracteres, sino por un caracter delimitador tal como un TABULADOR o “:”. Las siguientes
opciones pueden utilizarse para clasificar lo que se conoce como un campo o para líneas de fuente
más selectivas.

Table 1. Opciones para cut -f

Opción Efecto
-d DELIM Utilice DELIM para separar campos en entrada en lugar del
caracter por defectoTAB.
-s No incluya líneas que no contengan el caracter delimitador (útil
para eliminar comentarios y encabezados).
--delimitador de En salida, utilice el texto especificado por CADENA DE TEXTO
salida=CADENA DE TEXTO en lugar del delimitador de campo.

Por ejemplo, el archivo /usr/share/hwdata/pcitable lista más de 3000 IDS de vendedores IDS de
dispositivos (que pueden ensayarse desde dispositivos PCI) y los módulos de kernel y cadenas de
texto que deberían asociarse con ellos, separados por tabulaciones.

285
[student@rosemont hwdata]$ head -15 pcitable
# This file is automatically generated from isys/pci. Edit
# it by hand to change a driver mapping. Other changes will
# be lost at the next merge - you have been warned.
# Edit by hand to change a driver mapping. Changes to descriptions
# will be lost at the next merge - you have been warned.
# If you run makeids, please make sure no entries are lost.
# The format is ("%d\t%d\t%s\t"%s"\n", vendid, devid, moduleName,
cardDescription)
# or ("%d\t%d\t%d\t%d\t%s\t"%s"\n", vendid, devid, subvendid, subdevid,
moduleName, cardDescription)

0x0675 0x1700 "unknown" "Dynalink|IS64PH ISDN Adapter"


0x0675 0x1702 "hisax" "Dynalink|IS64PH ISDN Adapter"
0x09c1 0x0704 "unknown" "Arris|CM 200E Cable Modem"
0x0e11 0x0001 "ignore" "Compaq|PCI to EISA Bridge"
0x0e11 0x0002 "ignore" "Compaq|PCI to ISA Bridge"
0x0e11 0x0046 "cciss" "Compaq|Smart Array 64xx"

El siguiente ejemplo extrae la tercera y cuarta columna con el caracter por defecto TABULADOR
para separar campos. Observe el uso de la opción -s, elimina las líneas de encabezado (que no
contienen ningún TABULADOR).

[student@rosemont hwdata]$ cut -s -f3,4 pcitable | head


"unknown" "Dynalink|IS64PH ISDN Adapter"
"hisax" "Dynalink|IS64PH ISDN Adapter"
"unknown" "Arris|CM 200E Cable Modem"
"ignore" "Compaq|PCI to EISA Bridge"
"ignore" "Compaq|PCI to ISA Bridge"
"cciss" "Compaq|Smart Array 64xx"
"unknown" "Compaq|NC7132 Gigabit Upgrade Module"
"unknown" "Compaq|NC6136 Gigabit Server Adapter"
"tmspci" "Compaq|Netelligent 4/16 Token Ring"
"ignore" "Compaq|Triflex/Pentium Bridge, Model 1000"

Otro ejemplo, suponga que quisiéramos obtener un listado de los módulos del kernel más
referenciados en el archivo. Podríamos utilizar un comando similar a cut junto con trucos
aprendidos en la última lección para obtener un listado rápido de la frecuencia de aparición de cada
módulo de kernel.

[student@rosemont hwdata]$ cut -s -f3 pcitable | sort | uniq -c | sort -


rn | head
1988 "unknown"
148 "ignore"
83 "aic7xxx"
70 "gdth"
37 "e100"
37 "Card:ATI Rage 128"
36 "3c59x"
24 "Card:ATI Mach64"
21 "tulip"
20 "agpgart"

286
Muchas de las entradas obviamente se desconocen o se ignoran intencionalmente, pero sí vemos
que el controlador SCSI aic7xxx y el controlador de tarjeta Ethernet e100 se utilizan con mucha
frecuencia.

Extracción de texto por posición de byte con cut -b

La opción -b sirve para especificar qué texto extraer por bytes. Al extraer texto con la opción -b es
muy parecido en espíritu al uso de -c. De hecho, cuando se trabaja con un texto codificado
utilizando ASCII o uno de los conjuntos de caracteres ISO 8859 (tales como Latín-1), los dos son
idénticos. Sin embargo, la opción -b difiere de -c, cuando se utilizan conjuntos de caracteres con
codificación de variables de longitud tal como UTF-8 (un conjunto de caracteres estándar en el que
mucha gente converge y el predeterminado en Red Hat Enterprise Linux).

A manera de ejemplo, considere los siguientes tres caracteres en texto alemán: fr. Al utilizar la
codificación UTF-8, los dos caracteres que componen el conjunto de caracteres ASCII, “f” y “r”, son
codificadas en un sólo byte. No obstante, “”, se codifica con dos bytes como se observa en el
comando wc.

[elvis@station elvis]$ echo fr | wc -c


5

Tenemos un byte para cada una de las letras “f y r, un byte para la nueva ldos bytes para .”

Al utilizar cut -c, “” se consideraría como un sólo caracter, pero al utilizar cut -b, “” se tendrían en
cuenta dos bytes, como en el siguiente ejemplo.

[elvis@station elvis]$ echo f | cut -c 1-2


f
[elvis@station elvis]$ echo f | cut -b 1-2
f?

La primera vez, el comando cut contó los dos bytes utilizados para codificar “” como un caracter
sencillo, pero la segunda vez, se consideraron dos bytes. Como resultado, el caracter fue "cortado
por la mitad" con el comando y la terminal no pudo mostrarlo correctamente.

Usualmente, cut -c es la forma correcta de utilizar el comando cut y cut -b solo se necesitará para
situaciones técnicas.

Note

Observe la nomenclatura inconsistente entrewc y cut. Con wc -c, el comando wc devuelve


el número de bytes contenidos en una cadena de texto, mientras que cut -c mide texto en
caracteres. Infortunadamente, el comando wc no hace ninguna distinción equivalente entre
caracteres y bytes.

El comando paste

287
El comando paste sirve para combinar archivos múltiples en una sola salida. Recuerde cuando
imaginamos el pedazo de papel que listaba filas de nombres, direcciones de correo -e y números
telefónicos. Después de rasgarlo en tres columnas, ¿qué sucedería si pegaramos la primera a la
tercera, dejando un pedazo de papel listando sólo nombres y números telefónicos? Este es el
concepto detrás del comando paste.

El comando paste espera un conjunto de nombres de archivo como argumentos. El comando


paste leerá la primera línea de cada archivo, unirá el contenido de cada línea insertando un
caracter TABULADOR en el medio y escribirá la línea sencilla resultante en la salida estándar.
Luego continuará con la segunda línea de cada archivo.

Considere los dos archivos siguientes a manera de ejemplo.

[student@station student]$ cat file-1


File-1 Line 1
File-1 Line 2
File-1 Line 3
[student@station student]$ cat file-2
File-2 Line 1
File-2 Line 2
File-2 Line 3

El comando paste imprimiría lo siguiente:

[student@station student]$ paste file-1 file-2


File-1 Line 1 File-2 Line 1
File-1 Line 2 File-2 Line 2
File-1 Line 3 File-2 Line 3

Si tuviéramos más de dos archivos, la primera línea de cada archivo se convertiría en la primera
línea de la salida. La segunda línea de salida contendría las dos segundas líneas de cada archivo
de entrada, obtenido en el orden determinado en la línea de comandos. Por conveniencia, el
nombre de archivo - puede suministrarse en la línea de comandos. Para este "archivo", el comando
pastese leería desde la entrada estándar.

Table 1. Opciones para paste

Opción Descripción
-d lista Reutiliza caracteres del listado de delimitadores (en lugar del caracter predeterminado
TAB)
-s, Transpone el resultado para que cada línea en el primer archivo se pegue a una sola
--serial línea, cada línea del segundo archivo se pegue a la siguiente línea sencilla, etc.

Ejemplos

Manejo de registros de formato libre

En el diseño de un registro de formato libre, los elementos de registro de entrada son identificados
por su posición en la línea, no por la posición de caracter. Se espera que los campos de entrada
sean separados exactamente por un caracter TABULADOR, pero que ningún caracter que

288
aparezca en los elementos de información mismos pueda utilizarse Cada ocurrencia del
delimitador separa un campo.

Nuestro archivo favorito de ejemplo /etc/passwd tiene campos separados exactamente por el
caracter de dos puntos (“:”). El campo 1 es el nombre de cuenta y el campo 7 da el programa de
shell utilizado. Mediante el comando cut podemos imprimir un nuevo archivo con sólo el nombre de
cuenta y el nombre de shell:

[student@station student]$ cut -d: -f1,7 /etc/passwd


root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
...

Observe que las líneas de salida utilizan los mismos delimitadores de campo que los registros de
entrada. Podemos cambiar eso con la opción --output-delimiter.

[student@station student]$ cut -d: -f7,1 --output-delimiter=,


/etc/passwd
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
adm,/sbin/nologin
lp,/sbin/nologin
...

Vivir con registros de formatos fijos

En un registro de formato fijo, la información se asigna a posiciones de caracteres específicos o


columnas que son iguales en cada línea de entrada. Utilice la opción -c para identificar posiciones
del caracter de entrada copiados en cada línea de salida.

[student@station student]$ cat fixed-data


abc123
def456
hij789
lkm012

Podemos recortar sólo los caracteres 3 y 4 así:

[student@station student]$ cut -c3-4 fixed-data


c1
f4
j7
m0

Uso (y mal uso) de un espacio como delimitador

289
El comando mount sin argumentos, retorna una lista que muestra los dispositivos montados y los
puntos de montaje junto con el tipo de sistema de archivos y las opciones relevantes de montaje

[student@station student]$ mount


/dev/hda3 on / type ext3 (rw)
none on /proc type proc (rw)
usbdevfs on /proc/bus/usb type usbdevfs (rw)
/dev/hda1 on /boot type ext3 (rw)
none on /dev/pts type devpts (rw,gid=5,mode=620)
none on /dev/shm type tmpfs (rw)
automount(pid780) on /misc type autofs
(rw,fd=5,pgrp=780,minproto=2,maxproto=3)

Observando que las palabras están separadas por espacios sencillos, el comando cut puede
fácilmente utilizarse para extraer fácilmente la tercera y cuarta palabra (que contiene el punto de
montaje y archivos, respectivamente). El comando debe suplirse con la opción -d " ", que le pide
tratar espacios como delimitadores de campo.

[student@station student]$ mount | cut -d" " -f3,5


/ ext3
/proc proc
/proc/bus/usb usbdevfs
/boot ext3
/dev/pts devpts
/dev/shm tmpfs
/misc autofs

¿Funcionaría la misma técnica para el comando df?

[student@station student]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda3 5131108 4502000 368456 93% /
/dev/hda1 124427 26268 91735 23% /boot
none 127616 0 127616 0% /dev/shm
[student@station student]$ df | cut -d" " -f1,5
Filesystem
/dev/hda3
/dev/hda1
none

¿En qué parte de la salida del comando df, se presenta el quinto "campo"? En alguna parte a
medio camino de las primeras dos columnas. El comando cut obedientemente imprime el primer y
quinto campo (vacío).

Infortunadamente, esta es una limitación común del comando cut. Por fortuna, encontraremos
otras técnicas en una lección posterior para superar este inconveniente.

Ejemplos de pegado

290
Nuestro ejemplo inicial mostró el uso común de paste, donde las primeras líneas de todos los
archivos de entrada se concatenan y separan por un caracter delimitador, el proceso luego se
repite para las siguientes líneas. La opción -s pega todas las lineas del archivo de entrada a la
primera línea de salida, luego pega todas las líneas del segundo archivo de salida y así
sucesivamente:

[student@station student]$ paste -d: -s file-1 file-2


File-1 Line 1:File-1 Line 2:File-1 Line 3
File-2 Line 1:File-2 Line 2:File-2 Line 3

Recuerde que el argumento de la opción -d de la listade argumentos puede tomar más de un


caracter. Esto puede utilizarse para proveer un delimitador diferente entre cada par de partes
escritas en la salida. Los caracteres list son reciclados si es necesario:

[student@station student]$ paste -d+-/ file-1 file-2 file-1 file-2


file-1
File-1 Line 1+File-2 Line 1-File-1 Line 1/File-2 Line 1+File-1 Line 1
File-1 Line 2+File-2 Line 2-File-1 Line 2/File-2 Line 2+File-1 Line 2
File-1 Line 3+File-2 Line 3-File-1 Line 3/File-2 Line 3+File-1 Line 3

Ejercicios en línea Lab Exercise Objetivo: Utilizar cut y paste para administrar texto. Tiempo
Estimado: 25 minutos.

Especificaciones

1. Utilice el comando cut para extraer un listado de los nombres de usuario y las shells de
inicio desde el archivo /etc/passwd, donde los nombres de usuario resultantes y las shells
de inicio están separadas por un espacio. Clasifique el listado resultante en orden
alfabético ascendente, mediante la shell de inicio como tecla primaria y el nombre de
usuario como tecla secundaria. Almacene el resultado en el archivo recién creado
~/usershells.txt.
2. El archivo /proc/cpuinfo contiene información sobre su CPU del sistema detectado. Utilice
el comando cut para extraer sólo los valores, no los nombres o el“:” utilizado para separar
los nombres de los valores. Almacene el listado de valores resultante en un archivo recién
creado ~/cpuvalues.txt.
3. El archivo /etc/sysconfig/init sirve para definir parámetros que configuran su método de
arranque de la máquina. Los parámetros se definen mediante la misma sintaxis utilizada
por la shell bash, i.e., NAME=value.

Utilice la combinación de los comandos grep y cut para generar un listado de un


parámetro nombres hallado en este archivo uno por línea. No incluya los valores de
parámetros o “=”utilizados para separarlos ni ningún otro comentario o líneas vacías del
archivo original. Clasifique los nombres en orden alfabético ascendente y almacénelos en
el archivo recién creado ~/initparams.txt.

4. El siguiente script puede utilizarse para imprimir una serie de 10 números aleatorios.

291
#!/bin/bash

for i in $(seq 10); do


echo $RANDOM
done

5. Cree el script en un archivo de su escogencia y haga que el archivo sea ejecutable.


Ejecute el script 5 veces por separado, cada vez registrando el tiempo de salida en el
archivo llamado ~/trial1, ~/trial2, ~/trial3, etc.

Cree un archivo llamado titles, que contenga las palabras run1, run2, ... run10, una por
línea en cada una de las diez líneas.

Utilice el comando paste para combinar los archivos llamados titles, trial1, trial2, trial3trial4
y trial5, en ese orden, dentro de un archivo llamado trials. Utilice el caracter TABULADOR
predeterminado para separar las columnas.

Si ha completado el ejercicio de laboratorio correctamente, usted debería ser capaz de generar una
salida similar a la siguiente. No se preocupe si algunos de los valores difieren.

292
[student@station student]$ head -4 usershells.txt cpuvalues.txt
initparams.txt titles trial[15] trials

==> usershells.txt <==


news
alice /bin/bash
apache /bin/bash
arnold /bin/bash

==> cpuvalues.txt <==


0
GenuineIntel
6
8

==> initparams.txt <==


BOOTUP
LOGLEVEL
MOVE_TO_COL
PROMPT

==> titles <==


run1
run2
run3
run4

==> trial1 <==


9739
9089
6712
25993

==> trial5 <==


32029
1474
8347
31709

==> trials <==


run1 9739 27486 12465 14282 32029
run2 9089 27496 13136 15835 1474
run3 6712 7089 7467 7969 8347
run4 25993 12188 31152 12746 31709

content_view let_
Deliverables A title Question 1

1. El archivo usershells.txt, que contiene un listado de todos los usuarios y shells de inicio
definido en el archivo /etc/passwd, separado por un espacio. Las líneas deberían
clasificarse en orden alfabético ascendente, mediante las shells de inicio como la tecla
primaria y los nombres de usuario como la tecla secundaria.
2. El archivo cpuvalues.txt, que lista los valores para parámetros buscados en el archivo /proc/
cpuinfo, uno por línea. Los valores deberían aparecer en el mismo orden de aparición en el

293
archivo /proc/cpuinfo.
3. El archivo initparams.txt que contiene un listado en orden alfabético ascendente del
parámetro nombres hallado en el archivo /etc/sysconfig/init.
4. Cinco archivos llamados ~/trial1, ~/trial2, ... ~/trial5 que listan 10 números enteros
aleatorios, uno por línea.
5. El archivo ~/titles, que contiene las 10 palabras run1, run2, ... run10, una palabra por línea.

6. El archivo trials, que incluye el contenido de seis archivos titles, trial1, ... trial5 pegados en
un sólo archivo mediante el comando paste.

294
Rastreo de diferencias: diff

Conceptos clave

• El comando diff resume las diferencias entre dos archivos.


• El comando diff es compatible con una gran variedad de formatos de salida que pueden
escogerse mediante varias opciones. El más comun es el formato unificado.
• Al comando diff se le puede pedir que ignore ciertos tipos de diferencias tales como el uso
de espacios en blanco o de mayúsculas.
• El comando diff -r resume de modo recursivo las diferencias entre los dos directorios.
• Al comparar directorios, se le puede pedir al comando diff que ignore los archivos cuyos
nombres de archivo coincidan con patrones especificados.

Discussion

El comando diff

El comando diff está diseñado para comparar dos archivos similares, pero no idénticos y que
generen salida que describa exactamente la diferencia. El comando diff es más utilizado para
rastrear cambios a archivos de texto tales como informes, páginas web, scripts de shell o código
fuente C . También las utilidades con el comando diff, para que la versión dada de un archivo y la
salida del comando diff comparándolo con otra versión, el archivo puede actualizarse de modo
automático. El comando más importante es el comando patch.

Primero presentamos el comando diff por medio de un ejemplo. En la comunidad de código


abierto, la documentación por lo general sacrifica la corrección de la ortografía o gramática por
tiempo como se demuestra en el siguiente archivo README.pam_ftp.

[blondie@station blondie]$ cat README.pam_ftp


This is the README for pam_ftp
------------------------------

This module is an authentication module that does simple ftp


authentication.

Recognized arguments:

"debug" print debug messages


"users=" comma separated list of users which
could login only with email adress
"ignore" allow invalid email adresses

Options for:
auth: for authentication it provides pam_authenticate() and
pam_setcred() hooks.

James Anderson <james@anderson.us>, 17. June 1999

Observe que las palabras addressy addresses están mal escritas, blondie se dispone a aplicar
cambios, primero al corregir las palabres mal escritas y en segundo añadiendo una línea

295
registrando sus revisiones. Hace una copia del archivo añadiendo la extensión .orig. Luego hace
sus modificaciones.

[blondie@station blondie]$ cp README.pam_ftp README.pam_ftp.orig


[blondie@station blondie]$ nano README.pam_ftp

Ahora utiliza el comando diff para comparar las dos revisiones del archivo.

[blondie@station blondie]$ diff README.pam_ftp.orig README.pam_ftp


11,12c11,12
< could login only with email adress
< "ignore" allow invalid email adresses
---
> could login only with email address
> "ignore" allow invalid email addresses
18a19
> Spelling corrections applied by blondie, 22 Sep 2003

Sin ir aún dentro de mucho detalle sobre la sintaxis de diff, vemos que el comando ha identificado
las diferencias entre los dos archivos ejemplificando la esencia del comando diff. El comando diff
es tan utilizado que su salida a menudo se refiere como un sustantivo, como en "Aquí está la
diferencia entre los dos archivos".

Formatos de salida para el comando diff

El comando diff fue concebido en los primeros días de la comunidad Unix. Con el tiempo, se han
hecho mejoras en la manera que diff anota los cambios. Para preservar la compatibilidad de
segundo plano, todavía están disponibles formatos más antiguos. A continuación se listan los
formatos diff más utilizados.

diff"estándar"

En un principio, el comando diff se utilizaba para preservar el ancho de banda de las


conexiones de red lentas. En lugar de transferir una nueva versión del archivo, se
transfería un resumen de revisiones. El resumen estaba en un formato de fácil
reconocimiento por el editor de la línea de comando ed, el cual raras veces se utiliza hoy
en día. Al examinar la salida anterior uno puede imaginarse el editor ed siendo requerido
para c ambiar las líneas 11 y 12 y añadir una línea después de la línea 18.

No obstante, pronto se tuvieron que hacer algunas mejoras. ¿Qué sucedería si los cambios
se aplicaran dos veces? El editor de comando ed haría los cambios corrompiendo el
contenido del archivo. La solución es un contexto sensible a diff.

Contexto diff (diff -c)

El comando diff sensible al contexto se genera al especificar las opciones -c o -C N, (la


segunda forma se utiliza para especificar que exactamente N líneas del contexto deberían
ser generadas.) Analice el siguiente ejemplo.

296
[blondie@station blondie]$ diff -c README.pam_ftp.orig README.pam_ftp
*** README.pam_ftp.orig 2003-10-07 15:30:05.000000000 -0400
--- README.pam_ftp 2003-10-07 15:30:17.000000000 -0400
***************
*** 8,18 ****

"debug" print debug messages


"users=" comma separated list of users which
! could login only with email adress
! "ignore" allow invalid email adresses

Options for:
auth: for authentication it provides pam_authenticate() and
pam_setcred() hooks.

James Anderson <james@anderson.us>, 17. June 1999


--- 8,19 ----

"debug" print debug messages


"users=" comma separated list of users which
! could login only with email address
! "ignore" allow invalid email addresses

Options for:
auth: for authentication it provides pam_authenticate() and
pam_setcred() hooks.

James Anderson <james@anderson.us>, 17. June 1999


+ Spelling corrections applied by blondie, 22 Sep 2003

Es obvio que, el contexto diff incluye varias líneas alrededor antes de identificar cambios.
Los cambios son anotados al utilizar un “!” para marcar líneas que se han cambiado, “+”
para marcar líneas que se han añadido y “-” para marcar líneas que se han suprimido. Al
utilizar un contenidodiff, las utilidades detectan automáticamente cuando un administrador
trata de actualizar un archivo dos veces.

Comando diff unificado (diff -u)

El comando unificado diff se genera al especificar las opciones -u o -U N (la segunda


forma se utiliza para especificar las N líneas exactas de contexto que deberían generarse).
En lugar de duplicar las líneas de contexto, el comando unificado diff intenta registrar
todos los cambios en una estanza, creando una salida más compacta y podría decirse,
más legible.

297
[blondie@station blondie]$ diff -u README.pam_ftp.orig README.pam_ftp

--- README.pam_ftp.orig 2003-10-07 15:30:05.000000000 -0400


+++ README.pam_ftp 2003-10-07 15:30:17.000000000 -0400
@@ -8,11 +8,12 @@

"debug" print debug messages


"users=" comma separated list of users which
- could login only with email adress
- "ignore" allow invalid email adresses
+ could login only with email address
+ "ignore" allow invalid email addresses

Options for:
auth: for authentication it provides pam_authenticate() and
pam_setcred() hooks.

James Anderson <james@anderson.us>, 17. June 1999


+Spelling corrections applied by blondie, 22 Sep 2003

En lugar de identificar una línea como "cambiada", el comando unificadodiff anota que la
versión original debería borrarse y que debería agregarse la nueva versión.

diff lado a lado (diff -y)

Se supone que los tres formatos anteriores eran fáciles de leer por alguna otra utilidad tal
como el editor -W80 o la utilidad patch. En contraste, el formato "lado a lado" está
diseñado para ser leído por humanos. Como su nombre lo indica, las dos versiones del
archivo se muestran diff lado a lado, con anotaciones en el medio que ayudan a identificar
cambios. El siguiente ejemplo pide un diff"lado a lado" mediante la opción -y y más
adelante, clasifica lo que la salida debería formatear en las 80 columnas con -W80.

[blondie@station blondie]$ diff -y -W80 README.pam_ftp.orig README.pam_ftp


This is the README for pam_ftp This is the README for pam_ftp
------------------------------ ------------------------------

This module is an authentication modu This module is an authentication modu


authentication. authentication.

Recognized arguments: Recognized arguments:

"debug" print debug m "debug" print debug m


"users=" comma separat "users=" comma separat
could login o | could login o
"ignore" allow invalid | "ignore" allow invalid

Options for: Options for:


auth: for authentication it provide auth: for authentication it provide
pam_setcred() hooks. pam_setcred() hooks.

James Anderson <james@anderson.us>, 1 James Anderson <james@anderson.us>, 1


> Spelling corrections applied by blond

298
Aunque la salida sería más efectiva utilizando una terminal ancha, ofrece una idea intuitiva
para las diferencias entre los dos archivos.

diff silecioso (diff -q)

El comando diff silecioso apenas informa si dos archivos difieren, no la naturaleza de las
diferencias.

[blondie@station blondie]$ diff -q README.pam_ftp.orig README.pam_ftp


Files README.pam_ftp.orig and README.pam_ftp differ

if-then-else Macro diff (diff -D etiqueta)

Este formato genera diferencias mediante una sintaxis reconocida por el pre-procesador
cpp. Éste permite ya sea a la versión original como al la nueva ser incluidas al definir la
etiqueta especificada. Aunque esto está más allá del alcance de este curso es incluído
para beneficio de aquellos familiarizados con el preprocesadorcpp C.

También existen otros formatos de salida menos utilizados. ¿Qué formato es el correcto? La
respuesta depende de las preferencias del generador "diff" o de las expectativas de quien pueda
estar recibiendo el "diff". El comando diff sirve para comunicar sugerencias a la comunidad de
código abierto sobre cambios al código abierto de algún programa, con el fin de corregir un error o
agregar una característica. En este contexto, casi siempre se prefiere el formato unificado diff.

El siguiente cuadro resume algunas de las opciones que pueden utilizarse para especificar el
formato de salida para el comando diff.

Table 1. Opciones para especificar el formato de salida diff

Opción Efecto
-c Generar el contexto de formato sensible
-C, Generar un formato de contexto sensible mediante N líneas de contexto, si se
--context[=N] especifican.
-u Generar el formato unificado
-U, --unified[=N] Generar el formato unificado mediante contexto de líneas, si se especifican.
-N Otro formato para especificar líneas de contexto N. Sólo utilizadas con -c o -u.
-y, --side-by- Generar el formato lado a lado
side
-W, --width=N Usa las columnas Nal generar el formato lado a lado
--left-column Imprime sólo la columna izquierda cuando usa el formato lado a lado.
-q, --brief Solo reporta si los archivos difieren, no los detalles de la diferencia.

Cómo diff interpreta argumentos

El comando diff espera ser llamado con dos argumentos, uno desde- archivo y otro al-archivo (o
en otras palabras, un archivoviejo y un archivonuevo). La salida del comando diff describe lo que
se debe hacer al desde-archivo para crear el al-archivo.

299
Si uno de los nombres de archivo se refiere a un archivo regular y el otro a un directorio, el
comando diff buscará un archivo con el mismo nombre en el directorio especificado. Si ambos son
directorios, el comando diff comparará archivos en ambos directorios, pero no buscará de modo
recursivo en los subdirectorios (a menos que la opción -r sea especificada, ver abajo).
Adicionalmente, el nombre de archivo especial“-” hará que el comando diff lea desde la entrada
estándar en lugar de un archivo regular.

Para que la personalización de diff sea menos problemática

Si no se le ha pedido lo contrario, el comando diff rastreará de modo exhaustivo todas las


diferencias entre los dos archivos. Varias líneas de comando pueden utilizarse para hacer que el
comando diff tenga una conducta más relajada. El siguiente cuadro resume las opciones.

Table 1. Las opciones que especifican la problemática de diff

Opción Efecto
-b, -w, --ignore-all-space Ignora el espacio en blanco al comparar líneas.
-B, --ignore-blank-lines Ignora el espacio en blanco al comparar líneas.
-i, --ignore-case Ignora el uso de mayúsculas (i.e., considere caracteres equivalentes
a las mayúsculas y minúsculas).
-I, --ignore-matching- Ignora cambios que insertan o borran líneas coincidentes con el
lines=regex argumento obligatorio regex.

Como un ejemplo, considere los siguientes dos archivos.

[blondie@station blondie]$ cat cal.txt


September 2003
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

[blondie@station blondie]$ cat cal_edited.txt


====================
==== This Month ====
====================

September 2003

Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

El archivo cal_edited.txt difiere en dos respectos. Primero se agregó un encabezado de cuarta


línea en la parte superior. Segundo, se agregó una línea extra (vacía) a la parte inferior. Un
comando diff "ordinario" reconoce todos estos cambios.

300
[blondie@station blondie]$ diff cal.txt cal_edited.txt
0a1,4
> ====================
> ==== This Month ====
> ====================
>
9a14
>

Con la opción -B, sin embargo, el comando diff ignora la línea nueva, vacía en la parte inferior.

.[blondie@station blondie]$ diff -B cal.txt cal_edited.txt


0a1,4
> ====================
> ==== This Month ====
> ====================
>

Con la opción -I se puede pedirle al comando diff ignorar las líneas que comienzan por “=”.

[blondie@station blondie]$ diff -B -I "^=" cal.txt cal_edited.txt

Modo recursivo de diff

El comando diff puede actuar de modo recursivo, bajando dos árboles de directorio siimilares y
anotando las diferencias. El siguiente cuadro lista las opciones importantes para la conducta
recursiva de diff.

Table 1. Opciones para utilizar diff de modo recursivo

Opción Efecto
-r, --recursive Al comparar directorios, busque también de modo recursivo a través de
subdirectorios.
-x, Al comparar directorios de modo recursivo, omita los nombres de archivo
--exclude=patrón coincidentes patrón.
-X, --exclude- Al comparar directorio de modo recursivo, omita los nombres de archivos
from=file coincidentes con patrones especificados en file.

A manera de ejemplo, blondie está examinando dos versiones de un proyecto llamado vreader. El
proyecto involucra scripts Python que convierten la información de calendario del formato vcal a un
formato XML. Ella ha descargado dos versiones de un proyecto, vreader-1.2.tar.gz y
vreader-1.3.tar.gz y ha expandido cada uno de los archivos en su directorio de inicio local.

[blondie@station blondie]$ ls
vreader-1.2 vreader-1.2.tar.gz vreader-1.3 vreader-1.3.tar.gz

Los directorios vreader-1.2 y vreader-1.3 tienen la siguiente estructura.

301
vreader-1.2/
|-- addressbook.vcard
|-- calendar.ics
|-- conv_db.py
|-- conv_db.pyc
|-- datebook.xml
|-- templates/
| `-- datebook.xml
`-- vreader.py
vreader-1.3/
|-- addressbook.vcard
|-- calendar.ics
|-- conv_db.py
|-- conv_db.pyc
|-- datebook.out.xml
|-- datebook.xml
|-- templates/
| `-- datebook.xml
`-- vreader.py

Para resumir las diferencias entre las dos versiones, ella ejecuta diff de modo recursivo en los dos
directorios.

[blondie@station blondie]$ diff -r vreader-1.[23]


Binary files vreader-1.2/conv_db.pyc and vreader-1.3/conv_db.pyc differ
Only in vreader-1.3: datebook.out.xml
diff -r vreader-1.2/templates/datebook.xml
vreader-1.3/templates/datebook.xml
15a16
> <event description="Linux users 331 dabney" categories=""
uid="-1010079065" start="873246600" end="873248400" />
diff -r vreader-1.2/vreader.py vreader-1.3/vreader.py
6a7
> time_offset = 0 # in hours
348c349
< return utime
---
> return utime + time_offset*3600

El comando diff busca de modo recursivo a través de los dos directorios y observa las siguientes
diferencias.

1. Los dos archivos binarios vreader-1.2/conv_db.pyc y vreader-1.3/conv_db.pyc difieren.


Puesto que no son archivos de texto, el comando no intenta anotar las diferencias.
2. El archivo complementario a vreader-1.3/datebook.out.xml no se halla en el directorio
vreader-1.2.
3. Los archivos vreader-1.2/templates/datebook.xml y vreader-1.3/templates/datebook.xml
difieren y diff anota los cambios.
4. Los archivos vreader-1.2/vreader.py y vreader-1.3/vreader.py difieren y diff anota los
cambios.

302
A menudo, cuando comparamos los árboles de directorio más complicados se espera que haya
archivos que cambien y otros que no. Por ejemplo, el archivo conv_db.pyc es código Python
compilado, automáticamente generado desde el archivo del guión de texto Python conv_db.py.
Dado que blondie no está interesada en las diferencias entre las versiones compiladas del archivo,
utiliza la opción de línea de comando -x para excluir las comparaciones de la forma de archivo. Del
mismo modo, no está interesada en los archivos terminados en -x, así que los especifica con una
opción adicional-x.

[blondie@station blondie]$ diff -r -x "*.pyc" -x "*.xml" vreader-1.[23]


diff -r -x '*.pyc' -x '*.xml' vreader-1.2/vreader.py
vreader-1.3/vreader.py
6a7
> time_offset = 0 # in hours
348c349
< return utime
---
> return utime + time_offset*3600

Ahora que la salida del comando diff está limitada sólo por el archivo vreader-1.2/vreader.py y su
complemento en vreader-1.3.

Como una alternativa para listar los patrones de archivos a excluir en la línea de comandos, los
patrones pueden recopilarse en un simple archivo de texto que se especifica en su lugar, mediante
la opción -X. En el siguiente ejemplo blondie ha creado y utiliza tal archivo.

[blondie@station blondie]$ cat diff_excludes.txt


*.pyc
*.xml
*.py
[blondie@station blondie]$ diff -r -X diff_excludes.txt vreader-1.[23]

Dado que blondie incluyó *.py en su lista de patrones de archivo para excluir, el comando diff se
abandona sin nada qué decir.

Ejemplos

Uso de diff para examinar archivos nuevos de configuración

Después de actualizar su paquete RPM sendmail, blondie observa que tiene un nuevo archivo de
configuración en su directorio/etc/mail, sendmail.cf.rpmnew. A ella le gustaría ver cómo se compara
este archivo con su archivo de configuración ya existente, /etc/mail/sendmail.cf. Utiliza diff para
resumir las diferencias.

303
[blondie@station blondie]$ diff /etc/mail/sendmail.cf /etc/mail/sendmail.cf.rpmnew
19,21c19,21
< ##### built by root@station.example.com on Tue Apr 1 15:09:38 EST 2003
< ##### in /etc/mail
< ##### using /usr/share/sendmail-cf/ as configuration include directory
---
> ##### built by bhcompile@daffy.perf.redhat.com on Wed Sep 17 14:45:22 EDT 2003
> ##### in /usr/src/build/308253-i386/BUILD/sendmail-8.12.8/cf/cf
> ##### using ../ as configuration include directory
40d39
<
101c100
< DSnimbus.example.com
---
> DS

Está satisfecha con la nueva versión del archivo de configuración que difiere únicamente en
algunas de las líneas de comentarios y en la falta de una configuración local que ha agregado a su
nueva versión.

Uso de diff para examinar cambios recientes a /etc/passwd

El administrador de sistemas de una máquina ha notado que la utilidad useradd crea una copia de
seguridad del archivo /etc/passwd cada vez que le hace un cambio, llamado /etc/passwd-. Como
usuaria root, ella desearía ver el cambio más reciente al archivo /etc/passwd.

[root@station root]# diff /etc/passwd- /etc/passwd


68a69
> desktop:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin

Aparentemente, un nuevo usuario de sistema se ha agregado reciéntemente, probablemente como


resultado de agregar nuevo software mediante un archivo de paquete RPM.

Creación de un parche

Después de descargar el archivo vreader-1.3.tar.gz y de expandir su contenido, blondie decide que


pudo mejorar en el proyecto y le gustaría hacer cambios al archivo vreader.py. Primero hace una
copia "pristina" de la fuente (la versión que desempacó del archivo distribuído) y luego modifica su
copia del archivo.

[blondie@station blondie]$ tar xzf vreader-1.3.tar.gz


[blondie@station blondie]$ cp -a vreader-1.3 vreader-1.3.local
[blondie@station blondie]$ nano vreader-1.3.local/vreader.py

304
Una vez editada su copia del archivo, quisiera enviar los cambios al coordinador de cambios al
proyecto vreader. En la comunidad de código abierto, esta persona se conoce como el encargado
del proyecto. En lugar de enviar una copia entera de la versión. ella graba las diferencias entre su
versión y el original en un archivo llamado vreader-1.3.blondie.patch.

[blondie@station blondie]$ diff -ru vreader-1.3 vreader-1.3.local


> vreader-1.3.blondie.patch

Ahora envía por correo-e el archivo de corrección al encargado del proyecto, quien puede
fácilmente utilizar un comando llamado patch para aplicar los cambios a una versión original.

[blondie@station blondie]$ mail -s "my changes" maintainer@patch.org <


vreader-1.3.blondie.patch

Ejercicios en línea Lab Exercise Objetivo: Utilizar el comando diff para rastrear cambios en los
archivos. Estimated Time: 10 mins.

Especificaciones

1. Utilice el comando diff para anotar la diferencia entre los archivos


/usr/share/doc/pinfo-0*/COPYING y /usr/share/doc/mtools-3*/COPYING, utilizando el
formato de contexto sensible. Registre la salida en el archivo recién creado
~/COPYING.diff. Al especificar los nombres de archivo en la línea de comandos, liste
primero el archivo pinfo y utilice una referencia absoluta para los dos.
2. Cree una copia local del directorio /usr/share/gedit-2, utilizando el siguiente comando (en
su directorio de inicio).

[student@station student]$ cp -a /usr/share/gedit-2 .

3. Para su copia local del directorio gedit-2, haga los siguientes cambios.
1. Suprima los dos archivos.
2. Cree un archivo llamado arbitrariamente en algún lugar bajo el directorio gedit-2
con un contenido arbitrario.
3. Usando el editor de texto, borre las tres líneas de cualquier archivo en el directorio
gedit-2/taglist.

Cuando haya terminado, genere de modo recursivo un "diff" entre /usr/share/gedit-2 y su


copia, gedit-2. Registre la salida en un archivo recién creado ~/gedit.diff. Cuando
especifique los directorios en la línea de comandos especifique primero una copia original y
utilice una referencia absoluta para los dos. No modifique el contenido de su gedit-2 a
menos que usted también reconstruya su archivo ~/gedit.diff.

content_view let_
Deliverables A title Question 1

1. El archivo ~/COPYING.diff que contiene un contexto sensible "diff" de los archivos


/usr/share/doc/pinfo*/COPYING y /usr/share/doc/mtools*/COPYING, donde la versión del
archivo pinfo se utiliza como el original y cada archivo se especifica mediante una

305
referencia absoluta.

2. El archivo ~/gedit.diff que contiene un "diff" recursivo de los directorios /usr/share/gedit-2


y~/gedit-2. Ambos directorios deberían especificarse mediante referencias absolutas y el
directorio de sistema debería utilizarse como el original.

306
Traducción de texto: tr

Conceptos clave

• El comando tr traduce lectura de datos desde la entrada estándar.


• En su forma más básica, el comando tr realiza sustituciones byte por byte.
• Al utilizar la opción -d, el comando tr borrará caracteres especificados desde un flujo.
• Al utilizar la opción -s se comprimirá una serie de caracteres repetidos en un flujo a una
sola instancia del caracter.

Discussion

El comando tr

El comando tr es una utilidad muy versátil que realiza traducciones de caracter en flujos. Traducir
puede suponer sustituir un caracter por otro, borrar caracteres o "comprimirlos" (contrayendo
secuencias repetidas de un caracter en uno). Cada uno de estos usos será descrito en las
siguientes secciones.

A diferencia de los comandos anteriores en esta sección, el comando tr no espera nombres de


archivo como argumentos. En su lugar, el comando tr opera exclusivamente en el flujo de entrada
estándar, reservando los argumentos de línea de comandos para especificar conversiones.

El siguiente cuadro especifica varias formas de invocar el comando tr.

Table 1. Sintaxis de invocación para el comando tr

Sintaxis Efecto
tr SET1 SET2 Substituye los caracteres especificados en SET2 para los caracteres
complementarios especificados en SET1.
tr -d Borra todos los caracteres especificados en CONJUNTO.
CONJUNTO
tr -s Comprime todos los caracteres especificados en CONJUNTO.
CONJUNTO
tr -s SET1 Primero, sustituya todos los caracteres hallados en SET2 por los caracteres
SET2 complementarios en SET1 luego, comprima todos los caracteres encontrados en
SET2.
tr -ds SET1 Primero borre todos los caracteres hallados en SET1, luego comprima todos los
SET2 caracteres en SET2.

Especificación de caracter

Como el cuadro anterior lo ilustra, el comando tr hace uso extensivo de caracteres definidos en
conjuntos. La sintaxis para definir un intervalo de caracteres basados en el especificador de
intervalo hallado en expresiones regulares. Las siguientes expresiones pueden utilizarse al
especificar caracteres.

Table 1. Especificación de caracteres para el comandotr

Sintaxis Caracter(es)

307
literal La mayoría de los caracteres coinciden con una traducción literal de ellos mismos.
\n El caracter de nueva línea.
\r El caracter de entrada.
\t El caracter de tabulación (horizontal).
\\ El caracter \ .
[A-Z] El intervalo de caracteres delimitados por los caracteres especificados. Depreciado,
porque el orden en que se determina el intervalo depende del conjunto de caracteres
utilizados para codificar la información.
[:alnum:] Todas las letras y dígitos.
[:alpha:] Todas las letras.
[:blank:] Todos los espacios horizontales en blanco.
[:digit:] Todos los dígitos.
[:lower:] Todos los caracteres en minúsculas.
[:print:] Todos los caracteres imprimibles.
[:punct:] Todos los caracteres de puntuación.
[:space:] Todos los espacios horizontales o verticales en blanco.
[:upper:] Todos los caracteres en mayúsculas.

El cuadro no presenta una lista completa. Para mayor información, consulte la página de manual
tr(1) o tr --help.

Uso de tr para traducir caracteres

A menos que se haya solicitado lo contrario (mediante opciones), el comando espera ser llamado
con dos argumentos, cada uno de los cuales especifica un intervalo de caracteres. Para cada uno
de los caracteres especificados en el primer conjunto, lo sustituirá el caracter encontrado en la
misma posición en el segundo conjunto. Considere el siguiente ejemplo trivial.

[madonna@rosemont madonna]$ echo "abcdefghi" | tr fed xyz


abczyxghi

Observe que en la salida, el caracter “d” es remplazado por el caracter “z”, “e” es remplazado por el
caracter “y”, y “f” es remplazado por el caracter “x”. El orden de los conjuntos es importante. La
tercera letra del primer conjunto es remplazada por la tercera letra del segundo conjunto.

¿Qué sucede si las longitudes de los dos conjuntos son desiguales? El segundo conjunto se
extiende a la longitud del primer conjunto al copiar el último caracter.

[madonna@rosemont madonna]$ echo "abcdefghi" | tr fed xy


abcyyxghi

Un ejemplo clásico del comando es traducir todo el texto en letras mayúsculas o todo en
minúsculas. La sintaxis de la "vieja escuela" para dicha traducción utilizaría intervalos de caracter.

308
[madonna@rosemont madonna]$ cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost rha-server
192.168.0.254 rosemont.example.com rosemont
192.168.0.51 hedwig.example.com hedwig h
192.168.129.201 z
[madonna@rosemont madonna]$ tr a-z A-Z < /etc/hosts
# DO NOT REMOVE THE FOLLOWING LINE, OR VARIOUS PROGRAMS
# THAT REQUIRE NETWORK FUNCTIONALITY WILL FAIL.
127.0.0.1 LOCALHOST.LOCALDOMAIN LOCALHOST RHA-SERVER
192.168.0.254 ROSEMONT.EXAMPLE.COM ROSEMONT
192.168.0.51 HEDWIG.EXAMPLE.COM HEDWIG H
192.168.129.201 Z

No obstante, como se mencionó en la lección sobre expresiones regulares, las especificaciones de


intervalo pueden producir resultados impares cuando se consideran varios conjuntos de caracteres.
El método de la "nueva escuela" es utilizar clases de caracteres.

[madonna@rosemont madonna]$ tr '[:lower:]' '[:upper:]' < /etc/hosts


# DO NOT REMOVE THE FOLLOWING LINE, OR VARIOUS PROGRAMS
# THAT REQUIRE NETWORK FUNCTIONALITY WILL FAIL.
127.0.0.1 LOCALHOST.LOCALDOMAIN LOCALHOST RHA-SERVER
192.168.0.254 ROSEMONT.EXAMPLE.COM ROSEMONT
192.168.0.51 HEDWIG.EXAMPLE.COM HEDWIG H
192.168.129.201 Z

Si recordamos que el orden de intervalos de caracteres es importante para el comando tr, las
clases de caracteres necesitarían generar consistentemente intervalos ordenados. Únicamente las
clases de caracter [:minúscula:] y [:mayúscula:] están garantizadas para hacerlo, lo que implica que
son las únicas clases apropiadas cuando se utiliza tr para la traducción de caracteres.

Uso de tr para borrar caracteres

Cuando se invoca con la opción -d, el comando tr adopta una conducta radical diferente. El
comando tr ahora espera un único argumento (opuesto a dos, arriba), el cual establece otra vez
una serie de caracteres. El comando tr filtrará entonces el flujo de entrada estándar, borrando cada
uno de los caracteres especificados, escribiéndolo en la salida estándar.

Considere el siguiente par de ejemplos.

[madonna@station madonna]$ echo abcdefghi | tr -d def


abcghi
[madonna@station madonna]$ echo 'hark, I hear an elephant!' | tr -d
[:upper:][:punct:]
hark hear an elephant

En el primer caso, se borraron los caracteres literales especificados “d”, “e” y “f”. En el segundo
caso, fueron borrados todos los caracteres pertenecientes a las clases de caracteres [:punct:] o
[:upper:].

309
Uso de tr para comprimir caracteres

Al utilizar la opción -s, el comando tr puede utilizarse para comprimir un conjunto continuo de
caracteres en un caracter sencillo. Si es llamado sin argumentos el comando tr simplemente
comprimirá el conjunto específico de caracteres como en el siguiente ejemplo.

[madonna@station madonna]$ echo "aaabbbcccdddeeefffggg" | tr -s bcf


aaabcdddeeefggg

Si se llama con la opción de línea de comando -s y dos argumentos, el comando tr realizará


sustituciones (como si -s no se hubiera especificado), pero comprime los caracteres del segundo
conjunto.

[madonna@station madonna]$ echo "aaabbbcccdddeeefffggg" | tr -s bcf xye


aaaxydddeggg

Observe que esto es en esencia los mismo que realizar la operación dos por separado.

[madonna@station madonna]$ echo "aaabbbcccdddeeefffggg" | tr bcf xye


aaaxxxyyydddeeeeeeggg
[madonna@station madonna]$ echo "aaabbbcccdddeeefffggg" | tr bcf xye | tr -s xye
aaaxydddeggg

Por último, el comando tr se puede llamar con las opciones -s y -d. En este caso, el comando tr
espera dos argumentos. El comando tr borrará el primer conjunto de caracteres y luego comprimirá
el segundo conjunto.

[madonna@station madonna]$ echo "aaabbbcccaaadddeeefffggg" | tr -ds bcf ae


adddeggg

Observe el orden de operaciones cuidadosamente. Este comando es esencialmente el mismo que


un suprimir (tr -d seguido por un comprimir (tr -s).

[madonna@station madonna]$ echo "aaabbbcccaaadddeeefffggg" | tr -d bcf


aaaaaadddeeeggg
[madonna@station madonna]$ echo "aaabbbcccaaadddeeefffggg" | tr -d bcf | tr -s
ae
adddeggg

Conjuntos complementarios

Aparte de -s y -d, hay dos opciones que modifican la conducta de tr, presentadas a continuación.

Table 1. Opciones para el comando tr

Opción Efecto

310
-c, Complemento SET1 antes de operar (i.e., uso del conjunto de caracteres
--complement excluídos por SET1)
-t, --truncate- Trunca la longitud de SET1 a la de SET2 antes de operar.
set1

Como un ejemplo rápido de la opción -c, el siguiente borra desde la entrada estándar cada caracter
que no sea vocal o espacio en blanco.

[madonna@station madonna]$ echo aaabbbcccdddeee | tr -cd


'aeiouAEIOU[:space:]'
aaaeee

Nuestra advertencia final: ¡evite el archivo comodín!

Una nota final antes de dejar nuestras “aes” y “es” y dirigirnos a ejemplos más prácticos.

En algunos de los ejemplos anteriores, madonna tuvo el cuidado de proteger expresiones tales
como [:punct:] con comillas sencillas, pero en algunas veces no lo fue. Cuando no las protegió,
tuvo suerte. Considere la siguiente secuencia.

[madonna@station madonna]$ echo 'hark, I hear an elephant!' | tr -d


[:punct:]
hark I hear an elephant
[madonna@station madonna]$ touch n
[madonna@station madonna]$ echo 'hark, I hear an elephant!' | tr -d
[:punct:]
hark, I hear a elephat!

¿Por qué razón madonna obtuvo dos resultados muy diferentes de la misma línea de comando? Si
no sabe la respuesta, e incluso si la sabe, debería proteger argumentos al comando tr con
comillas.

Ejemplos

Uso de tr para limpiar el comando df

Recuerde unas pocas lecciones atrás, cuando describíamos el comando cut y su capacidad para
extraer campos de texto de un flujo. Tratamos de utilizar el comando cut para extraer el primer y
quinto campo de la salida del comando df, especificando un espacio como el campo delimitador.

[madonna@station madonna]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda3 5131108 4499548 370908 93% /
/dev/hda1 124427 26268 91735 23% /boot
none 127616 0 127616 0% /dev/shm
[madonna@station madonna]$ df | cut -d" " -f1,5
Filesystem
/dev/hda3
/dev/hda1
none

311
Previamente identificamos el problema con este enfoque. El comando cut no reconoce un conjunto
de espacios como campos separados, sino un conjunto de campos (uno por cada espacio). Con su
nuevo conocimiento del comando tr, madonna sabe cómo resolver el problema.

Primero utiliza el comando tr para comprimir espacios múltiples en un espacio sencillo

[madonna@station madonna]$ df | tr -s ' '


Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda3 5131108 4499556 370900 93% /
/dev/hda1 124427 26268 91735 23% /boot
none 127616 0 127616 0% /dev/shm

Ahora, madonna puede utilizar con facilidad el comando tr para extraer las columnas apropiadas.

[madonna@station madonna]$ df | tr -s ' ' | cut -d" " -f1,5


Filesystem Use%
/dev/hda3 93%
/dev/hda1 23%
none 0%

Uso de tr para convertir archivos de texto en DOS a Unix

La usuaria madonna ha descubierto recientemente el Proyecto Gutenberg, un repositorio de textos


que han entrado a dominio público[1]. Ha descargado uno de sus textos favoritos A Tale of Two
Cities y almacenado en el archivo2city12.txt.

Tras examinar el archivo, se da cuenta que éste utiliza la convención DOS para separar las líneas
(un retorno de carro/nueva línea) como es ilustrado por la combinación “^M$” cuando se utiliza el
comando cat -A.

[madonna@station madonna]$ head -5 2city12.txt | cat -A


The Project Gutenberg Etext of A Tale of Two Cities, by Dickens^M$
^M$
Please take a look at the important information in this header.^M$
We encourage you to keep this file on your own disk, keeping an^M$
electronic path open for the next readers. Do not remove this.^M$

Ella preferiría que el texto utilizara la convención Unix (un caracter de una sola palabra new line).
Utiliza el comando tr para borrar todas las instancias del caracter, almacenando el resultado en el
archivo 2city12unix.txt.

[madonna@station madonna]$ tr -d '\r' < 2city12.txt > 2city12unix.txt

Para confirmar que la conversión sucedió correctamente, realiza un par de revisiones. Primero
examina el archivo con cat -A y observa que los caracteres “^M” se han suprimido.

312
[madonna@station madonna]$ head -5 2city12unix.txt | cat -A
The Project Gutenberg Etext of A Tale of Two Cities, by Dickens$
$
Please take a look at the important information in this header.$
We encourage you to keep this file on your own disk, keeping an$
electronic path open for the next readers. Do not remove this.$

En segundo lugar, realiza una conteo de palabras en ambos archivos mediante el comando wc

[madonna@station madonna]$ wc 2city12*


16364 137667 787603 2city12.txt
16364 137667 771239 2city12unix.txt
32728 275334 1558842 total

Ella observa que la diferencia en el número de caracteres en los dos archivos es igual al número
de líneas en los archivos (787603 - 771239 = 16364). Esto es apropiado si el comando tr borra un
caracter por línea, como se espera.

Por último, puesto que ya no está interesada en mantener la versión DOS formateada del archivo,
renombra el archivo 2city12unix.txt como 2city12.txt.

[madonna@station madonna]$ mv 2city12unix.txt 2city12.txt

Uso de tr las frecuencias de conteo de palabras Este ejemplo está basado en un ejemplo
similar hallado en (info coreutils) de la página informativa (info coreutils).

La buena escritura suele requerir que los autores eviten el uso en exceso de ciertas palabras
claves. La usuaria madonna utiliza el editor de texto para extraer el párrafo del texto.

[madonna@station madonna]$ cat para1


It was the best of times, it was the worst of times,
it was the age of wisdom, it was the age of foolishness,
it was the epoch of belief, it was the epoch of incredulity,
it was the season of Light, it was the season of Darkness,
it was the spring of hope, it was the winter of despair,
we had everything before us, we had nothing before us,
we were all going direct to Heaven, we were all going direct
the other way--in short, the period was so far like the present
period, that some of its noisiest authorities insisted on its
being received, for good or for evil, in the superlative degree
of comparison only.

Ahora quisiera generar un conteo de la frecuencia con que se utilizan algunas palabras.Para utilizar
el comando uniq -c, madonna desearía reordenar el texto para que las palabras aparezcan una
por línea. Ella traza el siguiente plan.

1. Borrar todos los signos de puntuación.

313
2. Convertir todos los caracteres en letras mayúsculas a letras minúsculas, con el fin de que
It y it sean consideradas como la misma palabra.
3. Convertir cada caracter espacio en un nuevo caracter nueva línea y comprimir múltiples
caracteres nueva línea en uno.

Comienza por implementar su plan paso a paso con el fin de observar los resultados intermedios

[madonna@station madonna]$ tr -d '[:punct:]' < para1 | head -5


It was the best of times it was the worst of times
it was the age of wisdom it was the age of foolishness
it was the epoch of belief it was the epoch of incredulity
it was the season of Light it was the season of Darkness
it was the spring of hope it was the winter of despair
[madonna@station madonna]$ tr -d '[:punct:]' < para1 | tr '[:upper:]'
'[:lower:]' |
head -5
it was the best of times it was the worst of times
it was the age of wisdom it was the age of foolishness
it was the epoch of belief it was the epoch of incredulity
it was the season of light it was the season of darkness
it was the spring of hope it was the winter of despair
[madonna@station madonna]$ tr -d '[:punct:]' < para1 | tr '[:upper:]'
'[:lower:]' |
tr -s ' ' '\n' | head -5
it
was
the
best
of

En este punto, madonna está lo suficientemente cómoda con sort y uniq para finalizar el proceso.

[madonna@station madonna]$ tr -d '[:punct:]' < para1 | tr '[:upper:]'


'[:lower:]' |
tr -s ' ' '\n' | sort | uniq -c | sort -rn | head -5
14 the
12 of
11 was
10 it
4 we

Motivada por su progreso, repite la técnica en todo el texto (el proceso tomó cerca de 8 segundos
en un procesador 700MHZ).

314
[madonna@station madonna]$ tr -d '[:punct:]' < 2city12.txt | tr
'[:upper:]' '[:lower:]' |
tr -s ' ' '\n' | sort | uniq -c | sort -rn | head -5
8082 the
4967 and
4061 of
3517 to
2952 a

Rot13

En los comienzos de grupos de Usenet, la gente adoptó una convención para oscurecer el texto
llamado rot13. Suponga que usted va a enviar un chiste y quisiera inmediatamente incluir la línea
de remate del chiste, pero no quisiera que dicha línea de remate fuera immediatamente obvia. La
línea de remate se convirtió en la más obvia. Dicha línea pudo ser convertida al rotar cada letra por
13 sitios para que “a” se convirtiera en “n”, “b” se convirtiera en “o”, y “z” se convirtiera en “m”,
como se ilustra en el siguiente ejemplo.

P: ¿Por qué el pollito cruzó la calle?


R: Gb trg gb gur bgure fvqr.

¿Cómo encontraría la respuesta? Al mirar el texto a través de un traductor tr implementado rot13.

[madonna@station madonna]$ echo "Gb trg gb gur bgure fvqr." | tr A-Za-z N-ZA-Mn-za-m
Para pasar al otro lado.

Ejercicios en línea Lab Exercise Objetivo: Familiarizarse con el comando tr. Estimated Time: 10
mins.

Especificaciones

1. El archivo /etc/passwd usa los dos puntos para delimitar campos. Cree el archivo
~/passwd.tsv, el cual es una copia del archivo /etc/passwd convertido para utilizar
tabulaciones como delimitadores de campo (i.e., cada “:” se convierte en una tabulación).
2. Crear el archivo ~/file_roller.converted que es una copia del archivo /usr/share/file-
roller/glade/file_roller.glade, con las siguientes conversiones.
a. Convertir todas las tabulaciones a espacios.
b. Convertir las comillas dobles (") a comillas sencillas ('). (no utilice acento grave (`).)
3. Cree un archivo llamado ~/openssl.converted, el cual es copia del archivo
/usr/share/ssl/openssl.cnf, con las siguientes conversiones.
a. Todas las líneas de comentarios son suprimidas (líneas cuyo primer caracter de
espacio en blanco es un #).
b. Todas las líneas vacías son suprimidas.
c. Todas las mayúsculas son dobladas en letras minúsculas.

315
d. Todos los dígitos se remplazan por el caracter de subrayado (“_”).

content_view let_
Deliverables A title Question 1

1. El archivo ~/passwd.tsv, el cual es una copia del archivo /etc/passwd con tabulaciones
sustituídas por dos puntos.
2. El archivo ~/file_roller.converted, el cual es una copia del archivo /usr/share/file-roller/glade/
file_roller.glade, con todas las tabulaciones convertidas en espacios y todas las comillas
dobles (") convertidas en comillas sencillas (').

3. El archivo ~/openssl.converted, el cual es una copia del archivo /usr/share/ssl/openssl.cnf,


con todas las líneas de comentario suprimidas(aquellas cuyo primer caracter que no sea
espacio en blanco es un “#”), todas las líneas suprimidas, todas las letras mayúsculas
convertidas en minúsculas y todos los dígitos numéricos remplazados por el caracter de
subrayado (_).

316
Revisión ortográfica: aspell

Conceptos clave

• El comando aspell -c realiza revisiones ortográficas interactivas en los archivos.


• El comando aspell -l realiza una revisión ortográfica en el flujo de entrada estándar.
• El comando aspell dump puede utilizarse para ver el maestro del sistema o el directorio
personal de un usuario.
• Los comandos aspell create personal y aspell merge personal pueden utilizarse para
crear o añadirse al directorio personal del usuario de una lista de palabras.

Discussion

En la distribución de Red Hat Enterprise Linux, la utilidad del comando aspell es la utilidad primaria
para revisar la ortografía de los archivos de texto. En esta lección, aprendimos cómo utilizar aspell
para revisar la ortografía del archivo de modo interactivo y personalizar el corrector de ortografía
con un diccionario especial.

Uso de aspell

Cuando ejecute aspell, el primer argumento (diferente a la posible opción de comandos) es


interpretado como un comando que le indica aaspell lo que tiene que hacer. Los siguientes
comandos son compatibles con aspell.

Table 1. Comandos Aspell

Comando Acción
-c file, chequear file Realiza una revisión de ortografía en el archivo file.
-l, list Imprime una lista de las palabras mal escritas halladas en el flujo del
entrada estándar.
config Bota la configuración actual aspell a la salida estándar.
dump master|personal| Bota una copia de la lista maestra de palabras, lista personal de
repl palabras y lista personal de remplazo, respectivamente.
create master| Crea la lista maestra de palabras, lista personal de palabras o lista
personal|repl personal de remplazo, respectivamente, entradas de lectura desde la
entrada estándar.
merge master| Fusiona entradas leídas desde la entrada estándar dentro de la lista
personal|repl maestra de palabras, la lista personal de palabras o la lista de
remplazo, respectivamente.

El siguiente cuadro lista algunas de las opciones utilizadas con el comando aspell.

Table 2. Opciones para el comando aspell

Opción Efecto
-W --ignore=N Ignora palabras de menos de N caracteres, (por defecto, solo se hace
caso omiso a palabras sencillas).
--ignore-case Ignora mayúsculas al realizar comparaciones de palabras.
-p, Utiliza la lista de palabras filename para la lista personal de palabras.
--personal=filename

317
-x, --dont-backup No crea archivo de seguridad al realizar la revisión ortográfica.

Realización de una revisión ortográfica interactiva

El usuario prince ha compuesto el siguiente mensaje, el cual piensa enviar por correo-e al usuario
elvis.

[prince@station prince]$ cat toelvis


Hey Elvis!

I heard that you were about to take the lab test for the string
procesing workbook in Red Hat Academy. IIRC, its prety
straightforward, if you've been keeping up with the exercises.

LOL, Prince

Antes de enviar el mensaje, prince utiliza aspell -c para realizar una revisión ortográfica interactiva.

[prince@station prince] aspell -c toelvis

Tras la ejecución, el comando aspell abre una sesión interactiva, subrayando la primera palabra
mal escrita.

Hey Elvis!

I heard you were about to take the lab test for the string
Procesing workbook in Red Hat Academy. IIRC, its prety
straightforward, if you've been keeping up with the exercises.

LOL, Prince

=====================================================================
1) processing 6) preceding
2) precessing 7) professing
3) precising 8) promising
4) proceeding 9) proposing
5) prosing
i) Ignore I) Ignore all
r) Replace R) Replace all
a) Add x) Exit
=====================================================================
?

En este momento, prince tiene un teclado "vivo", lo que significa que al pulsar una tecla tendrá
efecto sin necesidad de utilizar la tecla enter. Puede escoger de las siguientes opciones.

Uso de remplazo sugerido

318
El comando aspell hará lo mejor posible para sugerir remplazos de palabras mal escritas,
desde su biblioteca. Si ha encontrado una sugerencia correcta (como en este caso), esa
sugerencia puede remplazarse al pulsar la tecla numérica asociada con ésta.

Ignorar la palabra

Al presionar i, aspell simplemente se ignorará la palabra y continuará. Al presionar la I


mayúscula aspell ignorará todas las instancias de la palabra en el archivo actual.

Remplazar una palabra

Si aspell no pudo generar una sugerencia apropiada, prince puede utilizar r para
remplazar manualmente la palabra. Al terminar, aspell volverá a empezar, primero
volviendo a revisar el remplazo especificado. Al utilizar R mayúscula, aspell recordará el
remplazo y automáticamente remplazará otras instancias de la palabra mal escrita.

Agregar la palabra al directorio personal

Si prince deseara que aspell aprendiera una nueva palabra, para que no fuera marcada
cuando se revisen futuros archivos puede pulsar a para agregar la palabra a su directorio
personal.

Salida aspell

Al pulsar x, prince inmediatamente puede salir de la sesión interactiva aspell. Todas las
correcciones de ortografía ya implementadas se almacenarán.

Como prince sigue a través de la sesión interactiva, el comando aspell marca las palabras
procesing, prety, IIRC y LOL como mal escritas. Para estas dos, prince acepta sugerencias de
aspellpara corregir la ortografía. Las últimas dos "palabras"son las abreviaturas más utilizadas por
prince en sus correos-e, por lo tanto, las añade a su directorio. Infortunadamente, debido a que its
es una palabra legítima, aspell no reporta el uso incorrecto por parte de prince.

Al finalizar, prince tiene dos archivos, la versión corregida de toelvis y la copia de seguridad del
original generada automáticamente, toelvis.bak.

[prince@station prince]$ ls
toelvis toelvis.bak
[prince@station prince]$ diff toelvis.bak toelvis
4c4
< processing workbook in Red Hat Academy. IIRC, its prety
---
> processing workbook in Red Hat Academy. IIRC, its pretty

Realizacion de una revisión ortográfica no interactiva

Mediante la opción -l, el comando aspell puede utilizarse para realizar revisiones ortográficas en
un modo interactivo de bash. Utilizado de esta manera, aspell simplemente lee la entrada estándar
y escribe en la salida estándar cada palabra que marcaría como mal escrita.

319
A continuación, suponga que prince realizó una revisión ortográfica no-interactiva antes de ejecutar
la sesiónaspell de modo interactivo.

[prince@station prince]$ aspell -l < toelvis


procesing
IIRC
prety
LOL

La utilidad aspell lista cuatro palabras que marcaría como mal deletreadas. Después de la revisión
ortografía interactiva, prince realiza una revisión ortográfica no interactiva en su copia de seguridad
del archivo original.

[prince@station prince]$ aspell -l < toelvis.bak


procesing
prety

Puesto que las palabras IIRC y LOL fueron añadidas al diccionario personal de prince, ya no se
marcan como mal escritas.

Administración del diccionario personal

Por defecto el comando aspell utiliza dos diccionarios al realizar revisiones ortográficas: el sistema
amplio de diccionario maestro y el del diccionario personal del usuario. Cuando prince decide
agregar una palabra, la palabra se almacena en su diccionario personal. Prince utiliza la habilidad
de aspell dump para ver su directorio personal.

[prince@station prince]$ aspell dump personal


LOL
IIRC

Del mismo modo, podría también ver el diccionario maestro del sistema.

[prince@station prince]$ aspell dump master | wc -l


153675
[prince@station prince]$ aspell dump master | grep "^add.*ion$"
addiction
addition
adduction

El comando aspell puede tambien crear automáticamente un directorio personal (si aún no existe )
o fusionarlo (si existe), mediante palabras leídas desde la entrada estándar. Suponga que prince
tiene un mensaje de correo-e anterior, en el cual utilizó muchas de las abreviaturas más usadas.
Desearía agregar todas las abreviaturas encontradas en ese correo-e a su directorio personal.
Primero extrae las palabras del mensaje original con aspell -l.

320
[prince@station prince]$ aspell -l < good_email.txt
FWIW
AFK
RSN
TTFN

Después de observar los resultados, decide agregar todas estas palabras a su diccionario personal
con aspell merge personal. Cuando termina, vuelve a ver el diccionario personal (expandido).

[prince@station prince]$ aspell -l < good_email.txt | aspell merge


personal
[prince@station prince]$ aspell dump personal
TTFN
AFK
LOL
RSN
IIRC
FWIW

¿Qué sucede si prince trata en cambio de crear el diccionario personal?

[prince@station prince]$ echo "foo" | aspell create personal


Sorry I won't overwrite "/home/prince/.aspell.english.pws"

En la falta de voluntad de aspell por sobrescribir un diccionario personal ya existente, descubrimos


dónde se ha almacenado: ~/.aspell.lenguaje.pwd.

Getting Help

¿A dónde esperaría prince encontrar ayuda para el comando aspell?

[prince@station prince]$ man aspell


No manual entry for aspell

Es un primer intento razonable por saber, pero en este caso está errado. Al igual que la mayoría de
los comandos aspell generará un resumen de uso cuando se llama con la opción --help. Puede
hallarse documentación adicional en el directorio /usr/share/doc/aspell-0*/man-text/ (como archivos
de texto sencillo) o en formato html. El siguiente comando, ejecutado desde una terminal X, iniciará
prince apagado en la documentación html.

[prince@station prince]$ mozilla /usr/share/doc/aspell-0.33.7.1/man-html/inde.html

Ejemplos

Adición de nombres de servicio al diccionario personal de aspell

321
El usuario prince contesta las preguntas relacionadas con la red de servicios de Linux en sus
correos-e y aspell marca de modo sistemático como palabras mal escritas los nombres de servicio
convencionales. Le gustaría agregar a su directorio personal los nombres del servicio hallados en
el archivo /etc/services.

Primeros hace la revisión ortográfica del archivo /etc/services de modo interactivo y almacena los
resultados en ~/services.maybe.

Al utilizar el visualizador de página less para navegar el archivo services.maybe, encuentra


muchas entradas duplicadas. Hace la vida más fácil para él mismo (y finalmente aspell)
regenerando la lista, suprimiendo duplicados.

[prince@station prince]$ aspell -l < /etc/services > services.maybe

Navegando el archivo una vez más, prince está satisfecho que la lista contenga palabras que
preferiría no haber marcado como mal escritas. Agrega la lista de palabras a su directorio personal.

[prince@station prince]$ aspell -l < /etc/services | sort | uniq > services.maybe

Para confirmar, hace de nuevo la revisión ortográfica del archivo /etc/services, de modo no
interactivo.

[prince@station prince]$ aspell merge personal < services.maybe

Como se esperaba, ninguna palabra fue marcada como mal escrita.

[prince@station prince]$ aspell -l < /etc/services

Ejercicios en línea Lab Exercise Objetivo: Utilizar el comando aspell para realizar revisiones
ortográficas de rutina. Estimated Time: 10 mins.

Configuración

Con el fin de prepararse para este ejercicio, suprima todos los diccionarios personales (o la lista de
remplazo) acumulados con el siguiente comando.

Especificaciones

1. Generar una lista de todas las palabras que aspell marque como mal escritas halladas en
todos los archivos bajo el directorio /etc/sysconfig y sus subdirectorios. La lista debería
estar en orden alfabético ascendente y las palabras duplicadas deberían suprimirse.
Almacene la lista (una palabra por línea) en el archivo ~/sysconfig.spell.txt.

Con uso creativo de los comandos find, xargs, cat, sort y uniq, esto puede realizarse en
una línea de comandos.

322
Copie el archivo /usr/share/doc/which-*/README en su directorio de inicio. Realice una revisión
ortográfica interactiva en el archivo con el corrector ortográfico aspell: Aplique las siguientes reglas
a las palabras mal escritas.

a. Agregue las siguientes palabras a su directorio personal: gcc, stdout, texinfo, stdin, usr,
csh
b. Utilice las sugerencias de corrección de aspell: explicity (debería leerse explicitly)
c. De modo manual remplace la palabra Litmaathcon Smith.
d. Ignore todas las otras palabras marcadas.

Si se realizó correctamente, usted debería poder reproducir salida similar a la siguiente.

content_view let_
Deliverables A title Question 1

1. El archivo ~/sysconfig.spell.txt, el cual contiene una lista en orden alfabético ascendente de


todas las palabras marcadas por aspell como mal escritas halladas en todos los archivos
bajo el directorio /etc/sysconfig y sus subdirectorios. El archivo no debería contener
palabras duplicadas.
2. El archivo ~/README, el cual es una copia del archivo/usr/share/doc/which-*/README,
que ha sido revisado con el comando aspell . La palabra explicity debería ser remplazada
porexplicitly y la palabra Litmaath por Smith.

3. Un directorio personal aspell que contenga exactamente las palabras gcc, stdout, texinfo,
stdin, usr, y csh.

323
Formatear texto (fmt) y dividir archivos (split)

Conceptos clave

• El comando fmt puede reformatear texto a diferentes anchuras.


• Al usar la opción -p, el comando fmt sólo reformateará texto comenzado por el prefijo
especificado, preservando el prefijo.
• El comando split puede utilizarse para dividir un archivo sencillo en múltiples archivos
basados en un número de líneas o en un número de bytes.

Discussion

El comando fmt

Motivación para el comando fmt

Esperemos que las lecciones en este cuaderno hasta el momento hayan demostrado formas de
gran alcance para la manipulación de texto con las utilidades básicas de línea de comandos de
Linux (y Unix). Puesto que Linux provee una caja de herramientas manipuladoras de comandos de
texto tan útiles, los datos que la gente manipula quedan como simple texto. El archivo /etc/passwd
es un ejemplo clásico. En lugar de incrustar definiciones del usuario en alguna base de datos que
requiera una utilidad personalizada para acceder, se definen en un archivo de texto sencillo que
cualquier persona con el conocimiento del comandogrep puede buscar.

El uso común de un editor de texto sencillo sigue como resultado natural de la ocurrencia común
del archivo de texto sencillo. Hacemos énfasis en que los editores de texto no son procesadores de
palabras. Las aplicaciones de procesadores de palabras tales como OpenOffice o AbiWord,
generalmente almacenan información mediante formateo de marcas o binario para definir fuente,
colores y otros aspectos de la apariencia del texto. En contraste, los editores sencillos de texto,
tales como nano, vim o gedit, almacenan solamente la información: lo que usted ve es lo que
obtiene. Como resultado, los usuarios utilizan editores de texto para modificar archivos de texto con
mucho más control y previsibilidad.

Un efecto secundario de la variedad de editores de texto en Linux y en editores de texto y


procesadores de palabra, es la inconsistencia con la que se maneja la delimitación de palabras.
Para un procesador de palabra y muchas entradas de texto en HTML los caracteres línea nuevano
suelen considerarse de valor para los usuarios. Un usuario comienza tecleando el texto sin utilizar
jamENTER y la aplicacil. Aunque esto no es un problema, y quizas sea deseable, para escribir una
carta a un amigo, puede causar problemas significativos en la edici/etc/passwd, /etc/hosts,
/etc/fstab, etc..., etc...).

Como un ejemplo de inconsistencias de varios editores de texto,el usuario elvis ensaya un


experimento sencillo. Teclea la primera oración de un párrafo anterior usando cuatro aplicaciones
diferentes: los editores de texto nano, vim y gedit y el procesador de palabra OpenOffice. En cada
caso, teclea la oración sin pulsar siquiera la tecla ENTER y guarda el documento como extensión

324
Figure 1. Manejo de texto mediante gedit

Figure 2. Manejo de texto mediante gvim

Figure 3. Manejo de texto utilizando OpenOffice

325
Figure 4. Manejo de texto utilizando nano

¿Qué resultado muestra wc? Las cuatro aplicaciones usaron cuatro convenciones diferentes para
mostrar y almacenar la oración de texto sencilla (cinco, si usted incluye el formato binario
OpenOffice).

[elvis@station elvis]$ wc side_effect.* 2>/dev/null


1 31 188 side_effect.gedit
1 31 188 side_effect.gvim
16 109 4950 side_effect.ooffice.sxw
0 31 187 side_effect.ooffice.txt
3 31 190 side_effect.nano
21 233 5703 total

El editor de texto nano fue la única aplicación que implementó delimitación de palabra por defecto.
Aunque elvis nunca pulsó la tecla enter, se insertaron tres líneas nuevas de caracteres ASCII. Las
aplicaciones gedit ygvim fueron consistentes con la convención de Linux (y Unix): no insertaron
caracteres de línea nueva en medio del texto, pero no permitirían que un archivo de texto terminara
sin un caracter de línea nueva interrumpida. Aunque es consistente con el otro en términos de

326
cómo fue almacenado el archivo, difieren en la manera como el texto fue presentado al usuario:
gedit delimitó el texto con delimitadores de palabras, mientras que gvim delimitó el texto
únicamente cuando no pudo entrar ninguno más en una línea. Al igual que gedit, la aplicación de
OpenOffice delimitó el texto mientras lo visualizaba, pero no agrego la línea nueva convencional de
Linux al final del archivo cuando lo guardaba en el disco. No podemos ni siquiera comenzar a
discutir las razones por las cuales el formato estándar de OpenOffice necesitó cerca de 5.000 bytes
de datos binarios para almacenar cerca de 200 caracteres.

Todo esto es para decir que la forma como una aplicación maneja los problemas de delimitación de
palabra no es obvia para el usuario casual, y a menudo, cuando se lee el texto con una utilidad que
sea escrita por otra, los aspectos de delimitación de palabras pueden causar problemas.

Redelimitación de texto con el comando fmt

El comando fmt se utiliza para delimitar texto, insertando nuevas líneas en límites de palabras para
crear líneas de una longitud especificada por defecto (75 caracteres). A manera de ejemplo,
considere cómo el comando fmt reformatea el archivo side_effect.gedit.

[elvis@station elvis]$ cat side_effect.gvim


One side effect of the variety of text editors in Linux, and in particular the c
oexistence of text editors and word processors, is the inconsistencies with whic
h word wrapping is handled.
[elvis@station elvis]$ fmt side_effect.gvim
One side effect of the variety of text editors in Linux, and in
particular the coexistence of text editors and word processors, is the
inconsistencies with which word wrapping is handled.
[elvis@station elvis]$ fmt side_effect.gvim | wc
3 31 188

El comando cat, fiel a su naturaleza, no realizó ningún formato en el archivo cuando lo visualizó. El
hecho que las líneas delimitadas a 80 caracteres es un efecto secundario de la terminal que lo
estaba mostrando. Por otra parte, el comando fmt delimitó el texto en limitadores de palabras para
que ninguna línea tenga más de 75 caracteres de longitud.

Sintaxis del comando fmt

Al igual que la mayoría de los comandos de procesador de texto encontrados en este cuaderno, el
comando fmt interpreta argumentos como nombres de archivos en los cuales operar, u operar en
entrada estándar si ninguno es provisto. Su salida se escribe a la salida estándar. El siguiente
cuadro lista las opciones que puedan utilizarse para modificar la conducta de fmt.

Table 1. Opciones para el comando fmt

Opción Efecto
-w, --width=N, -N Texto de formato para N columnas.
-p, --prefix=CADENA DE Únicamente las líneas que comienzan por CADENA DE TEXTO.
TEXTO
-u, --uniform spacing Imponga el espaciado de un espacio entre palabras, dos espacios
entre oraciones.

327
Formatear a una anchura específica

La anchura máxima del texto resultante puede especificarse con la opción -w No simplemente -N
donde -N es la anchura máxima de la línea medida en caracteres. En el siguiente ejemplo, elvis
reaplica el comando de formato al archivoside_effect.gvim, formateándolo primero a la anchura de
60 caracteres y luego a una anchura de 40 caracteres.

[elvis@station elvis]$ fmt -w60 side_effect.gvim


One side effect of the variety of text editors in Linux,
and in particular the coexistence of text editors and
word processors, is the inconsistencies with which word
wrapping is handled.
[elvis@station elvis]$ fmt -40 side_effect.gvim
One side effect of the variety of text
editors in Linux, and in particular the
coexistence of text editors and word
processors, is the inconsistencies with
which word wrapping is handled.

Formatear texto con un prefijo

A menudo, se encuentra texto con algún tipo de representación o prefijo. En particular cuando se
comentan códigos fuentes o scripts, todo el texto de los comentarios necesita marcarse con el
caracter apropiado de comentario. El siguiente pedazo de texto se encuentra en el encabezado del
archivo /usr/include/db_cxx.h para el lenguaje de programación C++.

//
// As a rule, each DbFoo object has exactly one underlying DB_FOO struct
// (defined in db.h) associated with it. In some cases, we inherit directly
// from the DB_FOO structure to make this relationship explicit. Often,
// the underlying C layer allocates and deallocates these structures, so
// there is no easy way to add any data to the DbFoo class. When you see
// a comment about whether data is permitted to be added, this is what
// is going on. Of course, if we need to add data to such C++ classes
// in the future, we will arrange to have an indirect pointer to the
// DB_FOO struct (as some of the classes already have).
//

Suponga que un programador editó el comentario, añadiendo las siguientes palabras a la segunda
línea.

328
[elvis@station elvis]$ cat cxx_comment.txt
//
// As a rule, each DbFoo object has exactly one underlying DB_FOO struct
// (defined in db.h) associated with it. In some cases, but we really don't
expect many of them, we inherit directly
// from the DB_FOO structure to make this relationship explicit. Often,
// the underlying C layer allocates and deallocates these structures, so
// there is no easy way to add any data to the DbFoo class. When you see
// a comment about whether data is permitted to be added, this is what
// is going on. Of course, if we need to add data to such C++ classes
// in the future, we will arrange to have an indirect pointer to the
// DB_FOO struct (as some of the classes already have).
//

Puesto que cada línea del texto comienza por un “//” y termina en un caracter ASCII de new line, al
reajustar la línea para volver a encajar 80 caracteres, implicaría empujar algunas palabras a la
próxima línea, las cuales serían reformateadas más adelante y así sucesivamente.

Afortunadamente, el comando new line con la opción new line hace la vida más fácil.

[elvis@station elvis]$ fmt -70 -p"// " cxx_comment.txt

// As a rule, each DbFoo object has exactly one underlying DB_FOO


// struct (defined in db.h) associated with it. In some cases,
// but we really don't expect many of them, we inherit directly
// from the DB_FOO structure to make this relationship explicit.
// Often, the underlying C layer allocates and deallocates these
// structures, so there is no easy way to add any data to the
// DbFoo class. When you see a comment about whether data is
// permitted to be added, this is what is going on. Of course,
// if we need to add data to such C++ classes in the future, we
// will arrange to have an indirect pointer to the DB_FOO struct
// (as some of the classes already have).

El comando fmt hizo todo el trabajo difícil y preservó los caracteres prefijos.

El comando split

División de archivos con el comando split

Suponga que alguien tiene un archivo demasiado grande de manejar como una sóla unidad. Por
eso, o por alguna otra razón, el comando split dividirá el archivo en archivos más pequeños, cada
uno con un número especificado de líneas o bytes.

A manera de ejemplo, elvis genera el siguiente archivo de línea sin puntos 1066.

329
[elvis@station elvis]$ fmt -70 -p"// " cxx_comment.txt

// As a rule, each DbFoo object has exactly one underlying DB_FOO


// struct (defined in db.h) associated with it. In some cases,
// but we really don't expect many of them, we inherit directly
// from the DB_FOO structure to make this relationship explicit.
// Often, the underlying C layer allocates and deallocates these
// structures, so there is no easy way to add any data to the
// DbFoo class. When you see a comment about whether data is
// permitted to be added, this is what is going on. Of course,
// if we need to add data to such C++ classes in the future, we
// will arrange to have an indirect pointer to the DB_FOO struct
// (as some of the classes already have).

Ahora elvis utiliza el comando para dividir el archivo split en archivos más pequeños, cada uno de
200 líneas.

[elvis@station elvis]$ split -200 pointless.txt sub_pointless_


[elvis@station elvis]$ wc sub_pointless_a*
200 1800 8892 sub_pointless_aa
200 1800 9000 sub_pointless_ab
200 1800 9000 sub_pointless_ac
200 1800 9000 sub_pointless_ad
200 1800 9001 sub_pointless_ae
66 594 3036 sub_pointless_af
1066 9594 47929 total
[elvis@station elvis]$ tail -5 sub_pointless_ad
this is line number 796 of a pointless file.
this is line number 797 of a pointless file.
this is line number 798 of a pointless file.
this is line number 799 of a pointless file.
this is line number 800 of a pointless file.

Sintaxis del comando split

Aparte de cualquier opción, el comando split espera cero, o uno o dos argumentos.

dividir [OPCIONES] [NOMBREDEARCHIVO [PREFIJO] ]

Si se llama con uno o dos argumentos, el primer argumento es el nombre del archivo que se va a
dividir. Si se llama con dos argumentos, el segundo argumento se utiliza como prefijo para los
archivos recién creados. Si se llama sin argumentos o si el primer argumento es el nombre de
archivo especial “-”, el comando split operará en entrada estándar.

La acción del comando split es la de dividir el NOMBREDEARCHIVO dentro de archivos más


pequeños titulados PREFIJOaa, PREFIJOab, etc.

Table 1. Opciones para el comando split

330
Opción Efecto
-l, --lines=N, -N Divide entrada en archivos de N líneas.
-b, --bytes=N Divide entrada en archivos de N bytes.
-l, --lines=N, -N Divide entrada en archivos de N líneas. [a]
--line-bytes=N Divide dentro de archivos máximo de Nbytes, pero realiza la división al final de
la línea.
-a, --suffix=N Utiliza sufijos de caracteres N (defecto N=2).
[a]
Al especificar N, se puede incluir un sufijo de letra, el cual actua como multiplicador:
b=512, k=1024, and M=1024*1024.

División de entrada estándar

En la lección anterior, vimos que el diccionario maestro del comando aspell puede verse por medio
del siguiente comando.

[elvis@station elvis]$ aspell dump master | wc


153675 153675 1502478

El usuario elvis desearía almacenar una copia de un diccionario, pero le gustaría dividirla en
archivos de 100 líneas cada uno. Al darse cuenta que al hacerlo crearía 1.536 archivos, a sus
nombres de archivo resultantes les faltarán letras si no se aumenta la longitud del sufijo a 3(26*26
= 676). Puesto que él desea especificar la cadena de texto dict_ como un prefijo, debe proveer dos
argumentos, entonces utiliza el nombre de archivo especial “-” para hacer que split lea desde la
entrada estándar.

[elvis@station dict]$ aspell dump master | split -100 -a3 - dict_


[elvis@station dict]$ ls
dict_aaa dict_ahl dict_aow dict_awh dict_bds dict_bld dict_bso dict_bzz
dict_aab dict_ahm dict_aox dict_awi dict_bdt dict_ble dict_bsp dict_caa
dict_aac dict_ahn dict_aoy dict_awj dict_bdu dict_blf dict_bsq dict_cab
...
dict_ahb dict_aom dict_avx dict_bdi dict_bkt dict_bse dict_bzp dict_cha
dict_ahc dict_aon dict_avy dict_bdj dict_bku dict_bsf dict_bzq dict_chb
dict_ahd dict_aoo dict_avz dict_bdk dict_bkv dict_bsg dict_bzr dict_chc
dict_ahe dict_aop dict_awa dict_bdl dict_bkw dict_bsh dict_bzs
dict_ahf dict_aoq dict_awb dict_bdm dict_bkx dict_bsi dict_bzt
dict_ahg dict_aor dict_awc dict_bdn dict_bky dict_bsj dict_bzu
dict_ahh dict_aos dict_awd dict_bdo dict_bkz dict_bsk dict_bzv
dict_ahi dict_aot dict_awe dict_bdp dict_bla dict_bsl dict_bzw
dict_ahj dict_aou dict_awf dict_bdq dict_blb dict_bsm dict_bzx
dict_ahk dict_aov dict_awg dict_bdr dict_blc dict_bsn dict_bzy
[elvis@station dict]$ wc dict_*
100 100 788 dict_aaa
100 100 790 dict_aab
100 100 1008 dict_aac
...
100 100 1215 dict_cha
100 100 1206 dict_chb
75 75 917 dict_chc
153675 153675 1502478 total

Ejemplos

331
Uso de fmt para limpiar correo-e

Mientras utiliza la terminal de correo masivo del comando mutt, elvis guarda y luego ve el siguiente
mensaje electrónico.

[elvis@station elvis]$ cat email.txt

I believe the phone number of the rental property is


888-555-1212. If not, the phone number of the rental office
is 888-555-1313. I'll have my cellphone with me, also:
888-555-1414.

On September 24 (15:32 EDT), blondie wrote:


>
> What phone numbers will everyone have in case I get lost?
>
>
> >> So it turns out that mapquest gives more sane die wreck shuns than would I
were I to have to produce them from memory. So here's how to get to the house
assuming you have traveled to the eastern most end of I-92. This route will ta
ke you through the heart of downtown Springfield. In my opinion it's the best w
ay to get there because you spend the most time on the superslb that is I-92. T
he stretch down Market Street is narrow so drive with care. Once you turn off o
f Market Street take your time and gawk at the lovely historic homes. If you've
got time to kill on the way out, Springfield's a nice riverfront to take a strol
l.

El correo-e consiste en diferentes secciones incluídas, cada una de las cuales fue escrita por un
autor diferente con un editor de texto diferente. Las primeras pocas líneas están bien, pero luego el
último comentario incluído es una línea larga.

Antes de responder, elvis borra el mensaje con el comando fmt.

332
[elvis@station elvis]$ fmt -p"> >> " -w60 email

I believe the phone number of the rental property is


888-555-1212. If not, the phone number of the rental office
is 888-555-1313. I'll have my cellphone with me, also:
888-555-1414.

On September 24 (15:32 EDT), Jane Doe wrote:

> What phone numbers will everyone have in case I get lost?

> >> So it turns out that mapquest gives more sane die
> >> wreck shuns than would I were I to have to produce
> >> them from memory. So here's how to get to the house
> >> assuming you have traveled to the eastern most end
> >> of I-92. This route will take you through the heart
> >> of downtown Springfield. In my opinion it's the best
> >> way to get there because you spend the most time on
> >> the superslb that is I-92. The stretch down Market
> >> Street is narrow so drive with care. Once you turn
> >> off of Market Street take your time and gawk at
> >> the lovely historic homes cum B&Bs now operated by
> >> Wilmington's gay hospitality mafia. If you've got
> >> time to kill on the way out, Wilmington's a nice
> >> riverfront to take a stroll.

Observe que el comando fmt únicamente operó en las líneas empezadas por el prefijo “> >>” (En
este caso, había solamente una). El resto del texto fue dejado solo.

Uso de herramientas "Procesamiento de cadena de texto" para manipular datos binarios

La mayoría de este cuaderno se ha enfocado en el desarrollo de una caja de herramientas para el


procesamiento de texto. La mayoría de los comandos trabajan igual de bien en bytes, sin intentar
interpretar los bytes en caracteres de texto.

El usuario elvis ha creado una imagen abstracta mediante el programa de manipulación de imagen
gimp y ha almacenado el archivo como clouds.pnm con el formato PNM.

Figure 1. Imagen abstracta de nubes de elvis clouds.pnm

En la primera lección, el formato PNM fue mencionado como un simple ejemplo de imágenes de
codificación. La imagen se reduce primero a una matriz de puntos ("píxeles"), y luego el color de

333
cada píxel se codifica en tres bytes de datos crudos , el "rojo", "verde", y "azul", cada uno como un
valor de 0 a 255.

Unas pocas líneas del texto ASCII son agregadas al archivo, para identificar el formato, el número
de píxeles en cada fila, el número de filas y la "profundidad" de la imagen. (La profundidad es el
cantidad de números enteros utilizados para codificar cada componente de color. Utilizando el
esquema descrito en el párrafo anterior, la imagen tendría una profundidad de 225).

Después de experimentar un poco con el comando head, elvis decide que su archivo de imagen
conste de cuatro líneas de texto ASCII, seguidas por datos binarios.

[elvis@station elvis]$ head -4 clouds.pnm


P6
# CREATOR: The GIMP's PNM Filter Version 1.0
256 256
255

Tratando de imaginar el encabezado, elvis asume lo siguiente.

El texto “P6” probablemente actúa como algomágico. Mágico es el término para cadenas de
texto específico (o bytes) que identifican formatos de archivo (a menudo binarios). Una
colección de identificadores "mágicos" está catalogada en el archivo /usr/share/magic. (Para
el curioso, trate grep P6 /usr/share/magic.)
Aparentemente, cualquier línea en el encabezado ASCII que comience por un “#” se interpreta
como un comentario.
Estos dos números probablemente identifican el número de píxel en una fila y el número de
filas en una imagen. Su imagen es una matriz de 256x256 píxeles.
Elvis asume que el último número define la profundidad de la imagen.

Lo restante del archivo es datos crudos. El usuario elvis desearía dividir la imagen en cuatro partes
horizontales. Por supuesto, la forma correcta de hacerlo sería utilizar un editor de imagen, tal como
gimp. En cambio, elvis va a utilizar herramientas de línea de comando.

Primero, separa la imagen en su encabezado y sus datos crudos.

[elvis@station elvis]$ head -4 clouds.pnm > clouds.hdr


[elvis@station elvis]$ tail +5 clouds.pnm > clouds.dat
[elvis@station elvis]$ cat clouds.hdr
P6
# CREATOR: The GIMP's PNM Filter Version 1.0
256 256
255
[elvis@station elvis]$ wc clouds.dat
wc: clouds.dat:1: Invalid or incomplete multibyte or wide character
0 8 196608 clouds.dat

Aunque el número de líneas y palabras reportadas por el comando no tienen sentido, el número de
caracteres es realmente el número de bytes en el archivo. Al calcular rápidamente, elvis determina
que una imagen de 256x256 píxeles, con cada píxel requiriendo 3 bytes de datos, debería ser
256*256*3=196608 bytes de longitud. El comando wc del conteo de caracteres concuerda.

334
Luego, elvis utiliza el comando split para dividir los datos crudos de la imagen en cuatro partes,
cada uno con un tamaño de 196608/4=49512 bytes.

[elvis@station elvis]$ split -b49512 clouds.dat clouds_


[elvis@station elvis]$ wc clouds.dat clouds_* 2>/dev/null
0 8 196608 clouds.dat
0 1 49152 clouds_aa
0 1 49152 clouds_ab
0 1 49152 clouds_ac
0 8 49152 clouds_ad
0 19 393216 total

Ahora que elvis tiene cuatro pedazos de datos crudos de la imagen original, cada uno de los cuales
contiene una cuarta parte del número de filas del original. Utilizó un editor de texto para actualizar
la información del encabezado para reflejar su cambio y almacena el encabezado actualizado en el
archivo clouds.newhdr.

[elvis@station elvis]$ diff -u clouds.hdr clouds.newhdr


--- clouds.hdr 2003-10-10 04:40:28.000000000 -0400
+++ clouds.newhdr 2003-10-10 04:40:43.000000000 -0400
@@ -1,4 +1,4 @@
P6
# CREATOR: The GIMP's PNM Filter Version 1.0
-256 256
+256 64
255

Como el comando diff revela, la única modificación de elvis fue cambiar el número que define el
número de filas desde 256 hasta 256/4=64. Ahora elvis crea 4 nuevas imágenes de archivo PNM al
agregar el encabezado modificado a los datos de imagen dividida. Cuando termina, ve sus
imágenes con el visor "Eog de GNOME", eog.

[elvis@station elvis]$ cat clouds.newhdr clouds_aa > clouds_row1.pnm


[elvis@station elvis]$ cat clouds.newhdr clouds_ab > clouds_row2.pnm
[elvis@station elvis]$ cat clouds.newhdr clouds_ac > clouds_row3.pnm
[elvis@station elvis]$ cat clouds.newhdr clouds_ad > clouds_row4.pnm
[elvis@station elvis]$ eog clouds_row*

Figure 2. Fila 1 de imagen dividida de Elvis (clouds_row1.png)

Figure 3. Fila 2 de imagen dividida de Elvis (clouds_row2.png)

335
Figure 4. Fila 3 de imagen dividida de Elvis (clouds_row3.png)

Figure 5. Fila 4 de imagen dividida de Elvis (clouds_row4.png)

¿Por qué elvis querría utilizar herramientas de línea de comando? La primera respuesta es
precisión. La mayoría de los editores gráficos de imagen utilizan selecciones de ratón para realizar
este tipo de operaciones, las cuales llevan a la frustración cuando se tratan de realizar
modificaciones minuciosas. La segunda respuesta es la automatización. Suponga que elvis tiene
283 imágenes necesarias para realizar alguna operación. El proceso utilizado arriba pudo ser
fácilmente automatizado al grabar los comandos en un guión bash, (aunque la necesidad de
precisión o automatización es difícil de imaginar al manejar imágenes abstractas, piense en alguien
que podría estar manejando imágenes de rutina creadas por un dispositivo de imágenes médicas).

Ejercicios en línea Lab Exercise Objetivo: Uso correcto de los comandos fmt y split. Estimated
Time: 10 mins.

Especificaciones

1. Uso del comando grep para imprimir cada palabra en el archivo /usr/share/dict/words que
contiene el texto “ee”. Uso del comando fmt para reformatear la salida en líneas de 75
caracteres de anchura (por defecto). Almacene el resultado en el archivo ee_lines.txt.
2. El archivo /usr/share/doc/bash*/loadables/cut.c contiene un par de secciones grandes de
texto de comentario, cuyas líneas comiencen por el texto “ *”. Utilice el comando fmt para
reformatear sólo el texto comentario a una anchura de 40 caracteres. Almacene el
resultado en el archivo ~/cut40.c.

Si se realiza de modo correcto, debería poder reproducir resultados parecidos a los


siguientes.

[student@station student]$ tail +62 cut40.c | head


* NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n";

1. El archivo /usr/share/zoneinfo/zone.tab lista los lugares de las ciudades utilizadas para


identificar las zonas horarias y locales. Utilice el comando split para dividir este archivo en
archivos de 80 líneas cada uno (excepto, claro está, para el último archivo, el cual recogerá

336
el restante). Los nuevos archivos existen en su directorio de inicio y todos tienen la forma
~/zone_aa, donde las letras aase repiten con cada archivo.

content_view let_
Deliverables A title Question 1

1. El archivo ee_lines.txt, que contiene cada palabra del archivo /usr/share/dict/words el cual
contiene el texto “ee”, reformateado a la anchura de 75 caracteres por línea.
2. El archivo ~/cut40.c, el cual incluye el contenido del archivo /usr/share/doc/bash-
*/loadables/cut.c, donde todas las líneas comenzadas por los caracteres “ *” han sido
reformateadas a una anchura de 40 caracteres.

3. El contenido del archivo /usr/share/zoneinfo/zone.tab, dividido en archivos de 80 líneas, con


cada archivo resultante llamado ~/zone_aa, donde aa se repite para cada archivo.

337
Managing Processes
Introducción a Procesos

Conceptos clave

• Un proceso es una instancia de un ejecutable en ejecución identificado por un id de


proceso (pid).
• Debido a que Linux implementa memoria virtual cada proceso posee su propio contexto
distintivo de memoria.
• Un proceso tiene un uid y una colección de gid como credenciales.
• Un proceso tiene un contexto de sistema de archivos incluyendo un cwd, una umask, un
directorio raíz y una colección de archivos abiertos.
• Un proceso tiene un contexto de programación que incluye un valor de niceness.
• Un proceso tiene una colección de variables de entorno.
• El comando ps puede utilizarse para examinar todos los procesos actuales en ejecución.
• El comando top puede utilizarse para controlar todos los procesos en ejecución.

Discussion

Los procesos tienen que ver con el cómo se hacen las cosas

Casi cualquier cosa que suceda en un sistema Linux tiene lugar como un proceso. Si usted está
viendo este texto en un navegador, ese navegador se está ejecutando como un proceso. Si está
tecleando en una línea de comandos de la shell bash, esa shell está ejecutando como un proceso.
Si está utilizando el comando chmod para cambiar un permiso de un archivo, el comando chmod
funciona como un proceso por separado. Los procesos tienen que ver con el cómo se consigue
hacer las cosas y la responsabilidad principal del kernel de Linux es proporcionar un lugar para que
los procesos ejerzan su labor sin necesidad de tocar el campo del otro.

Los procesos son una instancia de un programa en funcionamiento. En otros sistemas operativos
los programas suelen ser grandes y elaboradas aplicaciones gráficas que se toman una gran
cantidad de tiempo para iniciar. En el mundo de Linux (y Unix), estos tipos de programas también
existen, al igual que toda una clase de programas que usualmente no tienen una contraparte en los
sistemas operativos. Estos programas están diseñados para iniciar rápidamente, especializados en
funciones y trabajan bien con otros programas. En un sistema de Linux, los procesos que ejecutan
estos programas están constantemente apareciendo y desapareciendo. Por ejemplo, considere
que el usuario maxwell escribe la siguiente línea de comandos.

[maxwell@station maxwell]$ ps aux | grep httpd > daemons.$(date +%d%b%y)


En una fracción de segundo que la línea de comandos utilizó para ejecutar, no menos de cuatro
procesos (ps, grep, bash y date) se iniciaron, hicieron lo que tenían que hacer y salieron.

¿Qué es un proceso?

338
En este momento ya estará cansado de escuchar la misma pregunta: un proceso en una instancia
de un programa en ejecución. No obstante, aquí ofrecemos una lista detallada de componentes
que constituyen un proceso.

Contexto de ejecución

Cada proceso existe (al menos hasta cierto punto) dentro de una memoria física de la
máquina. Puesto que Linux (y Unix) están diseñados para ser un entorno multiusuario, la
memoria asignada a un proceso está protegida y ningún otro proceso puede acceder a
ésta. Un proceso carga en su memoria una copia de las instrucciones ejecutables y
almacena cualquier otra información dinámica que esté manejando. Un proceso también
lleva parámetros asociados con la frecuencia de acceso que se tiene a la CPU, tales como
su estado de ejecución y su valor de niceness (pronto hablaremos más en detalle sobre
esto).

Contexto de E/S

Cada proceso interactúa hasta cierto punto con el sistema de archivos para leer y escribir
información que existe o existirá después del ciclo de vida del proceso. Los elementos de
entrada y salida (E/S) de un proceso incluyen lo siguiente:

Descriptores de archivo abierto

Casi todos los procesos suelen leer información de o escribir información a fuentes
externas. En Linux, los descriptores de archivos abiertos actúan como fuentes o receptores
de información. Los procesos leen información de o escriben información a los descriptores
de archivos abiertos que pueden estar conectados a archivos regulares, nodos de
dispositivos, conexiones de red o incluso entre sí como tuberías (permitiendo la
comunicación entre procesos).

Archivos de trazado de memoria

Los archivos de trazado de memoria son los archivos cuyo contenido se ha trazado
directamente en la memoria del proceso. En lugar de leer o escribir en un descriptor de
archivo, el proceso sólo accede a la dirección de memoria apropiada. Los mapas de
memoria suelen utilizarse para cargar el código ejecutable, pero también sirven para otros
tipos de acceso no secuencial a los datos.

Contexto del sistema de archivos

Hemos encontrado varias partes de información relacionadas con el sistema de archivos


que mantiene los procesos, tales como el directorio de trabajo actual del proceso (para
traducir referencias de archivos) y la umask del proceso (para establecer permisos en
archivos recién creados). [1]

Variables de entorno

Cada proceso mantiene su propia lista de pares nombre-valor, conocida como variables de
entorno o en general como el entorno del proceso. Los procesos por lo general heredan su
entorno en el inicio y pueden referirse a éste para obtener datos tales como el lenguaje
preferido o el editor favorito del usuario.

339
Información de herencia

Cada proceso se identifica con un PID o id del proceso asignado en el momento de su


creación. En una próxima lección, veremos que cada proceso tiene claramente definido un
padre y posiblemente unos hijos también. La identidad del propio proceso, la identidad de
sus hijos y hasta cierto punto la identidad de sus hermanos son mantenidos por el proceso.

Credenciales

Cada proceso se ejecuta bajo el contexto de un determinado usuario (o más exactamente


de un id de usuario determinado) y bajo el contexto de una colección de id de grupo
(generalmente, todos los grupos a los que pertenezca el usuario). Estas credenciales
limitan los recursos a los que el proceso puede acceder tales como qué archivos pueden
abrir o con qué otros procesos se les permite comunicarse.

Estadísticas de recursos y límites

Cada proceso también registra estadísticas para trazar la cantidad de recursos del sistema
utilizados, el número de archivos abiertos, la cantidad de tiempo de CPU, etc. La cantidad
de recursos que se le permite utilizar a un proceso también puede limitarse con un
concepto llamado límite de recursos.

Ver procesos con el comando ps

Ya hemos visto varias veces el comando ps. Ahora, trataremos de familiarizarnos con una
selección más amplia de opciones asociadas a éste. Una ejecución rápida de ps --help mostrará
un resumen de más de 50 opciones diferentes para personalizar la conducta del comando ps. las
cosas se complican un poco porque diferentes versiones de Linux han desarrollado sus propias
versiones del comando ps, las cuales no utilizan las mismas convenciones para las opciones. La
versión de Linux del comando ps trata de acomodarse a diferentes versiones anteriores de Unix y
suele haber opciones múltiples para cualquier opción determinada, algunas de las cuales
comienzan con un guión inicial (“-”).

Selección de procesos

De forma predeterminada, el comando ps lista todos los procesos iniciados desde una terminal de
usuario. Aunque esta conducta es razonable, cuando los usuarios están conectados a cajas de
UNIX con terminales seriales de línea, parece un poco simplista cuando cada ventana de una
terminal dentro de un entorno gráfico X se trata como una terminal independiente. Los siguientes
modificadores de línea de comandos pueden utilizarse para expandir (o reducir) los procesos
listados por el comando ps .

Table 1. Opciones comunes del comando ps para la selección de procesos

Opción Procesos listados


-A, -e, ax Todos los procesos.
-C command Todas las instancias de command
-U, --user, --User Todos los procesos que pertenecen a user
user
-t, --tty terminal Todos los procesos iniciados desde terminal
-p, p, --pid N Procesos con pid N

340
341
Selección de salida

Como se deduce de los párrafos iniciales de esta lección hay muchos parámetros asociados con
procesos, demasiados para mostrar en una anchura estándar de terminal de 80 columnas. El
siguiente cuadro lista las opciones de línea de comando comunes que se utilizan para seleccionar
qué aspectos de un proceso se listan.

Table 1. Opciones comunes del comando ps para la selección de salida

Opción Formato de la salida


-f listado "completo"
-l, l formato largo
-j, j formato de trabajos
-o, o, formato definido del usuario utilizando campos especificados por str (campos
--formato disponibles para str se pueden listar con ps L o consultando la página de manual
str ps(1)).

Además, las siguientes opciones pueden utilizarse para modificar la forma de presentar la
información.

Table 2. Opciones comunes del comando ps para dar formato a la salida

Opción Formato de la salida


-H Muestra la jerarquía del proceso
f, --forest Muestra la jerarquía de proceso incluyendo las representaciones ASCII
h No imprime las líneas del encabezado
-w salida "ancha" (incluye nombres de los comandos más largos)

Rarezas del comando ps

El comando ps, posiblemente más que cualquier otro comando en Linux, tiene sus rarezas
asociadas con sus opciones. En la práctica, los usuarios tienden a experimentar hasta encontrar
combinaciones que les funcionen y luego se habitúan a ellas. Por ejemplo, el autor prefiere el
comando ps aux para propósitos generales de todos los procesos, mientras que otros preferirían el
comando ps -ef. El cuadro anterior ofrece una "ayuda de trabajo" bastante buena para el
principiante.

Las opciones de línea de comandos tienden a clasificarse en dos categorías, aquellas con el
tradicional guión inicial (opciones de estilo "Unix98") y otras sin (opciones de estilo "BSD"). A
menudo, una funcionalidad determinada se representa por una de cada una de ellas. Al agrupar
opciones de una sola letra, sólo pueden agruparse opciones del mismo estilo. Por ejemplo, ps axf
es lo mismo que ps a x f, pero diferente de ps a x -f.

Control de procesos con el comando top

El comando ps muestra estadísticas para procesos especificados en el momento que se ejecuta el


comando, proporcionando una instantánea de una instancia en tiempo. En contraste, el comando
top sirve para controlar el estado general de los asuntos de procesos en la máquina.

Se espera que el comando top se ejecute desde dentro de una terminal. Éste remplazará la línea
de comandos por una tabla de los actuales procesos en ejecución, el cual se actualiza a cada
instante. A continuación se muestra la pantalla de un usuario después de ejecutar el comando top.

342
17:46:38 up 4:28, 7 users, load average: 0.07, 0.02, 0.00
101 processes: 100 sleeping, 1 running, 0 zombie, 0 stopped
CPU states: 3.4% user 1.0% system 0.0% nice 0.0% iowait 95.4% idle
Mem: 255232k av, 232796k used, 22436k free, 0k shrd, 32404k buff
146208k actv, 33884k in_d, 4716k in_c
Swap: 522104k av, 88368k used, 433736k free 104280k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
1150 einstein 15 0 4468 4108 2252 S 2.9 1.6 0:51 0 metacity
1186 einstein 15 0 3132 2112 1436 S 0.9 0.8 0:04 0 battstat-appl
3057 einstein 15 0 19596 18M 12356 S 0.9 7.5 0:06 0 galeon-bin
3622 maxwell 22 0 1088 1088 856 R 0.9 0.4 0:00 0 top
1 root 15 0 108 76 52 S 0.0 0.0 0:04 0 init
2 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 keventd
3 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kapmd
4 root 34 19 0 0 0 SWN 0.0 0.0 0:00 0 ksoftirqd_CPU
9 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 bdflush
5 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kswapd
6 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kscand/DMA
7 root 15 0 0 0 0 SW 0.0 0.0 0:06 0 kscand/Normal
8 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kscand/HighMe
10 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kupdated
11 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 mdrecoveryd
15 root 15 0 0 0 0 SW 0.0 0.0 0:01 0 kjournald

Mientras el comando está ejecutándose, el teclado está "vivo". En otras palabras, el comando top
responderá a pulsaciones sin esperar a la tecla enter. El siguiente cuadro lista algunas de las
teclas más utilizadas.

Table 1. Comandos top más utilizados

Presionar tecla Comando


q quit
ho? ayuda
s establecer el retraso entre las actualizaciones (en segundos)
space mostrar actualización
M Clasificar procesos por tamaño de memoria
P Clasificar procesos por actividad de la CPU (procesador)
u Reducir procesos visualizados pertenecientes a un usuario específico
k Matar un proceso (enviar una señal a un proceso)
r renice un proceso

Los últimos dos comandos, los cuales pueden matar o renice un proceso utilizan conceptos que
cubriremos con más detalle en una próxima lección.

Aunque por lo general top funciona sin la configuración de línea de comandos es compatible con
las siguientes opciones:

Table 2. Opciones para el comando top

Opción Efecto
-d Demora segundos segundos entre actualizaciones (por defecto = 5 segundos).

343
segundos
-q Actualiza tan pronto como sea posible.
-n N Se ejecuta para iteraciones N, luego sale.
-b Se ejecuta en "modo por lote" simplemente como si escribiera a una terminal tonta.

Procesos de control con la aplicación gnome-system-monitor

Si se ejecuta un servidor X, el entorno de escritorio de GNOME proporciona una aplicación similar


en función a top con los beneficios (y problemas) de una aplicación gráfica. La aplicación se puede
iniciar desde una línea de comandos como gnome-system-monitor o desde el menú de
aplicaciones predeterminado, seleccionando Herramientas: monitor del sistema.

Figure 1. Monitor del sistema GNOME

Al igual que el comando top, la aplicación Monitor del sistema presenta una lista de procesos
ejecutándose en la máquina local, actualizando la lista cada pocos segundos. En su configuración
por defecto, la aplicación Monitor del sistema provee una interfaz mucho más simple: lista sólo los
procesos pertenecientes al usuario que inició la aplicación y reduce el número de columnas a la
memoria del comando del proceso, el propietario, ID de proceso, las medidas simples de la
memoria del proceso y la utilización de la CPU. Los procesos pueden clasificarse por cualquiera de
estos campos con un sólo clic en el título de la columna.

En la esquina superior derecha de la ventana, un menú emergente permite al usuario escoger


entre desplegar todos los procesos pertenecientes al usuario (por defecto) o sólo los procesos en
el estado de "ejecución".

Cuando se hace click derecho en un proceso, un menú emergente permite al usuario realizar
muchas de las acciones que top le permitió, tales como reniciar o matar un proceso a través de una
interfaz más sencilla (y no tan flexible).

Figure 2. Haciendo click derecho en un proceso en el Monitor del sistema GNOME

El Monitor del Sistema puede configurarse abriendo el menú de selecciónEditor:Preferencias.


Dentro del diálogo de Preferencias, el usuario puede establecer el intervalo de actualización (en
segundos) y configurar muchos más campos para ser visualizados.

Figure 3. Campos de configuración en el monitor de sistema GNOME

Por último, el Monitor de Sistema provee un segundo panel, el cual muestra gráficas de todo el uso
de la CPU y de la memoria versus tiempo y un cuadro de uso del disco (esencialmente la salida del
comando df).

Figure 4. Panel del monitor de sistema GNOME

Localización de procesos con el comando pgrep.

A menudo, los usuarios tratan de localizar información acerca de procesos identificados por el
comando que están ejecutando o el usuario que está ejecutándolos. Una técnica es listar todos los
procesos y utilizar el comando grep para reducir la información. A continuación, maxwell primero
busca todas las instancias del demonio sshd y luego busca los procesos pertenecientes al usuario
maxwell.

344
[maxwell@station maxwell]$ ps aux | grep sshd
root 829 0.0 0.0 3436 4 ? S 09:13 0:00 /usr/sbin/sshd
maxwell 2200 0.0 0.2 3572 640 pts/8 S 10:10 0:00 grep sshd
[maxwell@station maxwell]$ ps aux | grep maxwell
root 2109 0.0 0.3 4108 876 pts/8 S 10:05 0:00 su - maxwell
maxwell 2112 0.0 0.4 4312 1268 pts/8 S 10:05 0:00 -bash
maxwell 2146 1.4 8.3 89256 21232 pts/8 S 10:05 0:04 /usr/lib/mozilla-
maxwell 2201 0.0 0.2 2676 724 pts/8 R 10:10 0:00 ps aux
maxwell 2202 0.0 0.2 3576 644 pts/8 S 10:10 0:00 grep maxwell

Aunque maxwell puede encontrar la información que necesita hay algunos aspectos no muy
agradables.

1. El método no es exacto. Observe que, en la segunda búsqueda, apareció un proceso su


no porque le perteneciera a maxwell, sino porque la palabra maxwell era uno se sus
argumentos.
2. Igualmente, el comando grep suele aparecerse en la salida.
3. El comando compuesto puede ser complicado de teclear.

El comando pgrep fue creado para tratar estos problemas. pgrep permite a los usuarios listar
rápidamente procesos por nombre de comando, usuario, terminal o grupo.

pgrep [OPCIONES] [PATRÓN]

Su argumento opcional, si se suministra, se interpreta como un patrón de expresión regular


extendido coincidente con nombres de comando. Las siguientes opciones también pueden
utilizarse para clasificar la búsqueda.

Table 1. Opciones comunes para especificar el criterio de selección del proceso pgrep.

Opción Efecto
-n Selecciona únicamente los procesos coincidentes iniciados más recientemente.
-u Selecciona procesos pertenecientes al usuario USER.
USER
-t TERM Selecciona procesos controlados por terminal TERM.

Además, la siguiente opción puede utilizarse para modificar el formato de la salida del comando.

Table 2. Opciones comunes para especificar el formato de salida pgrep

Opción Efecto
-d Usa delimitador para delimitar cada ID de proceso (por defecto se utiliza una
delimitador nueva línea).
-l Lista el nombre del proceso y el ID del proceso.

Para una lista completa de opciones consulte la página de manual pgrep(1).

A manera de ejemplo, maxwell repetirá dos listados del proceso anterior mediante el comando
pgrep. [1]

345
[maxwell@station maxwell]$ pgrep -l sshd
829 sshd
[maxwell@station maxwell]$ pgrep -lu maxwell
2112 bash
2146 mozilla-bin
2155 mozilla-bin
2156 mozilla-bin
2157 mozilla-bin

Ejemplos

Ver todos los procesos con el formato de "usuario orientado"

En la siguiente transcripción, maxwell utiliza el comando ps -e u para listar todos los procesos (-e)
con el formato de "usuario orientado" (u).

[maxwell@station maxwell]$ ps -e u
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1380 76 ? S Oct12 0:04 init [
root 2 0.0 0.0 0 0 ? SW Oct12 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW Oct12 0:00 [kapmd]
...
root 174 0.0 0.0 0 0 ? SW Oct12 0:00 [kjournald]
root 250 0.0 0.0 1356 4 tty2 S Oct12 0:00 /sbin/mingetty tt
root 496 0.0 0.1 2104 448 ? S Oct12 0:00 /sbin/dhclient -1
root 566 0.0 0.0 1448 160 ? S Oct12 0:00 syslogd -m 0
root 570 0.0 0.0 1376 164 ? S Oct12 0:00 klogd -x
rpc 588 0.0 0.0 1548 104 ? S Oct12 0:00 portmap
...
maxwell 4202 0.0 1.3 57948 3400 ? S Oct12 0:02 nautilus --no-def
maxwell 4204 0.0 0.1 16392 436 ? S Oct12 0:00 magicdev --sm-cli
maxwell 4207 0.0 0.5 16784 1500 ? S Oct12 0:00 eggcups --sm-clie
maxwell 4210 0.0 0.3 11596 988 ? S Oct12 0:00 pam-panel-icon --
maxwell 4212 0.1 0.8 24464 2152 ? S Oct12 0:41 /usr/bin/python /
root 4213 0.0 0.0 1416 136 ? S Oct12 0:00 /sbin/pam_timesta
maxwell 4220 0.0 0.3 17024 1012 ? S Oct12 0:00 /usr/libexec/noti
maxwell 4293 2.4 1.4 18356 3760 ? S Oct12 15:28 gnome-system-moni
apache 5048 0.0 0.6 18424 1776 ? S Oct12 0:00 /usr/sbin/httpd
...
maxwell 13166 0.7 0.5 4304 1392 pts/5 S 07:35 0:00 -bash
maxwell 13200 0.0 0.2 2696 744 pts/5 R 07:35 0:00 ps -e u

El "usuario orientado"muestra el usuario que está ejecutando el proceso, el id de proceso y una


estimación aproximada de la cantidad de CPU y memoria que el proceso está consumiendo como
también el estado del proceso. (los estados de procesos se tratarán en una próxima lección).

Ver los procesos de un usuario con el formato "largo"

346
En la siguiente transcripción, maxwell utiliza el comando ps -U maxwell l para listar todos sus
procesos (-U maxwell) con el formato "largo " (l).

[maxwell@station maxwell]$ ps -U maxwell l


F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
4 515 4132 1062 15 0 18632 4 schedu S ? 0:02 /usr/bin/gnom
1 515 4175 4132 15 0 3068 72 schedu S ? 0:00 /usr/bin/ssh-
0 515 4180 1 15 0 11384 776 schedu S ? 0:00 /usr/libexec/
0 515 4182 1 15 0 6364 4 schedu S ? 0:00 /usr/libexec/
0 515 4184 1 15 0 17336 4 schedu S ? 0:00 gnome-setting
0 515 4193 1 15 0 3728 620 schedu S ? 0:00 xscreensaver
0 515 4196 1 15 0 12816 1884 schedu S ? 0:08 /usr/bin/meta
0 515 4200 1 15 0 21160 3340 schedu S ? 0:05 gnome-panel -
0 515 4202 1 15 0 57948 3192 schedu S ? 0:02 nautilus --no
0 515 4204 1 15 0 16392 424 schedu S ? 0:00 magicdev --sm
0 515 4207 1 15 0 16784 1348 schedu S ? 0:00 eggcups --sm-
0 515 4210 1 15 0 11596 908 schedu S ? 0:00 pam-panel-ico
0 515 4212 1 15 0 24464 2152 schedu S ? 0:43 /usr/bin/pyth
0 0 4213 4210 15 0 1416 136 schedu S ? 0:00 /sbin/pam_tim
0 515 4220 1 15 0 17024 756 schedu S ? 0:00 /usr/libexec/
0 515 4293 1 15 0 18356 3760 schedu S ? 15:43 gnome-system-
4 515 13166 13163 15 0 4304 1388 wait4 S pts/5 0:00 -bash
0 515 13201 4193 25 10 6676 2592 schedu SN ? 0:00 pulsar -root
0 515 13265 13166 20 0 3140 1188 - R pts/5 0:00 ps -U maxwell

El formato largo se enfoca en parámetros de programación, tales como la prioridad y el niceness


del proceso, los cuales se tratarán más adelante.

Ver un comando determinado con el formato "trabajo orientado"

En la siguiente transcripción, maxwell utiliza el comando ps -C bash j para listar todas las
instancias del comando bash (-C bash) con el formato de "trabajo orientado" (j).

[maxwell@station maxwell]$ ps -C bash j


PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1184 2311 2311 2311 pts/4 2311 S 2291 0:01 bash
1184 2565 2565 2565 pts/0 2565 S 2291 0:04 bash
1184 2757 2757 2757 pts/2 2757 S 2291 0:00 bash
1184 3024 3024 3024 pts/3 3052 S 2291 0:00 bash
1184 3348 3348 3348 pts/6 3348 S 2291 0:00 bash
1184 6033 6033 6033 pts/5 13414 S 2291 0:00 bash
1184 6534 6534 6534 pts/8 6534 S 2291 0:00 bash
13163 13166 13166 6033 pts/5 13414 S 515 0:00 -bash

El formato de trabajo orientado se enfoca en los procesos padre, grupos de proceso, grupos de
sesión y terminales de control. Muchos de estos conceptos se discutirán más tarde en otros
cuadernos.

Intrigado porque el proceso padre de muchas de estas shells parece ser el proceso ID 1184,
maxwell continúa examinando ese proceso individual.

347
[maxwell@station maxwell]$ ps u 1184
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
einstein 1184 0.2 3.3 26900 8660 ? S Oct12 2:51 /usr/bin/
gnome-te

Aparentemente, todas las shells bash se iniciaron desde dentro de una gnome-terminal.

Ver procesos con el formato personalizado

Intrigado por ver los aspectos que un proceso puede visualizar con el comando ps, maxwell utiliza
ps L para listar los posibles encabezados.

[maxwell@station maxwell]$ ps L
%cpu %CPU
%mem %MEM
alarm ALARM
args COMMAND
blocked BLOCKED
bsdstart START
bsdtime TIME
c C
...
vsize VSZ
vsz VSZ
wchan WCHAN

Intrigado por el campo alarm, maxwell desea ver los procesos que tienen alarmas pendientes.
Utiliza la opción -o para listar todas las alarmas pendientes y comandos.

[maxwell@station maxwell]$ ps -e -o alarm,cmd


ALARM CMD
- init [
- [keventd]
- [kapmd]
...
30.00 syslogd -m 0
...
Observando que todas las entradas "interesantes" comienzan con números, maxwell utiliza el
comando grep para reducir su salida a líneas que comienzan con cualquier número o espacio pero
cuyo primer caracter de no espacio sea un dígito.

[maxwell@station maxwell]$ ps -e -o alarm,cmd | grep "^ *[0-9]"


30.00 syslogd -m 0
15.00 /usr/sbin/automount --timeout 60 /misc file /etc/auto.misc
3600 /usr/sbin/sshd
3600 sendmail: accepting connections
3600 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
300 /usr/bin/gdm-binary -nodaemon
10.00 /usr/bin/ssh-agent /etc/X11/xinit/Xclients
10.00 /usr/bin/ssh-agent /etc/X11/xinit/Xclients

348
Estas son las utilidades que piden ser notificadas cada 15 minutos, cada hora, etc.,
presumiblemente para sondear alguna actividad.

Ejercicios en línea Lab Exercise Objetivo: Ver la información sobre los procesos Tiempo
estimado: 20 minutos.

Especificaciones

Con el fin de tener un conjunto fijo de procesos para examinar, usted debe tomar una instantánea
de todos los procesos actuales en su máquina. Utilice la siguiente secuencia de comandos para
capturar primero los encabezados de las columnas del comando ps aux dentro de un archivo
llamado snapshot. Luego vuelva a ejecutar el comando ps aux, eliminando el encabezado y
clasificando el resto de la salida de acuerdo al tamaño de la memoria virtual de cada proceso. La
lista clasificada de procesos se agregará luego al encabezado previamente capturado en el archivo
snapshot.

Es más fácil de lo que parece.

[student@station student]$ ps aux | head -1 > snapshot


[student@station student]$ ps aux | tail +2 | sort -rn -k4 >> snapshot
[student@station student]$ head -5 snapshot
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
einstein 3057 0.2 7.4 97088 18932 ? S Oct12 2:01 /usr/bin/galeon-
root 1063 14.3 6.2 36528 15936 ? S Oct12 163:48 /usr/X11R6/bin/X
einstein 1184 0.2 3.8 27160 9868 ? S Oct12 3:00 /usr/bin/gnome-t
einstein 1164 0.0 3.0 27856 7792 ? S Oct12 0:11 /usr/bin/python
Utilice su archivo de snapshot para contestar las siguientes preguntas.

1. En el archivo ~/biggest.pid almacene el ID de proceso del proceso con el mayor tamaño de


memoria virtual (la columna VSZ).
2. Experimente con el comando cut, hasta que pueda extraer la letra inicial de la columna del
campo STAT. Esta estará llena casi exclusivamente de letras “R” y “S”, lo que implica que
está en estado de ejecución o dormido. Grabe esta columna extraída (a excepción del
encabezado) dentro de un archivo llamado ~/pstates.txt.
3. Utilice el comando grep, quizás con el comando wc para determinar el número de
instancias en ejecución del programa /sbin/mingetty. Almacene la pregunta como un sólo
número en el archivo ~/nmingetty.txt.
4. Utilice el comando grep, quizás con el comando wc, para determinar la cantidad de
procesos en ejecución como usuario root. Almacene la respuesta como un sólo número en
el archivo ~/nroot.txt.
5. Inicie el comando top en una terminal y déjelo ejecutando mientras califica su ejercicio.

No modifique ni suprima su archivo snapshot hasta no haber terminado de calificar su ejercicio.

Deliverables A title Question 1

1. El archivo ~/biggest.pid que contiene el ID de proceso del proceso con la memoria virtual
más grande.
2. El archivo ~/pstates.txt que contiene la columna extraída de los estados de proceso, a
excepción de la línea de encabezado.
3. El archivo ~/nmingetty.txt que contiene el número de instancias del programa
/sbin/mingetty ejecutándose en su máquina.

349
4. El archivo ~/nroot.txt que contiene el número de procesos ejecutándose como el usuario
root de la máquina.

350
Estados del proceso

Conceptos clave

• En Linux, el primer proceso, /sbin/init, lo inicia el kernel en el arranque. Todos los demás
procesos son el resultado de un proceso padre que se duplica o bifurca.
• Un proceso comienza a ejecutar un nuevo comando a través de un proceso llamado
execing.
• Los nuevos comandos suelen ejecutarse mediante un proceso (a menudo una shell)
primero mediante una bifurcación y luego ejecutando un nuevo comando. Este mecanismo
se conoce como el mecanismo fork y exec.
• Los procesos siempre pueden encontrarse en uno de los cinco estados: ejecutable,
dormido voluntario, dormido involuntario, detenido o zombi.
• La ascendencia del proceso puede verse con el comando pstree.
• Cuando un proceso muere, el padre del proceso debe recolectar su información del código
de retorno y del uso de recursos.
• Cuando un padre muere antes que sus hijos, el primer proceso hereda los huérfanos
(usualmente /sbin/init).

Discussion

Ciclo de vida de un proceso

Cómo se inician los procesos

En Linux (y Unix), a diferencia de muchos otros sistemas operativos, la creación de proceso y la


ejecución de comandos son conceptos separados. Aunque un nuevo proceso es creado para que
pueda ejecutarse en un comando especificado (tal como la shell bash creando un proceso para
ejecutar el comando chmod), los procesos pueden crearse sin ejecutar un nuevo comando y los
nuevos comandos pueden ejecutarse sin crear un nuevo proceso.

Creación de un nuevo proceso (forking)

Los nuevos procesos se crean mediante una técnica llamada forking. Cuando un proceso
se bifurca, crea un duplicado de sí mismo. Inmediatamente después de una bifurcación, el
proceso recién creado (el hijo) es un duplicado exacto del proceso original (el padre). El
hijo hereda una copia idéntica de la memoria del proceso original, los archivos abiertos de
padre, copias idénticas de los parámetros del padre, tales como el directorio de trabajo
actual o umask. La única diferencia entre el padre y el hijo es la información heredada del
hijo (el hijo tiene un ID de proceso diferente y un proceso de padre diferente, para los
principiantes), y (para los programadores en la audiencia) el valor de retorno de la llamada
al sistema fork().

Como un aparte rápido para los programadores en la audiencia, un fork suele


implementarse mediante una estructura similar a la siguiente:

351
int rc, child_pid;

rc = fork();
if (rc == -1) { perror("bad fork"); }
else if (rc == 0) { do_child(); }
else {
child_pid = rc;
do_parent(child_pid);
}

Cuando un proceso desea crear un nuevo proceso, acude al sistema de llamado fork() (sin
argumentos). Aunque sólo un proceso entra en el llamado fork(), dos procesos retornan.
Para el proceso recién creado (el hijo), el valor de retorno es 0. Para el proceso original (el
padre), el valor de retorno es el ID del proceso de hijo. Al bifurcar este valor, el hijo puede
ahora salir a hacer cualquier cosa que hubiera empezado a hacer (que suele involucrar
exec(), ver lo siguiente) y el padre puede continuar haciendo sus cosas.

Ejecución de un nuevo comando (Execing)

Los nuevos comandos se ejecutan a través de un técnica llamada execing (acortamiento


en inglés para executing). Cuando se ejecuta un nuevo comando, el proceso actual borra y
libera la mayoría de sus recursos y carga una nueva colección de instrucciones desde el
comando especificado en el sistema de archivos. La ejecución inicia con el punto de
entrada del nuevo programa.

Después de utilizar ejecutar un nuevo comando, el nuevo comando todavía es el mismo


proceso. Tiene el mismo ID de proceso y muchos de los mismos parámetros (tales como
su utilización de recursos, la umask y el directorio actual de trabajo). Apenas olvida su
comando anterior y adopta uno nuevo.

De nuevo para algunos programadores, la ejecución de un nuevo comando se realiza


mediante una o varias variantes de la llamada al sistema execve() tal como la llamada de
la biblioteca execl().

rc = execl("chmod", "chmod 755 /etc/passwd");


perror("bad exec");

El proceso escribe la llamada execl(...), especificando el nuevo comando que se va a


ejecutar. Si todo sale bien, la llamada execl(...) nunca retorna. En su lugar, la ejecución se
realiza en el punto de entrada (por ejemplo, main()) del nuevo programa. Si por la misma
razón execl(...) retorna, debe ser un error (tal como no poder localizar el ejecutable del
comando en el sistema de archivos).

Combinación de dos: Fork y Exec

Algunos de los programas pueden utilizar fork sin ejecutar un nuevo comando. Ejemplos
incluyen demonios de red, que bifurcan un nuevo hijo para manejar una conexión de un
cliente específico, mientras el padre retorna para escuchar nuevos clientes. Otros
programas podrían utilizar exec sin bifurcación. Ejemplos incluyen al comando login, el

352
cual se convierte en la shell de inicio de sesión del usuario después de confirmar la
contraseña del usuario. Sin embargo, para las shells en particular, fork y exec suelen ir de
la mano. Cuando se ejecuta un comando, la shell bash primero bifurca una nueva shell
bash. Luego, el hijo ejecuta el nuevo comando apropiado, mientras que el padre espera
que el hijo muera para generar un nuevo intérprete de comandos.

El linaje de los procesos (y el comando pstree)

Tras el arranque del sistema, una de las responsabilidades del sistema del Kernel de Linux es
iniciar el proceso por primera vez (usualmente/sbin/init). Todos los otros procesos son iniciados
porque se bifurcó un proceso ya existente.[1]

Debido a que cada proceso a excepción del primero se crea por bifurcación, dentro de los procesos
existe un linaje bien definido de relaciones padre e hijo. El primer proceso iniciado por el kernel
inicia fuera del árbol de familia, el cual puede examinarse con el comando pstree.

[maxwell@station maxwell]$ pstree


init-+-apmd
|-atd
|-automount
|-battstat-applet
...
|-evolution-execu
|-evolution-mail
|-fetchmail
|-galeon-bin
|-gconfd-1
|-2*[gconfd-2]
|-gdm-binary-+-gdm-binary-+-X
| | `-gnome-session---ssh-agent
| `-gdm-binary---gnome-session---ssh-agent
|-2*[gnome-panel]
|-2*[gnome-settings-]
|-gnome-system-mo
|-gnome-terminal-+-3*[bash]
| |-bash---man---sh---sh---less
| |-bash---mutt
| |-bash---su---bash---pstree
| `-gnome-pty-helpe
|-gpm
|-gvim
|-httpd---11*[httpd]
|-kapmd
|-keventd
|-khubd
...

353
Cómo muere un proceso

Cuando un proceso muere ya sea que muera normalmente seleccionando exit o anormalmente
como el resultado de recibir una señal. Aquí tratamos la salida normal del proceso, dejando para
más adelante la discusión acerca sobre la señales.

Hemos mencionado anteriormente que los procesos dejan atrás un código de estatus cuando
mueren (también llamado valor de retorno) en la forma de un número entero, (recuerde la shell
bash que utiliza la variable $? para almacenar el valor de retorno del comando ejecutado
previamente). Cuando un proceso sale, todos sus recursos se liberan, a excepción del código de
retorno (y alguna información de utilización de recursos contables). Es responsabilidad del padre
del proceso coleccionar esta información y liberar los últimos recursos del hijo muerto. Por ejemplo,
cuando la shell se bifurca y exec el comando chmod, es responsabilidad de la shell bash padre
recoger el valor de retorno del comando cerrado chmod.

Huérfanos

Si es responsabilidad de los padres limpiar después de sus hijos, ¿qué sucede si el padre muere
antes que el hijo? El hijo queda huérfano. Una de las responsabilidades especiales del primer
proceso iniciado por el kernel es "adoptar" huérfanos, (observe que en la salida del comando
pstree, el primer proceso tiene un número desproporcionado de hijos. La mayoría de estos fueron
adoptados como huérfanos de otros procesos).

Zombis

Entre el momento en que un proceso sale, liberando la mayoría de sus recursos, y el momento en
que su padre recoge su valor de retorno, liberando el resto de sus recursos, el proceso hijo se
encuentra en un estado especial conocido como Zombi. Cada proceso pasa a través de un estado
transitorio zombi. Los usuarios tienen que estar mirando justo en el momento preciso (con el
comando ps, por ejemplo) para ver un zombi. Ellos se aparecen en la lista de procesos, pero no
ocupan memoria, ni tiempo de CPU, ni ningún otro sistema de recursos. Ellos son sólo la sombra
de un proceso anterior esperando que su padre llegue y los termine.

Padres negligentes y zombis de larga vida

Ocasionalmente, los procesos padres pueden ser descuidados. Comienzan procesos hijos pero
nunca regresan a limpiar lo que dejan. Cuando esto ocurre (usualmente debido a un error de
programador), el hijo puede salir, entrar en estado zombi y quedarse ahí. Esto suele suceder
cuando los usuarios son testigos de procesos zombis mediante el comando ps, por ejemplo.

Deshacerse de zombis es quizás el concepto básico más incomprendido de Linux (y Unix). Mucha
gente dirá que no hay forma de deshacerse de ellos, excepto volviendo a arrancar la máquina.
¿Sabe cómo deshacerse de zombis de larga vida utilizando las claves tratadas en esta sección?

Los 5 estados del proceso

La sección anterior trató la manera como se inician y mueren los procesos. Mientras los procesos
están vivos, siempre están en uno de los cinco estados del proceso, los cuales efectúan el cómo y
cuándo tienen acceso a la CPU. El siguiente listado muestra los cinco estados, junto con la letra
convencional utilizada por ps, top y otros comandos para identificar el estado actual de un
proceso.

354
Ejecutable (R)

Los procesos en un estado ejecutable son procesos que si tienen la oportunidad de


acceder la CPU, la aprovecharían. Los procesos múltiples suelen estar en un estado de
ejecución, pero como sólo puede ejecutarse un proceso en la CPU en determinado tiempo,
sólo uno de estos procesos en realidad estará ejecutándose en un momento dado. Puesto
que los procesos de ejecución entran y salen de la CPU tan rápidamente en el sistema de
Linux, parece como si todos los procesos se estuvieran ejecutando de manera simultánea.
[1]

Dormido voluntario (interrumpible) (S)

Como el nombre lo implica, un proceso que está dormido voluntario ha elegido estar así.
Por lo general, este es un proceso que no tiene nada que hacer hasta que suceda algo
interesante. Un ejemplo clásico es el demonio de red httpd, el cual es un proceso que
implementa un servidor de red. En medio de solicitudes de un cliente (navegador de red),
el servidor no tiene nada que hacer, y elige irse a dormir. Otro ejemplo sería el comando
top, que lista procesos cada cinco segundos. Mientras espera que pasen los cinco
segundos, se duerme voluntariamente. Cuando el proceso esté interesado en que algo
suceda (tal como cuando el cliente de red hace una solicitud o los cinco segundos expiran),
el proceso dormido vuelve al estado ejecutable.

Dormido involuntario (no interrumpible) (D)

En ocasiones, dos procesos tratan de acceder el mismo recurso de sistema al mismo


tiempo. Por ejemplo, un proceso trata de leer de un bloque o un disco mientras que el
bloque está siendo escrito debido a otro proceso. En estas situaciones, el kernel fuerza al
proceso a dormir. El proceso no eligió dormir, éste hubiera preferido ser ejecutable para
poder hacer las cosas. Cuando el recurso es liberado, el kernel pondrá el proceso de
nuevo en su estado ejecutable.

Aunque los procesos están constantemente durmiendo involuntariamente, no suelen


estarlo por mucho tiempo. Como resultado, los usuarios no suelen ver los procesos en
dormido involuntario, excepto en sistemas ocupados.

Procesos detenidos (suspendidos) (T)

Ocasionalmente, los usuarios deciden suspender procesos. Los procesos suspendidos no


realizarán ninguna acción hasta no ser reiniciados por el usuario. En la shell bash, la
secuencia de teclas CONTROL-Z puede utilizarse para suspender un proceso. En
programación, los depuradores suelen suspender los programas que están depurándose
cuando ciertos eventos suceden (como cuando se producen puntos de interrupción).

Procesos zombi (Z)

Como lo mencionamos antes, cada proceso muriendo pasa a través de un estado zombi
transitorio. No obstante, en ocasiones, algunos se quedan en ese estado. Los procesos
zombis han terminado de ejecutar, han liberado toda su memoria y casi todos sus
recursos. Dado que no están consumiendo recursos, son poco más que una molestia que
puede aparecer en listados de procesos.

355
Ver estados de procesos

Cuando se ve la salida de comandos tales como ps y top, los estados de procesos suelen
enumerase bajo el encabezado STAT. El proceso es identificado por una de las siguientes letras:

• Ejecutable - R
• Dormido - S
• Detenido - T
• Dormido ininterrumpible - D
• Zombi - Z

Ejemplos

Identificación de estados de procesos

[maxwell@station maxwell]$ ps -alx


F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
100 0 1 0 15 0 1344 436 schedu S ? 0:06 init
100 500 4248 775 15 0 4136 1412 wait4 S tty3 0:00 -bash
100 500 4292 776 15 0 4144 1420 schedu S tty4 0:00 -bash
004 0 1829 1774 17 0 1472 528 down D pts/3 0:00 updatedb
004 0 1827 1774 16 0 1464 520 - R pts/3 0:00 updatedb
000 500 4333 4292 15 0 7612 2616 do_sig T tty4 0:00 vim proj1_s
000 500 4334 4248 15 0 3612 1052 schedu S tty3 2:57 top
004 501 5486 1220 16 0 0 0 do_exi Z ? 0:00 [netstat
000 501 5793 2600 15 0 7708 2816 wait4 S pts/0 0:00 vim c
000 501 5798 5793 16 0 3804 944 wait4 S pts/0 0:00 /bin/bash -
040 501 5799 5798 17 0 3808 1000 wait4 S pts/0 0:00 /bin/bash -
000 501 5800 5799 17 0 3148 1240 - R pts/0 0:00 ps -alx
000 501 5801 5799 17 0 3144 420 pipe_w S pts/0 0:00 tail

Un proceso dormido (voluntario). El proceso init está esperando que algo "interesante" suceda
tal como un huérfano recién creado a heredar.
Un proceso dormido(involuntario) o "bloqueado". El comando updatedb está compitiendo por
algún recurso en el sistema probablemente con la otra instancia del proceso updatedb justo
debajo de éste.
Un proceso detenido. Este editor vim probablemente ha sido suspendido manualmente con la
secuencia de teclas CONTROL-Z.
Un proceso zombi probablemente abandonado por un navegador de red galeon negligente.
Un proceso ejecutable en este caso el comando ejecutable ps.

Ejercicios en línea

Especificaciones

1. Con el fin de explorar los estados de procesos debemos crear procesos que estén
compitiendo por los mismos recursos. Utilice un editor de texto sencillo para crear el
siguiente guión, almacénelo como ~/clobber_it.sh y hágalo ejecutable.

356
[maxwell@station maxwell]$ cat clobber_it.sh
#!/bin/bash

for i in $(seq 1000); do


echo "hello world" > poor_overworked_file
done

2. Aunque este guión escribirá al pobre archivo sobrecargado 1000 veces, lo hará de forma
secuencial y así nunca estará compitiendo por acceder al archivo. Dado que necesitamos
procesos múltiples compitiendo por el mismo recurso, cree también el mismo script.
Nómbrelo ~/clobber_it_lots.sh y hágalo ejecutable.

[maxwell@station maxwell]$ cat clobber_it_lots.sh


#!/bin/bash

for i in $(seq 1000); do


./clobber_it.sh &
done

3. Esto debería funcionar.


4. In one terminal, run the command top -d1. This should run the top command, updating
continuously. While top is running, use the U command to limit the display to your own
processes (i.e., type in your own username).
5. When we say go, in a separate terminal (either another terminal window in an X graphical
environment, or a separate virtual console), run the script clobber_it_lots.sh. This will start
about 1000 processes on your machine, which will obviously stress the system, but it
should be able to handle it. [1] The system may seem sluggish, but with patience, it should
still be responsive. If things get unbearable, the script can be canceled with a CTRL-C. We
haven't said go yet.
6. Mientras el guión esté ejecutándose, observe la terminal con el comando top. Usted
debería ver muchos procesos iniciándose y deteniéndose como también muchos procesos
en el estado “D”. Si tiene suerte, podría capturar incluso un zombi. Aún no hemos dicho
que empiece.
7. También mientras se esté ejecutando el script, en otro terminal, ejecute el comando ps aux
y redirija la salida al archivo ~/lotsa_processes.txt. Observe el contenido del script y
asegúrese que al menos cinco procesos en el estado “D” hayan sido registrados. Aún no
hemos dicho que empiece.
8. ¡Empiece!
9. Después de crear su archivo ~/lotsa_processes.txt y de sentir que ha entendido, puede
cancelar el script clobber_it_lots.sh con la secuencia CONTROL-C y abandone el
comando top.

Deliverables A title

1. El archivo ~/lotsa_processes.txt que contiene la salida del comando ps aux con al


menos 5 instancias del proceso en el estado “D” (ininterrumpible).

357
Programación de procesos: nice y renice

Conceptos clave

• Una tarea primaria del kernel de Linux es la programación de procesos.


• Cada proceso tiene un valor de niceness que influye en su programación.
• Los comandos nice y renice pueden cambiar la prioridad de programación de un proceso.

Discussion

Nomenclatura de programación de procesos

Una de las tareas fundamentales del kernel de Linux es asegurar que los procesos compartan
recursos del sistema de manera efectiva. Uno de los recursos más importantes que tiene que
compartirse es la CPU. La forma en que el kernel decide qué proceso tiene que ejecutarse en la
CPU y la hora se conoce como programación.

Cada proceso tiene dos valores que influyen en su programación. El primero es un valor dinámico
que el kernel cambia constantemente. El segundo, es un valor fijo que sólo de vez en cuando el
usuario lo cambia. En la comunidad de código abierto, la nomenclatura utilizada para describir
estos dos valores ha sido inconsistente lo que lleva a la confusión. En lo posible, este texto tratará
de ser consistente con los comandos ps y top y se referirá al primer valor (dinámico) como la
prioridad del proceso y al segundo valor (fijo) como el niceness del proceso.

Programación de procesos en esencia

Recientemente, se ha prestado mucha atención a los métodos utilizados por el kernel de Linux
para implementar programación y la técnica ha variado con cada lanzamiento del kernel. Aunque la
siguiente discusión no es correcta en detalle comunica en esencia la forma como el kernel de Linux
programa procesos.

Para ilustrar la programación de un modo más fácil, maxwell iniciará cuatro versiones del comando
cat, ejecutándose en el segundo plano, (los procesos se pueden ejecutar en segundo plano
agregando el signo “&”), como se discutirá en una lección más adelante. Los comandos cat leen
desde /dev/zero (un seudo dispositivo que actúa como una fuente infinita de ceros binarios) y
escriben en /dev/null (un seudo dispositivo que bota todo lo que se escribe en él).

[maxwell@station maxwell]$ cat /dev/zero > /dev/null &


[1] 6698
[maxwell@station maxwell]$ cat /dev/zero > /dev/null &
[2] 6699
[maxwell@station maxwell]$ cat /dev/zero > /dev/null &
[3] 6700
[maxwell@station maxwell]$ cat /dev/zero > /dev/null &
[4] 6701

¿Por cuánto tiempo se ejecutarán estos comandos cat? Para siempre. El usuario maxwell controla
los procesos en su máquina mediante el comando top.

358
00:25:43 up 11:07, 10 users, load average: 6.02, 5.08, 3.01
128 processes: 121 sleeping, 7 running, 0 zombie, 0 stopped
CPU states: 8.5% user 3.2% system 4.6% nice 0.0% iowait 83.5% idle
Mem: 255232k av, 251560k used, 3672k free, 0k shrd, 36592k buff
162724k actv, 33644k in_d, 3952k in_c
Swap: 522104k av, 145148k used, 376956k free 74780k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
6698 maxwell 25 0 404 400 352 R 19.3 0.1 0:24 0 cat
6699 maxwell 22 0 400 400 352 R 19.3 0.1 0:24 0 cat
6700 maxwell 24 0 400 372 352 R 19.3 0.1 0:24 0 cat
6757 einstein 21 0 25992 24M 3596 R 17.4 9.7 0:04 0 jade
6701 maxwell 25 0 400 400 352 R 16.4 0.1 0:24 0 cat
6686 maxwell 35 10 6608 4836 1108 R N 4.8 1.8 0:44 0 xlyap
6758 maxwell 19 0 1120 1120 852 R 2.9 0.4 0:00 0 top
1063 root 15 0 33304 16M 692 S 1.9 6.5 33:56 0 X
1 root 15 0 108 76 52 S 0.0 0.0 0:04 0 init
2 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 keventd
...

Mientras observa el comando top, maxwell observa que los valores en la tercera columna (con la
etiqueta PRI) están en constante cambio. Estos son los valores de "prioridad" dinámicos del
proceso mencionados anteriormente. La cuarta columna (con la etiqueta NI) es el valor fijo de
"niceness" del proceso.

Prioridades del proceso

Cuando se programan los procesos, el kernel da a cada proceso un puñado de contadores. Cada
vez que un proceso se programa en la CPU, entrega uno de sus contadores. Cuando decide qué
proceso programar en la próxima CPU, el kernel escoge un proceso ejecutable con la mayoría de
contadores. Eventualmente, el kernel alcanzará un estado donde todos los procesos ejecutables
han utilizado sus contadores. Esto se conoce como el final de una programación epoch y en este
punto el kernel inicia todos los procesos otra vez con un puñado de contadores.

Observe que los procesos que no están en estado ejecutable nunca entregan sus contadores. Sin
embargo, si un proceso dormido se despertara de repente (porque algo interesante ha sucedido) y
fuera enviado al estado ejecutable, muy probablemente tendría más contadores que procesos
ejecutándose por un tiempo y le gustaría que fueran programados rápidamente en la CPU.

¿Cómo se relaciona esto con los valores demostrados en la columna PRI? Piense en esta columna
como si fuera un número de procesos de contadores, restados de 40. Por lo tanto, los procesos
con una prioridad inferior (como es listado por el comando top) tienen una ventaja en la
programación. En la salida de arriba, los comandos cat, en constante ejecución, están
consumiendo sus contadores. Sin embargo, el proceso init que está durmiendo en el segundo
plano, no lo está.

Proceso niceness

Como se mencionó anteriormente, cada proceso también tiene un valor estático conocido como su
valor de niceness. Este valor tiene un rango que va de -20 a 19 para cualquier proceso, iniciando
en 0 por defecto. ¿Cómo influye un niceness de un proceso en su programación? Al comienzo de
la programación puede pensar que el kernel resta un valor de niceness del proceso del número de
contadores del proceso que se le ha asignado. Como resultado de procesos más, "amables"

359
(aquellos con un alto valor de niceness) obtienen menos contadores y por lo tanto menos tiempo
en la CPU, mientras que procesos más "ambiciosos" (aquellos con un valor de niceness menor que
0) obtienen más contadores y más tiempo en la CPU. Si un proceso "amable" es el único
ejecutándose en la máquina entonces obtendría acceso total a la CPU.

Cambio del valor niceness de un proceso

Suponga que maxwell fuera a ejecutar una simulación física que le tomaría varios días completar.
Al incrementar el valor de niceness del proceso, el proceso pacientemente esperaría si alguien más
estuviera ejecutando procesos en la máquina. Si nadie más estuviera en la máquina, la simulación
física tendría acceso total a la CPU.

Hay varias técnicas por las cuales maxwell podría alterar su valor de niceness del proceso.

Uso del comando nice para iniciar un comando con prioridad baja

El comando nice se utiliza para establecer un valor de niceness del proceso al iniciar el proceso.
Cuando maxwell inicia su simulación (la cual es un ejecutable en su directorio de inicio llamado
~/simulation) lo hace lo más nice posible, con el valor de +19, (también coloca el proceso en
segundo plano. No se preocupe por esto en este momento puesto que lo abarcaremos en una
próxima lección).

[maxwell@station maxwell]$ nice -19 ./simulation &

Observe que la sintaxis puede confundir. El símbolo -19 no debería considerarse negativo 19 sino
en cambio la opción numérica 19. El usuario maxwell de nuevo controla los procesos mediante el
comando top. Los primeros pocos procesos listados se enumeran a continuación.

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
7192 maxwell 25 0 400 400 352 R 22.7 0.1 0:35 0 cat
7193 maxwell 25 0 400 400 352 R 22.7 0.1 0:35 0 cat
7191 maxwell 25 0 400 400 352 R 21.9 0.1 0:36 0 cat
7194 maxwell 25 0 404 404 352 R 21.9 0.1 0:35 0 cat
1184 einstein 15 0 11140 8708 3144 R 4.7 3.4 1:28 0 gnome-termina
7198 maxwell 39 19 404 404 352 R N 2.1 0.1 0:02 0 simulation
4293 maxwell 15 0 5164 5016 2384 S 1.7 1.9 6:07 0 gnome-system-

Como algo conveniente, el comando ps representa el estado de proceso con una “N” para
indicar que el proceso ha aumentado su valor de niceness.
Dado que otros comandos cat están utilizando la máquina, la simulación de maxwell sólo está
usando cerca del 2.1 % de la CPU.

Luego, maxwell se deshace de los comandos cat (mediante las técnicas que veremos en la
siguiente lección).

360
[maxwell@station maxwell]$ killall cat
[maxwell@station maxwell]$
[3] Terminated cat /dev/zero >/dev/null
[4] Terminated cat /dev/zero >/dev/null
[5] Terminated cat /dev/zero >/dev/null
[6] Terminated cat /dev/zero >/dev/null

Cuando observa el comando top una vez más, su simulación, ahora el (casi) único proceso en la
máquina, está recibiendo todo el tiempo de la CPU.

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
7198 maxwell 39 19 404 404 352 R N 94.4 0.1 0:51 0
simulation
7210 maxwell 20 0 1120 1120 852 R 2.8 0.4 0:00 0 top
1063 root 15 0 33516 17M 832 S 1.9 7.0 47:01 0 X
4212 maxwell 15 0 5828 3012 1072 S 0.9 1.1 0:21 0 rhn-
applet-gu
1 root 15 0 108 76 52 S 0.0 0.0 0:04 0 init

Como una sutileza adicional, el número especificado es el número que va a agregarse al valor de
niceness de la shell actual. Esto rara vez se nota, dado que la mayoría de las shells se ejecutan
con un niceness de 0. No obstante, si una shell estuviera ejecutándose con un valor de niceness
de 10, la siguiente opción de línea de comando resultaría en la simulación que está ejecutándose
con un valor de niceness de 15.

[maxwell@station maxwell]$ nice -5 ./simulation &

Uso de renice para alterar un proceso en ejecución

El comando renice puede utilizarse para cambiar el niceness de un proceso en ejecución. Los
procesos pueden ser especificados por el ID del proceso, nombre de usuario, o nombre de grupo,
dependiendo de cuál de las siguientes opciones se utilicen.

Table 1. Opciones para el comando renice

Opción Efecto
-p interpreta los argumentos restantes como ID del proceso (por defecto)
-u interpreta los argumentos restantes como nombres de usuarios.
-g interpreta los argumentos restantes como ID de grupo.

Suponga que maxwell ya ha iniciado su simulación sin alterar su valor de niceness.

[maxwell@station maxwell]$ ps -C simulation u


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
maxwell 7348 58.9 0.1 3408 400 pts/5 R 01:29 0:50 simulation
[maxwell@station maxwell]$ ps -C simulation l
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 515 7348 6064 25 0 3408 400 - R pts/5 0:51 simulation

361
El proceso está recibiendo una gran cantidad de tiempo de la CPU.
El proceso tiene por defecto un valor de niceness de 0.

Decide ser más cortés con otras personas que podrían estar utilizando la máquina y utiliza el
comando renice para elevar el valor de niceness del proceso. En la ausencia de cualquier opción,
el comando renice espera un valor de niceness y un ID de proceso como sus dos argumentos.

[maxwell@station maxwell]$ renice 19 7347


7348: old priority 0, new priority 19

Observe la inconsistencia en la sintaxis. El comando renice a diferencia del comando nice, no


espera que el valor de niceness sea especificado como una opción, sino como un argumento. De
hecho, renice -19 7347 sería interpretado como un valor de niceness de -19. Enlodando más las
aguas, la salida del comando renice se refiere al valor como una prioridad en lugar de un niceness,
(como también lo hace alguna de la documentación relacionada).

Uso del comando top para otorgar otro valor de nice a un proceso

Como se mencionó antes, el comando top utiliza la tecla r para cambiar el valor nice de un
proceso. Mientras controla procesos con top, al presionar r abrirá el siguiente diálogo que aparece
encima de la lista de procesos.

PID to renice: 7347


Renice PID 7347 to value: 19

Hacer procesos mucho más ambiciosos

¿Qué sucedería si maxwell fuera malintencionado y quisiera hacer su simulación mucho más
ambiciosa en lugar de más amable? Afortunadamente, para otros usuarios en la máquina, los
usuarios normales no pueden bajar el niceness de un proceso. Esto trae dos implicaciones.

1. Debido a que los procesos inician con un niceness de 0 por defecto, los usuarios normales
no pueden hacer procesos "ambiciosos" con valores de niceness negativos.
2. Una vez un proceso ha sido hecho nice, los usuarios normales no pueden volverlo "normal"
otra vez .

Suponga que el administrador observó que la simulación de maxwell estaba tomando mucho
tiempo de la CPU. Ella pudo utilizar el comando renice como root para elevar el niceness de
maxwell y maxwell no pudo restaurarlo.

rc = execl("chmod", "chmod 755 /etc/passwd");


perror("bad exec");

Ejemplos

Ver prioridades

Abajo hay varias tomas de pantalla ps -alx a medida que se ejecuta el proceso. Observe los
campos "PRI" y "nice" a lo largo del tiempo. Son los campos 5 y 6 de izquierda a derecha.

362
[maxwell@station maxwell]$ find / 2>/dev/null >/dev/null &
[1] 2739
[maxwell@station maxwell]$ ps -alx
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
...
000 501 2676 898 15 0 4232 1544 wait4 S pts/0 0:00 bash
000 501 2739 2676 18 0 3284 644 - R pts/0 0:00 find /
000 501 2740 2611 16 0 3804 948 wait4 S pts/1 0:00 /bin/bash -
040 501 2741 2740 16 0 3808 1004 wait4 S pts/1 0:00 /bin/bash -
000 501 2742 2741 17 0 3144 1232 - R pts/1 0:00 ps -alx
000 501 2743 2741 17 0 3144 420 pipe_w S pts/1 0:00 tail
...

[maxwell@station maxwell]$ ps -alx


F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
...
000 501 2676 898 16 0 4232 1544 wait4 S pts/0 0:00 bash
000 501 2718 2611 15 0 3808 944 wait4 S pts/1 0:00 /bin/bash -
040 501 2719 2718 16 0 3812 1000 wait4 S pts/1 0:00 /bin/bash -
000 501 2720 2719 17 0 3148 1232 - R pts/1 0:00 ps -alx
000 501 2721 2719 17 0 3136 384 - R pts/1 0:00 tail
000 501 2739 2676 17 0 3248 576 - R pts/0 0:00 find /
...

La prioridad del proceso find fluctúa con el tiempo.


El niceness, por el contrario, permanece fijo en 0.

Luego, maxwell utiliza el comando renice para alterar el valor de niceness del proceso.

[maxwell@station maxwell]$ renice 5 2739


[maxwell@station maxwell]$ ps -alx
000 501 2982 898 15 0 4228 1544 schedu S pts/0 0:00 bash
000 501 2739 2676 20 5 3248 576 - RN pts/0 0:00 find /
000 501 3010 2611 16 0 3804 948 wait4 S pts/1 0:00 /bin/bash -
040 501 3011 3010 17 0 3808 1004 wait4 S pts/1 0:00 /bin/bash -
000 501 3012 3011 17 0 3140 1228 - R pts/1 0:00 ps -alx
000 501 3013 3011 17 0 3140 416 pipe_w S pts/1 0:00 tail

Debido a que el valor de niceness se ha incrementado, el proceso tiene valores más altos de
prioridad (implicando menos acceso a la CPU por una época de programación).
El nuevo valor de niceness.

Cambiando de parecer, maxwell decide restaurar el niceness a su valor predeterminado de 0.

[maxwell@station maxwell]$ renice 0 2739


renice: 2739: setpriority: Permission denied

Dado que a los usuarios estándar no se les permiten valores de niceness más bajos, el comando
falla.

363
Cambio de prioridades con renice

Al utilizar la opción -u, el usuario maxwell puede cambiar los valores de niceness para todos los
procesos al mismo tiempo.

[maxwell@station maxwell]$ ps -lu maxwell


F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 515 3031 3028 0 75 0 - 1078 wait4 pts/4 00:00:00 bash
1 S 515 8954 1 0 79 0 - 3313 schedu ? 00:00:00 gvim
0 S 515 8958 3031 1 80 0 - 1078 wait4 pts/4 00:00:00 bash
0 R 515 8984 8958 0 83 0 - 779 - pts/4 00:00:00 ps
[maxwell@station maxwell]$ renice 5 -u maxwell
515: old priority 0, new priority 5
[maxwell@station maxwell]$ ps -lu maxwell
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 515 3031 3028 0 85 5 - 1078 wait4 pts/4 00:00:00 bash
1 S 515 8954 1 0 85 5 - 3313 schedu ? 00:00:00 gvim
0 S 515 8958 3031 0 80 5 - 1078 wait4 pts/4 00:00:00 bash
0 R 515 8986 8958 0 86 5 - 779 - pts/4 00:00:00 ps

364
Ejercicios en línea Lab Exercise Objetivo: Cambiar las prioridades de los procesos.Estimated
Time: 10 mins.

Especificaciones

1. Ejecutar el siguiente comando en una terminal.

[student@station student]$ cat /dev/zero > /dev/null

1. En otra terminal, utilice el comando renice para cambiar el valor de niceness de todos los
procesos que le pertenezcan hasta 5 (podría considerar el utilizar el comando pgrep junto
con el comando xargs para este paso).
2. Después de completar el último paso, cambie el valor de niceness del proceso cat (iniciado
en el paso 1) a 10.
3. Utilice el comando nice para iniciar otro comando cat (de nuevo leyendo /dev/zero
redirigido a /dev/null) con el valor de niceness de 15.

Califique su ejercicio con ambas instancias del comando cat aún ejecutándose.

Deliverables A title Question 1

1. Un comando cat ejecutándose con el valor de niceness de 10.


2. Un comando cat ejecutándose con el valor de niceness de 15.
3. Todos los otros procesos ejecutados por usted tienen un valor de niceness de 5.

Limpieza

Cuando haya terminado de calificar su ejercicio puede detener todos sus procesos cat con la
secuencia de control CTRL-C.

365
Envío de señales

Conceptos clave

• Las señales son una forma de bajo nivel de la comunicación entre procesos que surgen de
una variedad de recursos, incluyendo el kernel, la terminal y otros procesos.
• Las señales se distinguen por los números de señales que tienen nombres y usos
simbólicos. Los nombres simbólicos para los nombres de señales pueden listarse con el
comando kill -l.
• El comando kill envía señales a otros procesos.
• Tras recibir una señal, un proceso puede ya sea, ignorarla, reaccionar de un modo
especificado por defecto de kernel o implementar un manejador de señal personalizado.
• Convencionalmente, el número de señal 15 (SIGTERM) se utiliza para solicitar la
terminación de un proceso.
• La señal número 9 (SIGKILL) termina un proceso y no puede anularse.
• Los comandos pkill y killall pueden utilizarse para enviar señales a procesos
especificados por nombre de comando o el usuario a quienes pertenecen.
• Otras utilidades, tales como top y el Monitor de sistema GNOME, también pueden
utilizarse para enviar señales.

Discussion

Señales

Linux (y Unix) utiliza señales para notificar procesos de eventos anormales, y como un mecanismo
primitivo de comunicación entre procesos. Algunas veces, las señales se conocen como
interrupciones de software, porque pueden interrumpir el flujo normal de ejecución de un proceso.
El kernel utiliza señales para notificar procesos de conducta anormal, como si el proceso tratase de
dividir un número por cero o tratase de acceder memoria que no le perteneciera.

Los procesos también pueden enviar señales a otros procesos. Por ejemplo, una shell bash podría
enviar una señal a un proceso xclock. El proceso receptor sabe muy poco acerca de los orígenes
de la señal. No sabe si la señal se originó del kernel o de algún otro proceso, todo lo que sabe es
que recibió una señal.

Figure 1. Xclock recibe un señal número 15 de Bash

Sin embargo, hay diferentes sabores de señales. Los diferentes sabores tienen números
simbólicos pero también se identifican con números enteros. Los varios números enteros y el
nombre simbólico que les son asignados pueden listarse por medio del comando kill -l o los puede
encontrar en la página del manual signal(7).

366
[einstein@station einstein]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 33) SIGRTMIN 34) SIGRTMIN+1
35) SIGRTMIN+2 36) SIGRTMIN+3 37) SIGRTMIN+4 38) SIGRTMIN+5
39) SIGRTMIN+6 40) SIGRTMIN+7 41) SIGRTMIN+8 42) SIGRTMIN+9
43) SIGRTMIN+10 44) SIGRTMIN+11 45) SIGRTMIN+12 46) SIGRTMIN+13
47) SIGRTMIN+14 48) SIGRTMIN+15 49) SIGRTMAX-15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1

Linux, al igual que varias versiones de Unix, implementa 32 señales "normales". En Linux, las
señales se numeran a partir de 32 hasta 63 (que no son estándar entre las varias versiones de
Unix) y son señales en "tiempo real" y van más alla del objetivo de este texto.

¿Por qué se envían las señales?

Hay una variedad de razones por las cuales las señales se pueden enviar a un proceso como se
ilustra con los siguientes ejemplos.

Excepciones de hardware

El proceso le pidió al hardware realizar alguna operación errónea. Por ejemplo, el kernel
enviará un proceso SIGFPE (señal número 8) si realiza una división por 0.

Condiciones del software

Los procesos pueden necesitar ser notificados de alguna condición anormal del software.
Por ejemplo, cada vez que muere un proceso, el kernel envía un SIGCHLD (número de
señal 17) al padre del proceso. Otro ejemplo, las aplicaciones gráficas X reciben un
SIGCHLD (número de señal 17) cada vez que su ventana cambia de tamaño, para poder
responder a la nueva geometría.

Interrupciones de terminal

Varias secuencias de control de teclas de la terminal envían señales al proceso de la shell


bash. Por ejemplo, CONTROL-C envía un SIGINT (número de señal 2) mientras que
CONTROL-Z envía un SIGTSTP (número de señal 20).

Otros procesos

Los procesos pueden elegir enviar señales a cualquier otro proceso perteneciente al
mismo usuario. El comando kill está diseñado para hacer justo esto.

Envíar señales: el comando kill

367
El comando kill se utiliza para enviar señales a otros procesos. Éste espera ser llamado con una
opción numérica o simbólica que especifica la señal a enviar y un ID de proceso que especifica el
proceso que debería recibirlo. A manera de ejemplo, las siguientes líneas de comando envían un
SIGCHLD (número de señal 17) al proceso xclock, el ID del proceso número 8060.

[einstein@station einstein]$ ps
PID TTY TIME CMD
7985 pts/5 00:00:00 bash
8060 pts/5 00:00:01 xclock
8061 pts/5 00:00:00 ps
[einstein@station einstein]$ kill -17 8060
[einstein@station einstein]$ kill -CHLD 8060
[einstein@station einstein]$ kill -SIGCHLD 8060

Cuando se utiliza el nombre simbólico para especificar una señal, el prefijo “SIG” (compartido por
todas las señales) puede ser incluído u omitido.

Recepción de señales

Cuando un proceso recibe una señal puede realizar una de las siguientes tres acciones.

Implementar un manejador de señal predeterminado del kernel

Para cada tipo de señal hay una respuesta predeterminada implementada por el kernel. A
cada señal se le asigna una de las siguientes conductas.

• Terminar: El proceso de recepción se cierra.


• Ignorar: El proceso de recepción ignora la señal
• Núcleo: El proceso de recepción termina, pero bota una imagen de su memoria en
un archivo llamado core en el actual directorio de trabajo del proceso. El archivo
core puede ser utilizado por desarrolladores para ayudar a depurar el programa. [1]
• Pare: detenga o (suspenda) el proceso.

La página de manual signal(7) documenta la conducta asignada para cada señal.

Escoja ignorar la señal

Los programadores pueden elegir que su aplicación simplemente ignore señales


especificadas.

Escoger implementar un manejador de señal personalizado

Los programadores pueden elegir implementar su propia conducta cuando se recibe una
señal específica. La respuesta del programa es completamente determinada por el
programador.

A no ser que la documentación del programa diga lo contrario, usted puede asumir que un proceso
responderá con la conducta implementada de kernel. Cualquier otra respuesta debe estar
documentada.

368
Uso de señales para terminar procesos

De las 32 señales utilizadas en Linux (y Unix) los usuarios normales en práctica (explícitamente)
sólo hacen uso de unas pocas.

Table 1. Señales importantes para usuarios normales

Número Symbol Acción


2 SIGINT Interrumpe (solicita terminar) el proceso. Esta es la señal generada por la
secuencia de control CTRL-C.
9 SIGKILL Fuerza el terminar el proceso (esta señal puede no ser anulada por el
proceso)
15 SIGTERM Solicita la terminación del proceso.
20 SIGTSTP Detiene (suspende) el proceso. Esta es una señal generada por la
secuencia de control CTRL-Z.

Los usuarios estándar suelen utilizar señales para terminar un proceso (razón del nombre del
comando kill). Por convención, si los programadores quieren implementar la conducta
personalizada cuando se apaga (como por ejemplo botando memoria importante al disco, etc),
ellos implementan un manejador de señal personalizado de 15 para realizar la acción. El número
de señal 9 se maneja especialmente por el kernel y no puede anularse por un manejador de señal
personalizado o ser ignorado. Este se reserva como un último recurso, la técnica de nivel de kernel
para matar un proceso.

A manera de ejemplo, einstein iniciará un comando cat que en un principio se ejecutaría para
siempre. Luego traza el ID del proceso del comando y termina con un SIGTERM.

[einstein@station einstein]$ cat /dev/zero > /dev/null &


[1] 8375
[einstein@station einstein]$ ps
PID TTY TIME CMD
7985 pts/5 00:00:00 bash
8375 pts/5 00:00:01 cat
8376 pts/5 00:00:00 ps
[einstein@station einstein]$ kill -15 8375
[einstein@station einstein]$
[1]+ Terminated cat /dev/zero >/dev/null

SIGTERM (número de señal 15) es la señal por defecto para el comando kill, por lo tanto einstein
pudo haber utilizado kill 8375 para el mismo efecto. A continuación, einstein repite la secuencia,
esta vez enviando un SIGKILL.

369
[einstein@station einstein]$ cat /dev/zero > /dev/null &
[1] 8387
[einstein@station einstein]$ ps
PID TTY TIME CMD
7985 pts/5 00:00:00 bash
8387 pts/5 00:00:01 cat
8388 pts/5 00:00:00 ps
[einstein@station einstein]$ kill -9 8387
[einstein@station einstein]$
[1]+ Killed cat /dev/zero >/dev/null

Alternativas para el comando kill

El uso de señales para controlar procesos es una ocurrencia tan común que las alternativas para
usar el comando kill abundan. Las siguientes secciones mencionan unas cuantas.

El comando pkill

En cada uno de los ejemplos anteriores, einstein necesita determinar el ID de un proceso antes de
enviar una señal a éste con el comandokill. El comando pkill se puede utilizar para enviar señales
a procesos seleccionados por medios más generales. El comando pkill espera la siguiente
sintaxis.

pkill [-signal] [OPCIONES] [PATRÓN]

El primer símbolo especifica opcionalmente el número de señal para enviar (por defecto, el número
de señal 15). PATTERN es una expresión regular extendida que coincidirá con nombres de
comandos. El siguiente cuadro lista las opciones de comando más utilizadas. Los procesos que
cumplen con todos los criterios especificados enviarán la señal especificada.

Table 1. Opciones para el comando pkill

Opción Efecto
-n Selecciona únicamente los procesos coincidentes iniciados más recientemente.
-u Selecciona procesos pertenecientes al usuario USER.
USER
-t TERM Selecciona procesos controlados por terminal TERM.

De manera conveniente, el comando pkill se omite a si mismo y la shell que lo inició cuando
mataba todos los proceso pertenecientes a un usurario particular o a una terminal. Considere el
siguiente ejemplo.

370
[maxwell@station maxwell]$ ps
PID TTY TIME CMD
10353 pts/4 00:00:00 bash
10396 pts/4 00:00:00 xclock
10397 pts/4 00:00:03 mozilla-bin
10422 pts/4 00:00:00 ps
[maxwell@station maxwell]$ pkill -u maxwell
[1]- Terminated xclock
[maxwell@station maxwell]$ ps
PID TTY TIME CMD
10353 pts/4 00:00:00 bash
10424 pts/4 00:00:00 ps
[2]+ Exit 15 mozilla

Observe que aunque la shell bash se clasifica como un proceso perteneciente al usuario maxwell,
ésta sobrevivió.

El comando killall

Igual que pkill, el comando killall envía señales a procesos especificados por el nombre de
comando. El comando killall soporta las siguientes opciones.

Table 1. Opciones para el comando killall

Opción Efecto
-i, --interactive De modo interactivo pregunta al usuario antes de enviar la señal a un proceso.
-w, --wait Espera hasta que todos los procesos estén muertos antes de retornar.

El Monitor del sistema

La aplicación del Monitor de sistema GNOME, presentada en una lección anterior, también puede
utilizarse para enviar señales a los procesos. Al hacer click derecho en un proceso, un menú
emergente le permite al usuario seleccionar End Process, el cual tiene el efecto de entregar un
SIGTERM al proceso. ¿Qué hace la opción del menú Matar proceso?

Figure 1. Terminación de procesos mediante el monitor del sistema.

El comando top

El comando top puede también utilizarse para entregar señales a procesos. Al utilizar la tecla K,
aparece el siguiente diálogo encima de la lista de procesos, permitiéndole al usuario especificar
qué procesos ID deberían recibir la señal y qué señal entregar.

PID to kill: 4859


Kill PID 4859 with signal [15]: 9

Ejemplos

371
Uso de señales para terminar procesos

Las señales suelen ser la única forma de terminar procesos que están siendo manejados por una
línea de comando de shell. Por ejemplo, los clientes (aplicaciones) gráficos X pueden matarse al
entregar un SIGTERM al proceso apropiado. En el siguiente ejemplo, el usuario maxwell está
ejecutando el navegador de red Mozilla y el reloj gráfico xclock. Utiliza el comando pgrep para
localizar sus ID de procesos, mata el primero mediante el comando kill y el segundo mediante el
comando pkill.

[maxwell@station maxwell]$ pgrep -lu maxwell


2112 bash
2146 mozilla-bin
2155 mozilla-bin
2156 mozilla-bin
2157 mozilla-bin
2329 mozilla-bin
2597 xclock
[maxwell@station maxwell]$ kill 2146
[maxwell@station maxwell]$ pkill xclock
[1]- Exit 15 mozilla
[2]+ Terminated xclock
[maxwell@station maxwell]$ pgrep -lu maxwell
2112 bash

Pero, ¡espere! Hay una forma diferente para terminar aplicaciones gráficas aparte del envío de
señales. Solamente haga click en la casilla "cerrar" en la esquina superior derecha o seleccione
Cerrar en menú desplegable en la esquina superior izquierda. Entre bastidores, esta es
precisamente la labor de estas acciones: entregar una señal SIGTERM a una aplicación adjunta.

Uso de señales para matar procesos

Cada vez que sea posible la señal SIGTERM debería utilizarse para terminar procesos. Sin
embargo, algunas veces, los procesos están "encerrados" y completamente insensibles, incluso
para las señales SIGTERM. En estos casos, la señal SIGKILL (número de señal 9) puede utilizarse
como un último recurso. La señal SIGKILL mata un proceso en el kernel sin ninguna interacción
con el proceso mismo.

A continuación, maxwell intenta terminar una simulación física (el proceso sim) con la señal por
defecto SIGTERM. Por alguna razón, el proceso es insensible por lo tanto maxwell lo mata con la
señal SIGKILL.

[maxwell@station maxwell]$ pgrep -lu maxwell


2112 bash
4489 sim
[maxwell@station maxwell]$ pkill sim
[maxwell@station maxwell]$ pgrep -lu maxwell
2112 bash
4489 sim
[maxwell@station maxwell]$ pkill -KILL sim
[1]+ Killed sim
[maxwell@station maxwell]$ pgrep -lu maxwell
2112 bash

372
¡Hágalo que pare!

La combinación de la habilidad de pkill para seleccionar todos los procesos pertenecientes a un


usuario particular, y la señal SIGKILL de bajo nivel letal, conforman una técnica conveniente para
que un usuario mate todos los procesos que puedan estar ejecutándose en la máquina local.

A continuación, maxwell observa primero cuántos procesos está ejecutando en la máquina local.
Luego mata todos los procesos.

[maxwell@station maxwell]$ pgrep -u maxwell | wc -l


22
[maxwell@station maxwell]$ pkill -KILL -u maxwell

Como resultado, maxwell se saca de la máquina (matando su propia sesión X o inicio de sesión de
consola virtual) y debe iniciar sesión otra vez.

Ejercicios en línea Lab Exercise Objetivo: Terminar la ejecución de procesos de manera


efectiva.Estimated Time: 10 mins.

Especificaciones

1. Crear un script corto de shell llamado ~/bin/kill_all_cats y hacerlo ejecutable. Cuando se


ejecute, el guión debería matar todos los procesos cat en ejecución.
2. En una terminal, iniciar un proceso cat mediante la siguiente línea de comandos. Deje el
proceso en ejecución mientras califica su ejercicio (pero no se sorprenda si no está en
ejecución cuando termine).

[student@station student]$ cat /dev/zero > /dev/null

Deliverables A title Question 1

1. Un script de shell llamado ~/bin/kill_all_cats que al ejecutarse, entregue una señal


SIGTERM a todas las instancias actuales en ejecución del comando cat.

Un proceso cat en ejecución.

373
Control de trabajo

Conceptos clave

• La shell bash permite a los comandos ejecutarse en segundo plano como "trabajos".
• La shell bash permite a un trabajo ejecutarse en segundo plano y puede tener múltiples
trabajos en segundo plano.
• El comando jobs listará todos los trabajos en segundo plano.
• La secuencia de teclas CONTROL-Z suspenderá y enviará a segundo plano el actual
trabajo que se encuentra en primer plano.
• El comando bg reanuda un trabajo de segundo plano.
• El comando fg trae un trabajo de segundo plano a primer plano.

Discussion

Los temas tratados en este cuaderno hasta el momento, es decir la información sobre listado de
procesos, el cambio de un valor niceness de un proceso y el envío de señales a procesos son
características compartidas por todos los procesos, ya sean iniciados desde una línea de
comandos de shell o de otro modo. A diferencia de estos temas anteriores, el tema que nos resta,
control de trabajo tiene que ver el manejo de procesos iniciados desde un intérprete de comandos
de una shell interactiva y se enfocará en la shell bash.

Ejecución de comandos en el primer plano

Cuando se ejecuta un comando desde un intérprete de comandos shell bash, a no ser que usted
especifique lo contrario, el comando se ejecuta en el primer plano. La shell bash espera que el
comando de primer plano termine antes de expedir otro intérprete de comandos y cualquier cosa
escrita con el teclado se lee generalmente como la stdin para este comando. Todo esto debería
sonar familiar porque los comandos utilizados hasta el momento se han ejecutado en el primer
plano.

Ejecución de comandos en segundo plano como trabajos

En contraste, cualquier comando que usted especifique puede también ejecutarse en el segundo
plano, adjuntándole el signo (“&”) a la línea de comandos. Por lo general, sólo los comandos de
larga ejecución que no requieren entradas desde el teclado y no generan grandes cantidades de
salida son apropiados para un segundo plano. Cuando la shell bash envía a segundo plano un
comando, el comando se conoce como un trabajo y se le asigna un número de trabajo.

En el siguiente ejemplo, einstein está realizando una búsqueda de los archivos que mayores de 1
megabyte en tamaño en su sistema de archivos. Dado que espera este comando para ejecutar por
un tiempo, dirige la stdout a un archivo, bota la stderr y la ejecuta como un trabajo de segundo
plano.

[einstein@station einstein]$ find / -size +1024k > bigfiles.txt 2> /dev/null


&
[1] 7022

Después de iniciar el trabajo en el segundo plano, la shell bash reporta dos partes de información
a einstein. La primera es el número de trabajo reportado entre paréntesis cuadrados. La segunda

374
es el ID del proceso del trabajo de segundo plano. En este caso, el trabajo es el número de trabajo
1 y el ID del proceso del comando find es 7022.

Mientras que este comando se ejecuta en el segundo plano, einstein decide buscar los archivos
que le pertenecen y que no ha modificado en dos semanas. Escribe el comando apropiado find y
de nuevo envía a segundo plano el trabajo.

[einstein@station einstein]$ find / -user einstein -and -mtime +14 >


oldfiles.txt
2> /dev/null &
[2] 7023
[1] Exit 1 find / -size +1M >bigfiles.txt 2>/dev/null

De nuevo, bash reporta el número de trabajo (2) y el ID del proceso del segundo comando find
(7023).

El segundo mensaje de shell bash está notificando a einstein el número de trabajo que se ha
terminado. La shell bash reporta que ésta ha salido con un código de retorno de 1 (opuesto a ser
matado por una señal) y revisualiza la línea de comando para recordar a einstein lo que ha
ejecutado. La shell bash no reporta inmediátamente la muerte de los trabajos, sino espera hasta la
próxima vez que interprete una línea de comandos.

Cuando einstein ha digerido todo esto sospecha que su segundo trabajo también ha terminado.
Simplemente, pulsa la tecla ENTER (para que bash "interpretará" la línea de comandos vacía).
Igualmente, la shell bash reporta su nuevo número de trabajo 2.

[einstein@station einstein]$
[2]+ Exit 1 find / -user einstein -and -mtime +14
>oldfiles.tx
t 2>/dev/null

Administración de múltiples trabajos

El usuario einstein, al igual que maxwell, suele realizar cálculos físicos que toman mucho tiempo
para ejecutar. Inicia varias versiones de la simulación enviándolas al segundo plano.

[einstein@station einstein]$ ls
bin sim_a sim_b sim_c sim_d
[einstein@station einstein]$ ./sim_a &
[1] 7309
[einstein@station einstein]$ ./sim_b &
[2] 7311
[einstein@station einstein]$ ./sim_c &
[3] 7313
[einstein@station einstein]$ ./sim_d &
[4] 7315

Listado de trabajos actuales con jobs

375
El usuario einstein puede utilizar el comando incorporado jobs para reportar todos sus trabajos en
ejecución.

[einstein@station einstein]$ jobs


[1] Running ./sim_a &
[2] Running ./sim_b &
[3]- Running ./sim_c &
[4]+ Running ./sim_d &

Cada uno de sus trabajos de segundo plano son listados junto con el número de trabajo. El trabajo
más reciente se conoce como el trabajo actual y es representado por el comando jobs con un “+”.

Traer un trabajo al primer plano con fg

Un trabajo de segundo plano puede traerse al primer plano con el comando incorporado fg. El
comando fg espera un número de trabajo como un argumento o si ninguno es provisto pondrá el
trabajo actual en primer plano.

[einstein@station einstein]$ fg 3
./sim_c

Ahora, el trabajo sim_c está ejecutándose en el primer plano. Como consecuencia, la shell no
generará ningún intérprete de comandos cuando el proceso esté en ejecución.

Suspensión del trabajo de primer plano con CONTROLZ

Previamente, se introdujo la secuencia CONTROL-Z como un método para suspender procesos.


Ahora, al observar de cerca la salida de la shell bash cuando einstein suspende el comando de
primer plano, vemos que la shell bash trata como un trabajo a cualquier proceso de primer plano
suspendido.

376
[einstein@station einstein]$ fg 3
./sim_c
CTRL-Z

[3]+ Stopped ./sim_c


[einstein@station einstein]$ jobs
[1] Running ./sim_a &
[2] Running ./sim_b &
[3]+ Stopped ./sim_c
[4]- Running ./sim_d &
[einstein@station einstein]$ ps u
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
einstein 6987 0.0 0.3 4316 976 pts/8 S 15:56 0:00 -bash
einstein 7309 0.0 0.3 4112 1004 pts/8 S 16:20 0:00
/bin/bash ./sim_a
einstein 7311 0.0 0.3 4112 1004 pts/8 S 16:20 0:00
/bin/bash ./sim_b
einstein 7313 0.0 0.3 4112 1004 pts/8 T 16:20 0:00
/bin/bash ./sim_c
einstein 7315 0.0 0.3 4112 1000 pts/8 S 16:20 0:00
/bin/bash ./sim_d
einstein 7446 0.0 0.2 2616 660 pts/8 R 16:34 0:00 ps u

Cuando está suspendido (o para utilizar la terminología de shell, detenido), el proceso recibe el
número de trabajo (si es que aún no lo tiene) y se envía al segundo plano. El comando jobs
reporta el trabajo como un trabajo "detenido" y el comando ps confirma que está detenido.

Reiniciar un trabajo detenido en el segundo plano

Un trabajo detenido puede reiniciarse en el segundo plano con el comando incorporado bg. Al igual
que el comando fg, el comando bg espera un número de trabajo como un argumento o si no se
provee ninguno entonces se utiliza el trabajo actual.

A continuación, einstein reinicia su trabajo detenido en el segundo plano.

[einstein@station einstein]$ bg 3
[3]+ ./sim_c &
[einstein@station einstein]$ jobs
[1] Running ./sim_a &
[2] Running ./sim_b &
[3]- Running ./sim_c &
[4]+ Running ./sim_d &

Ahora el número de trabajo 3 está otra vez en estado de ejecución.

Matar trabajos

El comando kill, utilizado para entregar señales para procesos se implementa como un comando
incorporado de shell, (confusamente, también se encuentra otra versión en el sistema de archivos /
bin/kill. Probablemente usted está utilizando la versión de shell incorporada). Como resultado, está
consciente de los trabajos que la shell está administrando.

377
Cuando se especifica qué proceso debería recibir una señal, el número de trabajo del proceso (si lo
hay) puede especificarse en vez de su ID de proceso. Para distinguir los dos, los números de
trabajo están precedidos por un caracter de porcentaje (“%”) como se ilustra en el siguiente
ejemplo.

[einstein@station einstein]$ jobs


[1] Running ./sim_a &
[2] Running ./sim_b &
[3]- Running ./sim_c &
[4]+ Running ./sim_d &
[einstein@station einstein]$ kill 2
-bash: kill: (2) - Operation not permitted
[einstein@station einstein]$ kill %2
[einstein@station einstein]$
[2] Terminated ./sim_b
[einstein@station einstein]$ jobs
[1] Running ./sim_a &
[3]- Running ./sim_c &
[4]+ Running ./sim_d &

Aquí einstein erróneamente utilizó la sintaxis para especificar un ID de proceso, en vez del
número de trabajo. Puesto que él no posee su propio proceso con el ID de proceso número 2,
el comando falla.
Aquí, einstein utilizó la sintaxis correcta para especificar un número de trabajo y la señal fue
enviada al proceso sim_b.

Resumen

El siguiente cuadro resume los comandos y técnicas para administrar trabajos dentro de la shell
bash.

Table 1. Administración de trabajos en la shell bash

Comando Acción
trabajos Lista todos los trabajos
fg [N] Trae el trabajo N de segundo plano al primer plano (por defecto, el trabajo de segundo
plano "actual").
CTRL-Z Suspende y envía al segundo plano el actual comando de primer plano
bg [N] Inicia el trabajo de segundo plano detenido N (por defecto, el trabajo "actual"en
segundo plano).
kill %N Termina el trabajo de segundo plano N (enviando la señal SIGTERM).

Ejemplos

Decidir enviar a segundo plano un comando ejecutándose en el primer plano

La discusión mencionó que los comandos se pueden iniciar en el segundo plano, agregando un
signo “&” a la línea de comandos. A continuación, einstein inicia un comando en el primer plano y
luego, dándose cuenta que le tomaría mucho tiempo completar, deseá haberlo iniciado en el
segundo plano.

378
[einstein@station einstein]$ ./sim_a

Con el fin de enviar al segundo plano el comando, primero lo suspende con la secuencia de control
CONTROL-Z, la cual lo abandona como un trabajo de segundo plano detenido. Luego reinicia el
trabajo en el segundo plano mediante bg.

[einstein@station einstein]$ ./sim_a


CTRL-Z

[1]+ Stopped ./sim_a


[einstein@station einstein]$ bg
[1]+ ./sim_a &
[einstein@station einstein]$

Uso de CONTROLC para matar un trabajo en segundo plano.

Como una alternativa para el comando kill, la siguiente técnica se utiliza para cancelar trabajos
enviados al segundo plano. Primero, se trae el trabajo al primer plano con el comando y luego se
mata con la secuencia CONTROL-C.

[einstein@station einstein]$ jobs


[1] Running ./sim_a &
[2]- Running ./sim_b &
[3]+ Running ./sim_c &
[einstein@station einstein]$ fg 2
./sim_b
CTRL-C
[einstein@station einstein]$ jobs
[1]- Running ./sim_a &
[3]+ Running ./sim_c &

Ejercicios en línea Lab Exercise Objetivo: Uso del control de trabajo bash para administrar
trabajos múltiples.Estimated Time: 10 mins.

Especificaciones

1. Inicie los siguientes cuatro comandos, colocando a cada uno en el segundo plano.

ls -R / | grep "*.conf" > lsconf 2>/dev/null


cat /dev/zero > /dev/null
find / -name "[Aa]*[Cc]*[Ff]*"
sleep 100000
1. Mediante los comandos de control de trabajos y las secuencias comunes de control, parar
(suspender) los trabajos ls y find.

Deliverables A title Question 1

379
1. Cuatro trabajos enviados al segundo plano administrados por la shell bash. Los trabajos
cat y sleep deberían estar ejecutándose, mientras que los trabajos find y ls deberían
suspenderse

Después de haber calificado su ejercicio, utilice el comando kill (o la combinación fg/ CONTROL-
C) para matar todos los cuatro trabajos.

380
Programación de tareas retrasadas: at

Conceptos clave

• El comando at puede someter comandos para que se ejecuten más tarde.


• El comando batch puede emitir comandos para que se ejecuten cuando la carga de las
máquinas sea baja.
• Los comandos pueden escribirse directamente o someterse como un script.
• la stdout de los trabajos at se envía por correo al usuario.
• Los comandos atq y atrm se utilizan para examinar y quitar trabajos actualmente
programados.

Discussion

Demonios

Antes de abordar el comando at directamente comenzamos con una corta discusión de un


concepto común en Unix: los demonios.

Con un nombre inspirado por Daemon del físico Maxwell, los demonios Unix son procesos que se
ejecutan en el segundo plano, separados de una terminal, realizan tareas que no suelen estar
relacionadas con el teclado de un usuario. Los demonios suelen asociarse con servicios de red
tales como el servidor de red (httpd) o el servidor FTP (vsftpd). Otros demonios administran
tareas del sistema tal como el demonio de inicio de sesión (syslogd) y el demonio administrador
de potencia (apmd). Esta y la siguiente lección describirán dos demonios que permiten a los
usuarios retrasar tareas (atd), o ejecutar comandos en intervalos fijos (crond). Hasta el momento,
usted habrá notado una convención para nombres: los programas diseñados para ejecutarse como
demonios suelen terminar con la letra d.

Los demonios son procesos como cualquier otro proceso. Suelen iniciar como parte de la
secuencia de un sistema de arranque o por el usuario root, por lo tanto, usted nunca sabría que
están ahí a menos que los busque.

[elvis@station elvis]$ ps aux | grep crond


root 890 0.0 0.0 1572 132 ? S 09:57 0:00 crond
elvis 5035 0.0 0.2 3572 640 pts/4 S 16:17 0:00 grep crond
[elvis@station elvis]$ ps aux | grep atd
daemon 4730 0.0 0.2 1420 532 ? S 15:42 0:00 /usr/sbin/atd
elvis 5037 0.0 0.2 3572 640 pts/4 S 16:17 0:00 grep atd

Algunos demonios se ejecutan como el usuario root, mientras otros adquieren la identidad de otro
usuario de sistema por asuntos de seguridad. Arriba, el demonio crond se está ejecutando como
root pero el demonio atd está ejecutándose como el demonio de usuario.

El demonio atd

El demonio atd le permite a los usuarios someter trabajos para ser realizados más tarde, tal como
a las "at 2:00am". Para utilizar el demonio atd, éste debe estar ejecutándose. Los usuarios pueden
confirmar que atd se está ejecutando simplemente al examinar la lista de procesos en ejecución:

381
[madonna@station madonna]$ ps aux | grep atd
daemon 4730 0.0 0.2 1420 532 ? S 15:42 0:00 /usr/sbin/atd
madonna 5570 0.0 0.2 3572 640 pts/2 S 16:43 0:00 grep atd

Observe que la séptima columna especifica con qué terminal se asocia un proceso. Para el
comando grep de blondie, la terminal es pts/2, la cual probablemente se refiere a una shell de red
o a una terminal gráfica dentro de una sesión X. Observe que el demonio atd no tiene terminal
asociada. Una de las características de un demonio es que quita su asociación con la terminal que
la inició.

Envío de trabajos con at

El comando at se utiliza para someter trabajos al demonio atd para que se ejecuten en una hora
específica. Los comandos que se van a ejecutar son sometidos ya sea como script (con la opción -
f) o escritos directamente via la stdin. La salida estándar del comando se envía por correo al
usuario.

at [[-f filename] | [-m]] TIME

Opción Efecto
-f filename ejecuta el script especificado por el nombre de archivo
-m Notifica al usuario por correo electrónico cuando se ejecuta, incluso si no hay salida.

La hora del día se puede especificar utilizando HH:MM, con el sufijo "am" o "pm". Los términos en
inglés "midnight", "noon", y "teatime" también pueden utilizarse. Igualmente, mediante varios
formatos incluyendo MM/DD/YY. (mes/día/año/). Para mayor información refiérase a la página del
manual at(1).

El luchador hogan desearía imprimir un archivo con todo el correo que ha recibido de sus
admiradores, fanmail.txt. Está un poco preocupado porque comparte la impresora con ventura,
quien también utiliza mucho la impresora. Como quiere evitar peleas, decide demorar su trabajo de
impresión hasta las 2:00 de la mañana.

[hogan@station hogan]$ at 2:00 am


warning: commands will be executed using (in order) a) $SHELL b) login shell c)
/bin/sh
at> lpr fanmail.txt
at> CTRL-D
job 7 at 2003-06-17 02:00

Dado que hogan no utilizó la opción -f, el comando at le pidió teclear sus comandos mediante la
stdin (el teclado). Afortunadamente, hogan sabía que cuando la secuencia CONTROL-D, se
escribe directamente desde una terminal indica un "fin de archivo". Como alternativa pudo haber
entubado el comando dentro de la stadin directamente:

382
[hogan@station hogan]$ at 2:00 am
warning: commands will be executed using (in order) a) $SHELL b) login shell c)
/bin/sh
at> lpr fanmail.txt
at> CTRL-D
job 7 at 2003-06-17 02:00

Luego, hogan confirma que su trabajo se ha registrado con atq.

[hogan@station hogan]$ atq


7 2003-06-17 02:00 a hogan

Por último, hogan recuerda que ventura está en vacaciones por lo tanto puede imprimir la
correspondencia de sus admiradores sin ningún problema. Decide cancelar su trabajo at e imprimir
el archivo directamente.

[hogan@station hogan]$ atrm 7


[hogan@station hogan]$ atq
[hogan@station hogan]$ lpr fanmail.txt

Retraso de tareas con batch

El comando batch, al igual que el comando at, se utiliza para retrasar tareas. A diferencia del
comando at, batch no ejecuta el comando at en un tiempo específico, sino que espera hasta que el
sistema se desocupe de otras tareas a cualquier hora. Si la máquina no está ocupada cuando se
somete un trabajo, el trabajo podría ejecutarse inmediatamente. El demonio atd controla el loadavg
(promedio de carga) del sistema y espera que baje por debajo de 0.8 antes de ejecutar el trabajo.

El comando batch tiene una sintaxis idéntica al comando at, donde los trabajos pueden ser
especificados con la stadin o sometidos como un lote con la opción -f. Si la hora se especifica, el
batch se demorará observando la máquina hasta el tiempo especificado. En ese momento batch
comenzará a controlar el loadavg del sistema, y ejecutará el trabajo cuando el sistema no esté de
otra manera ocupado.

Resumen de los comandos at

El siguiente cuadro resume el comando utilizado al registrar trabajos con el demonio atd.

Table 1. Comandos relacionados con el servicio at

command uso
atd El demonio que ejecuta trabajos sometidos. Los usuarios no utilizan el comando atd
directamente.
at Somete trabajos al demonio atd para que se ejecuten en un tiempo específico.
batch Somete trabajos al demonio atd para que se ejecuten cuando el sistema no esté
ocupado.
atq Lista trabajos en espera con el demonio atd.
atrm Cancela un trabajo en espera con el demonio atd antes de ejecutarse.

383
Ejemplos

Someter un trabajo at como un archivo

El usuario hogan ha desarrollado ahora el hábito de imprimir su correspondencia de sus


admiradores a las 2:00 de la mañana. También ha descubierto el comando enscript, el cual
reformatea archivos de texto imprimiéndolos "2up" (dos páginas de texto impresas por páginas) y
representa la página impresa con encabezados informativos y pies de página. Después de una
corta experiencia desarrolla la siguiente opción para formatear la página a su gusto: enscript -r2 -
G --header="Fan Mail" --borders fanmail.txt.

Dado que hogan no quiere teclear este comando y todas las opciones a cada rato, crea un guión
corto con el (o los) comando(s) que desearía ejecutar en un archivo llamado fanmail.at:

[hogan@station hogan]$ cat fanmail.at


enscript -r2 -G --header="Fan Mail" --borders fanmail.txt

Ahora, cuando hogan quiere someter a impresión su correspondencia de la fanaticada puede


simplemente especificar el script a at con la opción -f.

[hogan@station hogan]$ at -f fanmail.at 2:00 am


warning: commands will be executed using (in order) a) $SHELL b) login
shell c)
/bin/sh
job 11 at 2003-06-18 02:00
[hogan@station hogan]$ atq
11 2003-06-18 02:00 a hogan

Examen de la sintaxis Spool

El usuario ventura ha notado que hogan tiene la costumbre de imprimir la correspondencia de sus
admiradores a las 2:00 am y como un chiste práctico decide someter un trabajo de su propiedad.
Crea el archivo bogus_fanmail.txt, que falsifica correspondencia no muy elogiosa de sus fanáticos.
Somete un trabajo que imprimirá el archivo a la 1:59 am confiando que hogan no notará la
inserción cuando recoja los papeles de la impresora en la mañana.

[ventura@station ventura]$ echo "lpr bogus_fanmail.txt" | at 1:59 am


warning: commands will be executed using (in order) a) $SHELL b) login shell c)
/bin/sh
job 12 at 2003-06-18 01:59
[ventura@station ventura]$ atq
12 2003-06-18 01:59 a ventura

En cierto punto más adelante, el administrador del sistema de la máquina actuando como root,
observa los dos trabajos at en espera.

[root@station at]# atq


11 2003-06-18 02:00 a hogan
12 2003-06-18 01:59 a ventura

384
Curioso por lo que ventura piensa hacer, root fisgonea dentro del directorio spool de at. Examina el
contenido de su nombre de archivo spool llamado de forma críptica a0000c010c8887, el cual
pertenece al usuario ventura.

[root@station at]# ls -l
total 12
-rwx------ 1 hogan hogan 1480 Jun 17 12:37 a0000b010c8888
-rwx------ 1 ventura ventura 1459 Jun 17 13:08 a0000c010c8887
drwx------ 2 daemon daemon 4096 Jun 16 17:24 spool
[root@station at]# cat /var/spool/at/a0000c010c8887
#!/bin/sh
# atrun uid=511 gid=511
# mail ventura 0
umask 2
HOSTNAME=bowe-lt.rdu.redhat.com; export HOSTNAME
HISTSIZE=1000; export HISTSIZE
USER=ventura; export USER
LOGNAME=ventura; export LOGNAME
...
LESSOPEN=\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN
G_BROKEN_FILENAMES=1; export G_BROKEN_FILENAMES
XAUTHORITY=/home/ventura/.xauthqEj97Q; export XAUTHORITY
cd /home/ventura || {
echo 'Execution directory inaccessible' >&2
exit 1
}
lpr bogus_fanmail.txt

(En este listado largo, se han borrado varias líneas y se han remplazado por "...".)

root observa los siguientes aspectos de la conducta del script:

El archivo es un script de shell y debido a sus permisos pudo ejecutarse directamente.


La primera acción del script es la de establecer la umask del proceso a la umask de shell que
sometió el trabajo.
La segunda acción es inicializar una colección de variables de entorno para imitar el entorno
de shell que sometió el trabajo.
La tercera acción es cambiar el directorio actual del proceso al directorio actual de trabajo de
la shell que sometió el trabajo.
Por último, después de toda esta inicialización, el guión está listo para ejecutar el trabajo
sometido, en este caso lpr bogus_fanmail.txt.

Al almacenar toda esta información con el trabajo sometido, el demonio atd es capaz de reconstruir
el entorno de ventura cuando se envía el trabajo. Si el trabajo enviado crea nuevos archivos, los
archivos tendrían los permisos esperados, porque el guión crearía la umask apropiada. Si
cualquiera de los comandos iniciados por el script dependiera de las variables de entorno, el
entorno se establecería como se espera y así sucesivamente.

(En este listado largo, se han borrado varias líneas y se han remplazado por "...".)

root observa los siguientes aspectos de la conducta del script:

385
El archivo es un script de shell y debido a sus permisos pudo ejecutarse directamente.
La primera acción del script es la de establecer la umask del proceso a la umask de shell que
sometió el trabajo.
La segunda acción es inicializar una colección de variables de entorno para imitar el entorno
de shell que sometió el trabajo.
La tercera acción es cambiar el directorio actual del proceso al directorio actual de trabajo de
la shell que sometió el trabajo.
Por último, después de toda esta inicialización, el guión está listo para ejecutar el trabajo
sometido, en este caso lpr bogus_fanmail.txt.

Al almacenar toda esta información con el trabajo sometido, el demonio atd es capaz de reconstruir
el entorno de ventura cuando se envía el trabajo. Si el trabajo enviado crea nuevos archivos, los
archivos tendrían los permisos esperados, porque el guión crearía la umask apropiada. Si
cualquiera de los comandos iniciados por el script dependiera de las variables de entorno, el
entorno se establecería como se espera y así sucesivamente.

Ejercicios en línea

Someter un trabajo para una ejecución posterior

Ejercicio Objetivo: Utilizar el servicio atd para retrasar la ejecución de una tarea.

Estimated Time: 10 mins.

Especificaciones

Usted ha tenido dificultades tratando de recordar qué día es y por lo tanto quisiera enviarse una
copia del calendario actual para verlo como primera cosa en la mañana. Envía un trabajo que
simplemente ejecuta el comando cal para las 3:45 de la mañana. Asegúrese que es el único
trabajo programado con esa facultad.

Deliverables A title Question 1

Un trabajo en espera que generará la salida del comando cal a las 3:45 de la mañana.

386
Programación de tareas periódicas: cron

Conceptos clave

• La utilidad cron se utiliza para programar tareas recurrentes.


• El comando crontab provee un frontend para editar archivos crontab.
• El archivo crontab utiliza 5 campos para especificar la información de temporización.
• la stdout de trabajos cron se envía por correo al usuario.

Discussion

Ejecución de tareas periódicas

A menudo, las personas encuentran que están realizando tareas en forma sistemática. En la
administración de sistemas dichas tareas podrían incluir quitar archivos viejos o no utilizados del
directorio /tmp o comprobar si un archivo que está recolectando mensajes de registro no ha crecido
demasiado. Otros usuarios podrían hallar que son tareas propias el chequear archivos grandes que
ya no se estén utilizando o chequear un sitio web para ver si hay algún anuncio.

El servicio cron permite a los usuarios configurar comandos para que se ejecuten con regularidad
tal como cada 10 minutos, una vez cada jueves, o dos veces al mes. Los usuarios especifican qué
comandos deberían ejecutarse y a qué horas mediante el comando crontab para configurar su
"cuadro cron". Las tareas se administran por el demonio tradicional de Linux (y Unix), el demonio
crond.

El servicio cron

El demonio crond es el demonio que realiza tareas periódicamente en nombre del sistema o de
usuarios individuales. El demonio suele iniciarse cuando el sistema arranca, por lo tanto, la
mayoría de usuarios lo pueden ignorar. Al listar todos los procesos y buscar crond puede confirmar
si el demonio crond está en ejecución.

[hogan@station hogan]$ ps aux | grep crond


root 891 0.0 0.0 1572 128 ? S Jun17 0:00 crond
hogan 8118 0.0 0.2 3576 644 pts/2 S 10:15 0:00 grep
crond

Si el demonio crond no está ejecutándose, su administrador de sistema necesitaría iniciar el


servicio crond como root.

Sintaxis crontab

Los usuarios especifican los trabajos que se van a ejecutar y cuándo se van a ejecutar, al
configurar un archivo conocido como el "cuadro cron" a menudo abreviado en inglés "crontab". Un
ejemplo de archivo crontab aparece a continuación.

387
# set the default language to be english
LOCALE=en_US

05 * * * * procinfo
15 04 * * * find $HOME -size +100k
25 04 1 * * echo "Pay your bills"
35 04 14 3 * echo "Beware the Ides of March" | mail -s "a warning" julius
45 04 * * 1 find $HOME -atime +30 | lpr

Un archivo crontab es un archivo de configuración basado en línea, cada línea realiza una de tres
funciones:

Comentarios

Todas las líneas cuyo primer caracter (no espacio) es # se consideran comentarios y se
ignoran.

Variables de entorno

Todas las líneas que tienen la forma nombre = valor se utilizan para definir variables de
entorno.

Comandos cron

Cualquier otra línea (no en blanco) se considera un comando cron, el cual consta de seis
campos descritos a continuación.

Las líneas del comando cron constan de seis campos separados de espacios en blanco. Los
primeros 5 campos se utilizan para especificar cuándo ejecutar el comando y el sexto campo se
utiliza para especificar el comando a ejecutar (compuesto de todo después del quinto campo). Los
primeros cinco campos especifican la siguiente información:

,----------------> minute
| ,-------------> hour
| | ,----------> day of month
| | | ,-------> month (1=January, 2=February, ...)
| | | | ,----> day of week (0=Sunday, 1=Monday, ...)
| | | | | ,-> command to run
| | | | | |
25 04 1 * * echo "Pay your bills"

Cada uno de los primeros cinco campos debe llenarse con un símbolo mediante la siguiente
sintaxis:

símbolo significado ejemplo interpretación (si se utiliza en el primer campo)


* cada vez * cada minuto
n a la hora especificada 10 cada hora y 10 minutos
n, n, ... a cualquiera de las horas 22,52 a cada hora pasados los 22 y 52 minutos
especificadas
*/n cada n hora */15 cada 15 minutos (a los 0, 15, 30 y 45 minutos

388
después de la hora)

Uso del comando crontab

Los usuarios rara vez administran su archivo crontab directamente (o incluso saben dónde se
almacena), en cambio, utilizan el comando crontab para editar la lista o quitarla.

crontab {[-e] | [-l] | [-r]}

crontab ARCHIVO

Edita o quita el archivo crontab actual o remplaza el archivo actual crontab con FILE.

Opción Efecto
-e modifica el archivo actual
-l lista el archivo actual
-r quita el archivo actual

En la siguiente secuencia de comandos, hogan utilizará el comando crontab para administrar su


configuración crontab. Primero lista su configuración actual crontab en la pantalla, luego lista el
archivo actual otra vez almacenando la salida dentro del archivo mycopy.

[hogan@station hogan]$ crontab -l


# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.9212 installed on Wed Jun 18 11:46:36 2003)
# (Cron version -- $Id: 040_crontab.dbk,v 1.1 2005/03/21 05:24:29 brads Exp $)
# set the default language to be english.
LOCALE=en_US

05 * * * * procinfo
15 04 * * * find $HOME -size +100k
25 04 1 * * echo "Pay your bills"
35 04 14 3 * echo "Beware the Ides of March" | mail -s "a warning" julius
45 04 * * 1 find $HOME -atime +30 | lpr
[hogan@station hogan]$ crontab -l > mycopy

Luego, hogan quita su configuración de crontab actual. Cuando trata de nuevo de listar la
configuración, se le informa que no existe ninguna configuración actual.

[hogan@station hogan]$ crontab -r


[hogan@station hogan]$ crontab -l
no crontab for hogan

Con el fin de restaurar su configuración cron, hogan utiliza el comando crontab una vez más, esta
vez especificando el archivo mycopy como un argumento. Tras listar su configuración una vez más,
halla que su actual configuración fue leída desde el archivo mycopy.

389
Un poco molesto, el banner se ha duplicado en el proceso, ¿sabe por qué?

[hogan@station hogan]$ crontab mycopy


[hogan@station hogan]$ crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (mycopy installed on Wed Jun 18 11:47:00 2003)
# (Cron version -- $Id: 040_crontab.dbk,v 1.1 2005/03/21 05:24:29 brads Exp $)
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.9212 installed on Wed Jun 18 11:46:36 2003)
# (Cron version -- $Id: 040_crontab.dbk,v 1.1 2005/03/21 05:24:29 brads Exp $)
# set the default language to be english.
LOCALE=en_US

05 * * * * procinfo
15 04 * * * find $HOME -size +100k
25 04 1 * * echo "Pay your bills"
35 04 14 3 * echo "Beware the Ides of March" | mail -s "a warning" julius
45 04 * * 1 find $HOME -atime +30 | lpr
[hogan@station hogan]$ rm mycopy
7 2003-06-17 02:00 a hogan

Modificar archivos crontab ya establecidos

Los usuarios suelen modificar sus archivos crontab mediante crontab -e. El comando crontab
abrirá la configuración crontab dentro del editor predeterminado del usuario. Cuando el usuario
termina de modificar el archivo y sale del editor, el contenido modificado del archivo se instala
como la nueva configuración crontab.

El editor por defecto es /bin/vi, sin embargo,crontab, al igual que otros comandos, examina la
variable de entorno EDITOR. Si la variable se ha establecido, se utilizará para especificar el editor
que se va a abrir. Por ejemplo, si hogan prefiere utilizar el editor nano, primero puede configurar la
variable de entorno EDITOR como /usr/bin/nano (o simplemente nano) y luego ejecutar crontab -
e.

Si hogan quisiera utilizar nano como su editor podría utilizar uno de los siguientes métodos:

[hogan@station hogan]$ export EDITOR=nano


[hogan@station hogan]$ crontab -e

[hogan@station hogan]$ EDITOR=nano crontab -e

o aún mejor, hogan pudo agregar la línea "export EDITOR=nano" a su archivo .bash_profile y la
variable de entorno se establecería automáticamente cada vez que inicie sesión.

En resumen, hay dos formas de crear o modificar la configuración crontab.

390
1. Crear un archivo de texto que contenga su configuración deseada y luego instalarlo con
crontab FILENAME.
2. Editar su configuración establecida con crontab -e.

¿A dónde va la salida?

¿Cómo recibe el usuario la salida de los comandos que cron ejecuta? El demonio enviará por
correo la stdout y el stderr de todos los comandos ejecutados al usuario local. Suponga que
ventura configuró el siguiente trabajo cron:

05 * * * * cal

Una vez por hora, a la hora y cinco minutos espera recibir un nuevo correo como el siguiente:

Date: Wed, 18 Jun 2003 14:24:00 -0400


From: root@station.redhat.com (Cron Daemon)
To: ventura@station.redhat.com
Subject: Cron <ventura@station> cal
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/ventura>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=ventura>

June 2003
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

El mensaje del correo contiene la salida del comando en el cuerpo y todas las variables de entorno
en los encabezados.

Opcionalmente, ventura podría haber definido la variable de entorno especial MAILTO a una
dirección de correo electrónico y el correo sería enviado a esa dirección en su lugar:

MAILTO=ventura@redhat.com

05 * * * * cal

Variables de entorno y cron

Al configurar trabajos cron, los usuarios deberían tener en cuenta un detalle. Cuando el demonio
crond inicia el comando del usuario, éste no ejecuta el comando desde la shell sino que bifurca y
exec el comando directamente. Esto tiene una implicación importante: cualquier variable de
entorno o alias configurados por la shell en el arranque tal como cualquiera que esté definida en
/etc/profile o ~/.bash_profile, no estarán disponibles cuando cron ejecute el comando.

391
Si un usuario quiere que una variable de entorno esté definida necesita explícitamente definir la
variable en su configuración crontab.

Ejemplos

Control de un sitio web

ventura quiere asegurarse que no se va a perder de ninguna nueva oportunidad de formación de


su compañía favorita, Red Hat Inc. Con el fin de estar pendiente de estas oportunidades configura
un trabajo cron que descargará la página web de formación de Red Hat y se la enviará como un
correo electrónico una vez por la mañana. Con el fin de modificar su configuración en el lugar
utiliza el comando crontab -e.

[ventura@station ventura]$ crontab -e


no crontab for ventura - using an empty one

(... while in the text editor, ventura adds the following line...)

00 05 * * * links -dump http://www.redhat.com/training

(... and quits the text editor...)

crontab: installing new crontab

Luego confirma que su trabajo cron esté en su lugar.

[ventura@station ventura]$ crontab -l


# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.10296 installed on Wed Jun 18 14:17:43 2003)
# (Cron version -- $Id: 010_text.dbk,v 1.1 2005/03/21 05:24:29 brads Exp $)

00 05 * * * links -dump http://www.redhat.com/training

ventura ahora puede esperar recibir correo electŕonico, conteniendo una versión formateada de
texto de la página web de formación de Red Hat cada mañana a las 5:00.

Control de archivos grandes

Luego, ventura se da cuenta que ha tenido la mala costumbre de crear archivos muy grandes y
luego los olvida. Con el fin de ayudarse a recordar los archivos grandes que está dejando atrás,
configura un trabajo cron el cual le enviará cada domingo un correo con una lista de todos los
archivos mayores de 100k.

392
[ventura@station ventura]$ crontab -e
no crontab for ventura - using an empty one

(... within the text editor, ventura adds the following line...)

05 05 * * 0 find $HOME -size +100k

(... and exits the text editor ...)

crontab: installing new crontab


[ventura@station ventura]$ crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.10678 installed on Wed Jun 18 14:50:39 2003)
# (Cron version -- $Id: 010_text.dbk,v 1.1 2005/03/21 05:24:29 brads Exp
$)

00 05 * * * links -dump http://www.redhat.com/training


10 05 * * 0 find $HOME -size +100k

Ahora, los domingos a las 5:10 de la mañana, ventura puede esperar recibir un correo electrónico
listando todos los archivos mayores de 100 K bajo su directorio de inicio.

Ejecución de scripts desde cron

Continuando con sus esfuerzos de no desperdiciar espacio duro, ventura desearía crear
regularmente una lista separada de archivos a los que no haya tenido acceso reciéntemente y
recibir esta lista al mismo tiempo que recibe su lista de archivos grandes. En lugar de complicar su
archivo cron, crea un guión llamado cron.weekly, lo coloca en el subdirectorio bin y lo hace
ejecutable.

[ventura@station ventura]$ cat cron.weekly


#!/bin/bash

echo "===== files larger than 100k ====="


find $HOME -size +100k

echo
echo "==== files not used in the past month ====="
find $HOME -atime +30

[ventura@station ventura]$ mkdir bin


[ventura@station ventura]$ mv cron.weekly bin/
[ventura@station ventura]$ chmod 755 bin/cron.weekly
Luego, modifica su configuración crontab para que su guión se ejecute como un trabajo cron una
vez por semana:

393
[ventura@station ventura]$ crontab -e

(... within the text editor, ventura edits the following line ...)

05 05 * * 0 find $HOME -size +100k

(... so that it reads ...)

05 05 * * 0 bin/cron.weekly

(... and exits ...)

crontab: installing new crontab


[ventura@station ventura]$ crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.11252 installed on Wed Jun 18 15:45:53 2003)
# (Cron version -- $Id: 010_text.dbk,v 1.1 2005/03/21 05:24:29 brads Exp
$)
00 05 * * * links -dump http://www.redhat.com/training
05 05 * * 0 bin/cron.weekly

Ahora en lugar de mantener su configuración crontab, ventura puede apenas modifica el script
cron.weekly.

Impresión de fanmail

El usuario hogan ha llegado al punto donde imprime el archivo que recoge la nueva
correspondencia de los admiradores, fanmail.txt, cada lunes, miércoles y viernes. Decide utilizar el
servicio cron para automatizar el proceso.

Debido a que esta es la primera vez que utiliza cron, él no tiene que preocuparse por la posibilidad
de remplazar trabajos ya existentes. Entonces configura un archivo cron localmente. Mediante un
editor de texto, crea el archivo crontab.hogan en su directorio de inicio. Luego instala el archivo con
el comando crontab.

[hogan@station hogan]$ cat crontab.hogan

45 13 * * 1,3,5 lpr fanmail.txt


[hogan@station hogan]$ crontab crontab.hogan

Ahora espera que su archivo de correspondencia de sus admiradores sea impreso los lunes,
miércoles y viernes en las tardes a la 1:45. Cuando se imprimen las primeras copias se envían a la
impresora que no es, hogan nota que su .bash_profile configura su variable de entorno PRINTER
para cola de espera local, hp-color, automáticamente cuando inicia sesión. Sin embargo, como
cron no utiliza una shell para ejecutar trabajos cron, la variable de entorno de inicio sesión no se
está configurando. Edita crontab.hogan para definir explícitamente y vuelve a someter el archivo
con crontab.

394
[hogan@station hogan]$ cat crontab.hogan

PRINTER=hp-color
45 13 * * 1,3,5 lpr fanmail.txt
[hogan@station hogan]$ crontab crontab.hogan

Ahora su trabajo imprime en la impresora correcta.

395
Ejercicios en línea

Control de quién está en el sistema. Ejercicio en línea Objetivo: Configurar un trabajo cron

Estimated Time: 10 mins. Especificaciones

Está un poco paranóico y quiere controlar quién está usando su computador en la noche. Configura
un trabajo cron que le enviará por correo la salida del comando who diariamente a las 4:35 de la
mañana.

Deliverables A title Question 1

1. Una configuración cron que envía por correo la salida del comando who diariamente a las
4:30 am.

396
Network Applications
Introducción a las redes TCP/IP

Conceptos clave

• La mayoría de los servicios de redes de Linux están diseñados en torno a una relación de
cliente servidor.
• Las aplicaciones de servidor de red generalmente están diseñadas para permanecer
"siempre en ejecución" iniciándose automáticamente cuando el sistema arranca y
apagándose solamente cuando el sistema lo hace. Por lo general, sólo el usuario root
puede administrar procesos del servidor.
• Las aplicaciones de cliente de red suelen ejecutarse únicamente cuando están en uso y las
puede iniciar cualquier usuario.
• La mayoría de los servidores de red Linux y clientes se comunican mediante el
protocoloTCP/IP.
• La dirección TCP/IP tanto del proceso del cliente como del proceso del servidor consta de
una dirección IP y de un puerto.
• Los servidores de red suelen utilizar puertos asignados denominados puertos "bien
conocidos" como se catalogan en el archivo /etc/services. Los clientes de red suelen
utilizar puertos privilegiados de modo aleatorio. A menudo, los puertos bien conocidos
residen en el rango de puertos privilegiados por debajo del puerto número 1024.
• El comando hostname puede utilizarse para examinar la dirección IP actual de la máquina,
mientras que el comando netstat -tuna se puede utilizar para examinar todos los puertos
abiertos.

Discussion

Clientes, servidores y protocolo TCP/IP

Iniciaremos nuestro cuaderno sobre las aplicaciones de redes con la introducción a los conceptos
de clientes y servidores y los aspectos básicos del protocolo TCP/IP. Hablaremos del protocolo
TCP/IP como si fuera el único protocolo disponible en Internet. Este no es el caso pero es el
protocolo más utilizado y los conceptos necesarios para entender se amplían (o reducen) de forma
natural a los otros protocolos.

La mayoría de las aplicaciones de redes actuales están diseñadas en torno a la relación cliente-
servidor. El cliente de red suele ser una aplicación que actúa en nombre de una persona que está
tratando de realizar alguna tarea en particular tal como navegar en una URL o ejecutar el comando
rdate para preguntar la hora actual a un servidor de tiempo. El servidor de red suele ser una
aplicación que ofrece servicios, tales como entregar el contenido de las páginas web o dar la hora
actual.

El diseño de (aplicaciones que actúan como) clientes de red y (aplicaciones que actúan como)
servidores de red difiere dramáticamente. Con el fin de apreciar las diferencias, los compararemos
con los agentes en una relación cliente-servidor, un cliente comprando una barra de caramelo a un
vendedor.

El servidor

Los vendedores y los servicios de red efectivos comparten las siguientes características.

397
Los servidores están altamente disponibles

Así como un vendedor siempre debe utilizar la registradora, incluso cuando no hay clientes, los
procesos que ejecutan servicios de red necesitan estar ejecutándose, listos para suplir los servicios
cuando se soliciten. Por lo general, los procesos que ejecutan servicios de red se inician en el
momento de arranque y continúan ejecutándose hasta que la máquina sea apagada. En Linux (y
Unix) dichos procesos se conocen como demonios. Por lo general, sólo el usuario root puede
iniciar o cerrar procesos que funcionan como servidores de red.

Los servidores tienen sitios bien conocidos

Además de estar disponibles cuando un cliente necesita el servicio, los vendedores se están dónde
saben que los clientes los pueden encontrar. Así como los clientes pueden buscar la ubicación de
vendedores de caramelos desconocidos, en los directorios telefónicos y encontrarlos por dirección
postal, los clientes de red pueden ubicar servidores de redes desconocidas mediante un hostname,
el cual se convierte en la dirección IP utilizada para tener acceso al servicio.

El cliente

Por el contrario, el cliente de la tienda de caramelos no necesita estar ni altamente disponible ni ser
muy conocido. Un cliente no se estará en una tienda de caramelos todo el día por si decide
comprar un caramelo. Del mismo modo, los clientes no necesitan permanecer en sitios bien
conocidos. Nuestro cliente no se queda todo el día en casa por si alguien pasa a venderle una
barra de caramelo.

Los procesos que ejecutan clientes de red son iniciados por usuarios normales y por lo general se
ejecutan todo el tiempo necesario para completar una tarea. Cuando alguien hace un receso para ir
a almorzar, cierra su navegador de red. Además, las aplicaciones de cliente no necesitan tener
direcciones fijas, pueden moverse de un lugar a otro. Más adelante veremos esto detalladamente.

Direcciones TCP/IP

Todo proceso que participa en una conversación TCP/IP debe tener una Dirección IP, así como
cada participante en una conversación debe tener un número telefónico. Además, todo proceso en
una conversación TCP/IP debe tener un número de puerto, cuya analogía más cercana podría ser
una extensión telefónica asociada a un número de teléfono.

Los computadores en una red se identificans con una dirección IP. La dirección IP viene en forma
de cuatro números enteros, cada uno en un rango de 0 a 255 (no es una coincidencia que la
cantidad de información pueda codificarse en un byte de memoria) y tradicionalmente separados
por puntos así como 192.168.0.3. Esta representación suele conocerse de modo informal como un
quad punteado.

Los procesos en computadores se identifican con unnúmero de puerto, el cual es un entero entre 1
y 65535 (no es una coincidencia que la cantidad de información se codifique en 2 bytes de
memoria). Cada vez que un proceso quiere participar en una conversación TCP/IP con otro
proceso, el kernel debe asignarle primero un número de puerto.

El protocolo TCP/IP permite dos procesos, para localizarse entre sí, cada uno se identifica con una
dirección IP y un número de puerto. La dirección IP sirve para localizar la máquina en la que el
proceso se está ejecutando (esta es la "parte del protocolo IP") y el número de puerto se utiliza
para localizar el proceso correcto en la máquina (esta es la parte "TCP").

398
Sockets

Con el fin de ilustrar una transacción típica TCP/IP, examinaremos la conversación entre el
navegador de red mozilla de un estudiante fictisio ejecutándo en la máquina
station3.example.com, lo que se traduce en una dirección IP 123.45.67.89 y el servidor de red
httpd ejecutando en academy.redhat.com, lo que se traduce en una dirección IP de 66.187.232.51.
El proceso suele parecerse a lo siguiente.

1. Cuando la máquina academy.redhat.com arranca, se inicia el proceso httpd. Primero


asigna un socket, ejecuta bind al puerto 80 y comienza a listen conexiones.
2. En algún momento más tarde, quizás minutos o días, el proceso mozilla se inicia en la
máquina station3.example.com. También asigna un socket y solicita connect al puerto 80
de la máquina 66.187.232.51. Puesto que no pidió un número de puerto particular, el
kernel provee uno aleatorio, digamos 12345. Como le solicita la conexión, provee su propia
dirección IP y el número de puerto (asignado de modo aleatorio) al servidor.
3. El servidor selecciona la conexión accept. El socket establecido se identifica ahora con
dirección IP y número de puerto del cliente y del servidor.

Una vez se establece el socket, los procesos mozilla y httpd pueden leer información con read y
escribir a un archivo con write de un modo tan sencillo como leer y escribir desde un archivo,
(recuerde ..."todo es un archivo", incluyendo las conexiones de red! Para fines más prácticos, un
socket es sólo otro descriptor de archivo). Los verbos resaltados en esta sección bind (unir), listen
(escuchar), connect (conectar), accept (aceptar), e inclusoread (leer) y write (escribir) son
términos bien definidos en Linux (y Unix). También son los nombres de llamadas al sistema de
programación que realizan cada paso.

Figure 1. Un socket TCP/IP entre un navegador de red Mozilla y un servidor Apache

En el protocoloTCP/IP, un socket se define como la combinación de una dirección IP y el número


de puerto del servidor y cliente. Por ejemplo, ¿qué sucedería si nuestro estudiante estuviera
ejecutando múltiples versiones de Mozilla, cada uno haciendo solicitudes de academy.redhat.com?
o ¿qué sucedería si múltiples usuarios estuvieran usando la máquina station3.example.com
simultáneamente todas accediendo academy.redhat.com? ¿De qué forma mantendría en orden un
servidor de red qué conversación estaba teniendo con cuál cliente? A cada proceso de cliente se le
asignaría un número de puerto distinto y por lo tanto conversa con el demonio httpd mediante un
socket diferente.

399
Figure 2. Múltiples sockets TCP/IP

Más acerca de puertos

Servicios bien conocidos y el archivo /etc/services

En nuestro ejemplo, mencionamos que el proceso httpd solicitó bind al puerto 80, y en retorno, el
proceso mozilla solicitó connect al puerto 80 del servidor. ¿Cómo se convino que el puerto 80 era
el apropiado para el servidor de red? Los servicios de Internet tradicionales tales como el servidor
de red o el servidor ftp o el servidor smtp (de correo electrónico), se conocen como servicios bien
conocidos. En máquinas de Linux y (Unix), el catálogo de servicios bien conocidos, y los puertos
asignados a ellos se mantienen en el archivo /etc/services.

Observe que tanto el cliente como el servidor necesitan concordar con el número apropiado de
puerto para que el archivo /etc/services sea tan importante en la máquina del cliente como en la del
servidor. El sólo hecho de que un servicio se liste en el archivo /etc/services no significa que usted
está ejecutando (o incluso siendo capaz de ejecutar) ese servicio bien conocido.

Puertos privilegiados

A diferencia de los clientes, los procesos que ejecutan servidores de red suelen solicitar el puerto al
que quieren vincularse. Solamente un proceso puede vincularse a un puerto en un tiempo
determinado (¿A qué se debe esto?) Los puertos menores de 1024 se conocen como puertos
privilegiados y son tratados de modo especial por el kernel. Únicamente los procesos ejecutándose
como el usuario root pueden enlazarse a puertos privilegiados, (esto ayuda a asegurar que si elvis
tuviera una cuenta en la máquina academy.redhat.com, no podría iniciar una versión falsa de un
servidor de red que podría distribuir información falsa). En un principio, los puertos bien conocidos
y los puertos con privilegios pretendian coincidir pero en la práctica hay más puertos bien
conocidos que privilegiados.

400
Determinar los servicios actuales de red TCP/IP

Uso de hostname para visualizar la dirección IP actual

El comando hostname, sin argumentos, muestra el nombre del equipo de la máquina actual. Con
la opción -i, la dirección IP de la máquina se visualiza en su lugar.

[elvis@station elvis]$ hostname


station.example.com
[elvis@station elvis]$ hostname -i
172.16.62.9

¿Qué sucede si hay múltiples direcciones IP?

El diseño del comando hostname es un poco equívoco, porque las máquinas pueden tener
fácilmente más de una dirección IP (una para cada red múltiple de tarjetas de interfaz, por
ejemplo). En dichas situaciones, no hay razón para que cualquier dirección IP tenga prioridad
sobre las otras. No obstante, por razones históricas, el kernel mantiene el rastro de un
parámetro conocido como su nombre del equipo y el comando hostname -i presenta la
dirección IP asociada con éste.

Uso del comando netstat para ver los puertos abiertos

Cuando un puerto es utilizado por un socket se le conoce como puerto abierto. El comando netstat
sirve para ver una variedad de información de redes incluyendo los puertos abiertos.

Infortunadamente, cuando un comando es llamado sin ninguna opción la salida del comando
netstat se inunda de información poco interesante, sockets locales "Unix" utilizados para
comunicarse entre procesos en la misma máquina. Sin embargo, cuando se llama con las
siguientes opciones se ve información más interesante.

Table 1. Opciones para el comando netstat

Opción Efecto
-t Presenta los sockets TCP
-u Presenta los sockets UDP
-n Presenta la dirección IP en lugar del hostname
-a Presenta todos los sockets incluso aquellos en estado LISTEN

Muchas más opciones están disponibles, para mayor información acuda a la página de manual
netstat(8). Las siguientes opciones se escogieron, no solo porque cuando se combinan producen
una salida interesante, sino porque también son fáciles de recordar: por ejemplo, "tuna" (atún).

401
Cuando se invoca con las siguientes opciones, la salida de netstat es similar a la siguiente.

[elvis@station elvis]$ netstat -tuna


Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:32768 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:777 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 127.0.0.1:32769 ESTABLISHED
tcp 0 0 172.16.62.9:32903 172.16.62.8:6001 ESTABLISHED
tcp 0 0 172.16.62.9:32848 172.16.62.8:6001 ESTABLISHED
...
tcp 0 0 172.16.62.9:33325 172.16.62.8:6001 ESTABLISHED
tcp 0 0 127.0.0.1:33953 127.0.0.1:631 TIME_WAIT
tcp 0 0 127.0.0.1:33952 127.0.0.1:631 TIME_WAIT
...
tcp 0 314 127.0.0.1:32769 127.0.0.1:631 ESTABLISHED
tcp 0 0 172.16.62.9:34387 172.16.62.8:22 ESTABLISHED
udp 0 0 0.0.0.0:32768 0.0.0.0:*
udp 0 0 0.0.0.0:177 0.0.0.0:*
...

¿Qué sucede si hay múltiples direcciones IP?

El diseño del comando hostname es un poco equívoco, porque las máquinas pueden tener
fácilmente más de una dirección IP (una para cada red múltiple de tarjetas de interfaz, por
ejemplo). En dichas situaciones, no hay razón para que cualquier dirección IP tenga prioridad
sobre las otras. No obstante, por razones históricas, el kernel mantiene el rastro de un
parámetro conocido como su nombre del equipo y el comando hostname -i presenta la
dirección IP asociada con éste.

Uso del comando netstat para ver los puertos abiertos

Cuando un puerto es utilizado por un socket se le conoce como puerto abierto. El comando netstat
sirve para ver una variedad de información de redes incluyendo los puertos abiertos.

Infortunadamente, cuando un comando es llamado sin ninguna opción la salida del comando
netstat se inunda de información poco interesante, sockets locales "Unix" utilizados para
comunicarse entre procesos en la misma máquina. Sin embargo, cuando se llama con las
siguientes opciones se ve información más interesante.

402
Table 1. Opciones para el comando netstat

Opción Efecto
-t Presenta los sockets TCP
-u Presenta los sockets UDP
-n Presenta la dirección IP en lugar del hostname
-a Presenta todos los sockets incluso aquellos en estado LISTEN

Muchas más opciones están disponibles, para mayor información acuda a la página de manual
netstat(8). Las siguientes opciones se escogieron, no solo porque cuando se combinan producen
una salida interesante, sino porque también son fáciles de recordar: por ejemplo, "tuna" (atún).

Cuando se invoca con las siguientes opciones, la salida de netstat es similar a la siguiente.

[elvis@station elvis]$ netstat -tuna


Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:32768 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:777 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 127.0.0.1:32769 ESTABLISHED
tcp 0 0 172.16.62.9:32903 172.16.62.8:6001 ESTABLISHED
tcp 0 0 172.16.62.9:32848 172.16.62.8:6001 ESTABLISHED
...
tcp 0 0 172.16.62.9:33325 172.16.62.8:6001 ESTABLISHED
tcp 0 0 127.0.0.1:33953 127.0.0.1:631 TIME_WAIT
tcp 0 0 127.0.0.1:33952 127.0.0.1:631 TIME_WAIT
...
tcp 0 314 127.0.0.1:32769 127.0.0.1:631 ESTABLISHED
tcp 0 0 172.16.62.9:34387 172.16.62.8:22 ESTABLISHED
udp 0 0 0.0.0.0:32768 0.0.0.0:*
udp 0 0 0.0.0.0:177 0.0.0.0:*
...
De las muchas líneas, podemos retirar aquellas asociadas con el protocolo udp y concentrarnos en
las columnas 4, 5 y 6 de las filas asociadas con tcp.

Table 2. Columnas relevantes desde la salida de netstat

Columna Título Función


1 Protocolo El protocolo del socket. Nos referiremos a los sockets tcp.
4 Dirección local La dirección IP y el número de puerto de la mitad local del socket.
5 Dirección La dirección IP y el número del puerto de la mitad remota del socket.
extranjera
6 Estado El estado de la conexión TCP. Nos referiremos a los estados más
interesantes LISTEN y ESTABLECIDO.

403
Direcciones especiales IP

Las siguientes direcciones IP pueden hallarse en la columna de dirección local de la salida anterior.

Dirección Función
IP
172.16.62.9 La dirección IP externa de la máquina tal como la reportó el comando hostname -i.
127.0.0.1 La dirección bucle local. Cada máquina que utiliza las redes TCP/IP es compatible
con la dirección de bucle local o loopback. Las conexiones a la máquina o desde la
máquina desde esta dirección siempre se retroalimentan a la máquina local para que
la comunicación pueda ocurrir entre dos procesos en la misma máquina. La
conversación que se presenta sobre la dirección de bucle local ocurre internamente,
no se expone a la red.
0.0.0.0 Esta dirección especial IP sirve para referirse a "todas" las direcciones IP
disponibles. Cuando un proceso se enlaza a un determinado puerto, puede elegir
entre utilizar únicamente una dirección particular externa, sólo la dirección de bucle
local o todas las direcciones IP disponibles.

Sockets de escucha

Los sockets de escucha son conexiones pertenecientes a un servidor antes de que los clientes se
presenten. Por ejemplo, al final del primer paso de nuestra conexión TCP/IP de muestra anterior, el
proceso httpd tendría una conexión abierta en el estado de escucha. Observe en la salida anterior
que para las conexiones de escucha, sólo se define la mitad de la dirección.

Conexiones establecidas

Como su nombre lo implica, los sockets establecidos tienen un proceso de cliente y un proceso de
servidor con comunicación establecida.

Uniendo esfuerzos

Ahora podemos reunir algunas de las partes para analizar unas pocas líneas extraídas de la salida
anterior.

tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN

Este socket está conectado a todas las interfaces en el puerto 80 en el estado de ESCUCHA.
Aparentemente esta máquina también tiene un servidor de red httpd escuchando activamente
conexiones de clientes.

tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN


tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN

Estos dos sockets están escuchando conexiones, pero sólo en la dirección de bucle local. Deben
pertenecer a servicios que esperan recibir conexiones desde otros procesos en la máquina local

404
pero no desde la red. Para determinar a qué servicios pertenecen estos puertos ejecutamos un
grep desde el archivo /etc/services.

[elvis@station elvis]$ grep 25 /etc/services


smtp 25/tcp mail
smtp 25/udp mail
timed 525/tcp timeserver
timed 525/udp timeserver
prospero-np 1525/tcp # Prospero non-privileged
prospero-np 1525/udp
[elvis@station elvis]$ grep 631 /etc/services
ipp 631/tcp # Internet Printing Protocol
ipp 631/ucp # Internet Printing Protocol

Aparentemente, cualquier proceso que haya solicitado el puerto 25 está escuchando clientes de
correo electrónico. Probablemente es el demonio sendmail. El proceso de escucha en el puerto
631 está escuchando clientes de impresión. Probablemente es el demonio de impresión cupsd.
Ambos servicios se tratarán más adelante en este cuaderno.

tcp 0 314 127.0.0.1:32769 127.0.0.1:631 ESTABLISHED


Esta línea refleja una conexión establecida entre dos procesos ambos en la máquina local (observe
la dirección IP de bucle local para los dos). El primero está conectado al puerto 32769
(probablemente un puerto cliente asignado de modo aleatorio) y el segundo al puerto 631. Algunos
procesos en la máquina local deben estar comunicándose con el demonio cupsd.

tcp 0 0 172.16.62.9:34387 172.16.62.8:22 ESTABLISHED

Nuestra línea extraída representa una conexión establecida entre lo que aparentemente es un
cliente en nuestra máquina local, conectado al servicio enlazado al puerto 22 en nuestra máquina
remota. De nuevo, trataremos de llamar a grep para buscar el servicio bien conocido asociado con
el puerto 22.

[elvis@station elvis]$ grep 22 /etc/services


ssh 22/tcp # SSH Remote Login Protocol
ssh 22/udp # SSH Remote Login Protocol
imap3 220/tcp # Interactive Mail Access
imap3 220/udp # Protocol v3
...

Aparentemente, esta línea representa una conexión activa entre un cliente ssh en la máquina local
y un demonio sshd en una máquina con una dirección IP de172.16.62.8.

Ejercicios en línea Lab Exercise Objetivo: Familiarizarse con la configuración y actividad TCP/IP.
Estimated Time: 10 mins.

Especificaciones

1. Crear el archivo ~/lab11.1/ipaddr que contenga su dirección IP de máquina como lo reporta


el comando hostname como su única palabra.

405
2. Crear el archivo ~/lab11.1/listening_ports que contenga una lista de todos los puertos
menores que 1024 en su máquina actual, abiertos en el estado de escucha, un puerto por
línea.

Deliverables A title Question 1

1. El archivo ~/lab11.1/ipaddr que contiene su dirección IP actual de la máquina (como lo


reportó el comando hostname) como su única palabra.
2. El archivo ~/lab11.1/listening_ports que incluye un listado de todos los puertos menores de
1024 en su máquina actual, abiertos en el estado de escucha, un puerto por línea.

406
Impresión Linux

Conceptos clave

• Linux de Red Hat Enterprise utiliza el sistema de impresión CUPS para administrar
impresoras.
• El sistema de impresión CUPS está diseñado en torno al concepto de cola de impresión, el
cual combina un directorio de almacenamiento temporal, un filtro y un dispositivo de
impresión.
• Los comandos gnome-print-manager y lpstat pueden utilizarse para navegar colas de
impresión disponibles.
• Los comandos lpr, lpq y lprm se utilizan para someter ("solicitar") trabajos de impresión,
averiguar por trabajos importantes y quitar trabajos de impresión pendientes,
respectivamente. Todos examinarán la variable de entorno PRINTER para determinar la
cola de impresión por defecto.
• Los comandos lp y cancel se comportan de un modo similar a los comandos lpr ylprm.
• Muchas aplicaciones imprimen por entubamiento a stdin de una línea de comando
personalizable lpr.

Discussion

Introducción a CUPS

Linux de Red Hat Enterprise utiliza el Sistema de Impresión Común de Unix (CUPS) para
administrar impresoras. En lugar de interactuar con la impresora directamente, los usuarios
someten las solicitudes de impresión a las colas de impresión que son manejadas por el demonio
cupsd. Las solicitudes de impresión pendientes en una cola de impresión se conocen como
trabajos de impresión. Una vez se ha sometido el trabajo a la cola, los usuarios pueden retornar
rápidamente a cualquiera de las tareas que estaban haciendo. Si la impresora está ocupada con
otro documento o no tiene papel, o no está disponible en la red, el demonio cupsd controlará la
situación y enviará (o reenviará) el trabajo de impresión a la impresora cuando quede disponible.

El demonio cupsd utiliza el Protocolo de Impresión de Internet (IPP), el cual es una extensión
directa del protocolo HTTP, diseñado para permitir administración de cola de impresión, a la
manera de un sistema operativo independiente. Como resultado, la administración de CUPS tiene
mucho en común con la administración del servidor de red.

La siguiente gráfica identifica los elementos que participan en la impresión Linux; dichos elementos
se tratan en detalle más adelante.

Figure 1. Infraestructura de impresión Linux

407
Colas de impresión

Una cola de impresión es una combinación de los siguientes elementos.

• Un directorio de almacenamiento temporal donde se pueden almacenar los trabajos


pendientes.
• Una serie de filtros que transforman archivos de entrada en formatos apropiados para
cualquier dispositivo secundario conectado a la cola.
• Un dispositivo secundario, tal como una impresora conectada localmente o una cola de
impresión definida en una máquina remota. A continuación, se listan algunos de los
dispositivos secundarios admitidos por CUPS.
o impresoras de puerto paralelo conectadas localmente
o impresoras localmente conectadas através de un USB
o impresoras de red utilizando la interfaz LPD
o impresoras de red utilizando interfaz de JetDirect
o Colas de impresión IPP en máquinas remotas
o Colas de impresión LPD en máquinas remotas
o Servicios de impresión de red (Microsoft) SMB

La tarea fundamental que enfrenta el administrador al configurar Linux de Red Hat Enterprise para
que utilice una impresora particular o un servicio de red de impresión, es definir y nombrar
correctamente la cola de impresión para el recurso. Esto generalmente implica identificar cuáles de
los dispositivos secundarios anteriores se utilizan para acceder al dispositivo, elegir un filtro
apropiado para el dispositivo, llamar y activar la cola de impresión.

En este curso asumiremos que ya se ha hecho todo el trabajo difícil y que las colas de impresión
disponibles para su sistema ya se han definido.

408
Navegar las colas de impresión disponibles: gnome-print-manager y lpstat

Las colas de impresión están disponibles ya sea porque se han definido en la máquina local o
descubierto mediante la habilidad de CUPS para navegar la red local para impresoras publicadas.

En el entorno gráfico, gnome-print-manager puede utilizarse para identificar las colas de


impresión y controlar los trabajos de impresión sometidos a ellas. El control de impresión puede
iniciarse ya sea desde la línea de comandos o al elegir Herramientas del Sistema: Administrador de
Impresión desde el menú de aplicaciones GNOME.

Figure 1. El administrador de impresión GNOME

Cuando el entorno gráfico no está disponible, o incluso cuando lo está, el comando lpstat se puede
utilizar para escanear las colas de impresión disponibles desde la línea de comando. La siguiente
línea de comandos sirve para clasificar el comando lpstat.

Table 1. Opciones para el comando lpstat

Opción Efecto
-a Lista estado de aceptación de todas las colas de impresión.
-o Lista todos los trabajos importantes
-p Lista todas las colas de impresión y si están inactivas u ocupadas.
-s Lista el estatus de la impresora, incluída la cola por defecto y el dispositivo secundario
asociado con cada cola.

Para mayor información, vea la página de manual lpstat(1). A continuación, elvis descubre que su
cola de impresión de sistema por defecto, se llama simplemente "printer" y que tiene varias colas
de impresión disponibles, que parecen referirse a la cola de impresión IPP en un servidor de
impresora local.

[elvis@station elvis]$ lpstat -s


system default destination: printer
device for acct2_ire: ipp://printsrv.example.com:631/printers/acct2_ire
device for acct_ire: ipp://printsrv.example.com:631/printers/acct_ire
device for ba: ipp://printsrv.example.com:631/printers/ba
device for checks: ipp://printsrv.example.com:631/printers/checks
device for coms: ipp://printsrv.example.com:631/printers/coms
device for exec: ipp://printsrv.example.com:631/printers/exec
...

Someter y administrar trabajos: lpr, lpqy lprm

CUPS utiliza los comandos de UNIX tradicionales para interactuar con el sistema de impresión: lpr
somete archivos e información que van a imprimirse, lpq examina el estatus de trabajos de
impresión importantes y lprm quita trabajos de impresión pendientes en la cola. Todos los tres
comandos utilizan las siguientes técnicas para especificar qué cola de impresión utilizar en el orden
especificado.

1. Si se halla la opción -P, su argumento se utiliza para especificar la cola de impresión.


2. Si no se utiliza -P para definir la cola de impresión por defecto, entonces se utiliza la
variable de entorno PRINTER, si existe.

409
3. De otra manera, se utiliza el sistema de cola de impresión por defecto.

Someter trabajos con lpr

Los trabajos pueden someterse con el comando lpr. Todos los argumentos son interpretados como
archivos para someter. Si no se especifican argumentos en su lugar se lee la entrada estándar. Las
siguientes opciones sirven para clasificar el comando lpr.

Table 1. Opciones del comando lpr

Opción Efecto
-P Uso de la cola de impresión impresora.
impresora
-# Imprime # copias
-p Representa archivos de texto con un encabezado que contiene el nombre del
archivo, nombre del trabajo y el sello de fecha.
-r Borra los archivos de impresión nombrados después de imprimir.

A manera de ejemplo, a continuación, blondie utiliza el comando lpr para imprimir el archivo
README mediante la cola de impresiónsales.

[blondie@station blondie]$ lpr -P sales README

Control de trabajos con lpq

El comando lpq lista los trabajos pendientes en una cola. En el siguiente ejemplo, blondie somete
la salida del comando df para la impresora legal y luego examina el contenido de la cola.

[blondie@station blondie]$ df | lpr -P legal


[blondie@station blondie]$ lpq -P legal
legal is ready and printing
Rank Owner Job File(s) Total Size
active elvis 1 services 20480 bytes
1st blondie 5 (stdin) 1024 bytes

Eliminación de trabajos con lprm

Blondie sospecha que algo anda mal con la impresora legal y decide iniciar utilizando la impresora
sales como su impresora por defecto. Primero configura la variable de entorno PRINTER para
reflejar sus nuevas preferencias, luego utiliza el comando lprm para quitar su trabajo de la cola
legal.

410
[blondie@station blondie]$ export PRINTER=sales
[blondie@station blondie]$ lpq
sales is ready
no entries
[blondie@station blondie]$ lpq -P legal
legal is ready and printing
Rank Owner Job File(s) Total Size
active elvis 1 services 20480 bytes
1st blondie 5 (stdin) 1024 bytes
[blondie@station blondie]$ lprm 5
[blondie@station blondie]$ lpq -P legal
legal is ready and printing
Rank Owner Job File(s) Total Size
active bowe 1 services 20480 bytes
[blondie@station blondie]$ df | lpr

Observe que en el primer comando lpq y el último comando lpr, la variable de entorno PRINTER
implícitamente especificó la cola de impresión sales.

Los comandos de Front End alternativos: lp y cancel

En Unix, en los días precedentes a CUPS, se implementaron dos ejecuciones paralelas de la


infraestructura de impresión. La primera utilizó los tres comandos presentados anteriormente es
decir lpr, lpq, y lprm. La segunda utilizó lp, lpstat y cancel para tareas análogas.

Ya hemos visto que lpstat es compatible y es la herramienta preferida para descubrir colas de
impresión. Los comandos lp y cancel también están disponibles como variaciones leves de los
comandos lpr y lprm. Para mayor información, consulte la página de manual lp(1).

Impresión dentro de aplicaciones Linux

Con frecuencia las aplicaciones Linux suelen imprimir entubando la información directamente a la
entrada estándar del comando lpr. Por lo general, las aplicaciones permiten a los usuarios
personalizar la línea de comando lpr, para que, por ejemplo, se pueda especificar una cola de
impresión diferente a la cola de impresión por defecto.

En la siguiente toma de pantalla del diálogo de impresión de la aplicación Evolution, el campo


Printer inicialmente sólo contenía un lpr, pero blondie añadió la opción -P sales para que la salida
de evolution vaya a la impresora sales.

Figure 1. Diálogo de impresión de Evolution

La interfaz de red CUPS

Por último, seríamos negligentes si abandonáramos el tema de CUPS sin mencionar la interfaz de
red nativa que el demonio cupsd brinda. Como se mencionó, la mayoría de los clientes interactúan
con el demonio cupsd mediante el protocolo IPP, el cual es una extensión del protocolo HTTP.
Debido a su parecido, el demonio cupsd se comporta en muchas formas como el demonio de web,
incluyendo el servidor de las páginas de administración de estilo CGI.

411
Con el fin de ver las páginas de administración de CUPS, apunte un navegador de red hacia la
dirección de la máquina local, pero sobreescriba el puerto 80 por defecto con el puerto de servicio
bien conocido de los demonios de CUPS, 631.

http://localhost:631

El demonio cupsd retornará con una"página de inicio" de CUPS desde donde pueden verse las
impresoras y los trabajos de impresión y existe dsiponible una copiosa documentación en línea.

Figure 1. La página de inicio de administración de CUPS

Ejercicios en línea

Lab Exercise

Objetivo: Administrar trabajos de impresión efectivamente.

Estimated Time: 10 mins.

Configuración

Su estación debería configurarse con una cola de impresión llamada rha_faux. Esta cola de
impresión se anexa a la impresora virtual en ejecución en el servidor del aula de clase. Usted
puede ver la primera página de cualquier trabajo de impresión enviado a la impresora en el
classroom server.

Si el comando lpstat -s no menciona una cola de impresión llamada rha_faux o si no puede


acceder a la página web del servidor del aula de clase, consúltele a su instructor.

Especificaciones

1. Imprima el archivo /etc/services mediante la cola de impresión rha_faux y observe su


salida. http://rha-server/cgi-bin/rha/printer.
2. Imprima el archivo /usr/share/backgrounds/tiles/floral.png mediante la cola de impresión
rha_faux y observe su salida. http://rha-server/cgi-bin/rha/printer.
3. Desde su navegador de red, imprima la página actual directamente a la cola de impresión
rha_faux.

Deliverables A title Question 1

1. Tres trabajos de impresión sometidos a la cola de impresión rha_faux.

412
Administración de archivos de impresión

Conceptos clave

• El formato de impresión primario en Linux es PostScript.


• gs y ggv ven con anticipación los documentos PostScript.
• enscript convierte archivo de texto en PostScript decorado.
• ps2pdf y pdf2ps convierten de PostScript a PDF y viceversa.
• mpage pueden reordenar las páginas individuales de un documento PostScript.

Discussion

PostScript

En Linux, la mayoría de las impresoras esperan recibir texto ASCII o gráficas mediante el formato
PostScript. A diferencia de la mayoría de los formatos gráficos, PostScript es un lenguaje de
guiones de gran alcance, el cual se ha adaptado a la tarea de traducir gráficas en la página
impresa. La sofisticación del lenguaje PostScript le permite realizar trabajos complejos, pero debe
utilizar un intérprete para entregar archivos PostScript como imágenes.

Muchas impresoras ejecutan intérpretes PostScript originales y se conocen como impresoras


PostScript. Cada vez que una impresora PostScript recibe un archivo de texto que comienza con
los caracteres %!PS, el resto del archivo se interpreta como un guión PostScript, en lugar
imprimirse como un texto ASCII directamente (observe la semejanza con el mecanismo de scripts
de Unix#!/bin/bash).

En Linux (y Unix) una aplicación llamada Ghostscript o simplemente gs ejecuta un intérprete


PostScript. La ejecución de un PostScript es una tarea importante y aunque las aplicaciones en
Linux pueden utilizarse para ver o manipular archivos PostScript casi todos utilizan Ghostscript
como el dispositivo secundario para realizar la traducción real de PostScript en formatos gráficos
más accesibles [1].

Entrega de gráficos PostScript con GhostScript

Cuando se invoca como el comando gs, el intérprete Ghostscript puede utilizarse para traducir
archivos PostScript directamente en la pantalla. Por ejemplo, en el siguiente diálogo, al navegador
de red mozilla se le pide imprimir la página web actual no a una cola de impresión, sino a un
archivo PostScript titulado output.ps.

Figure 1. Impresión a un archivo PostScript

Como lo ilustra el comando head, un archivo PostScript es un archivo de texto sencillo que
comienza con el "mágico" PostSript%!PS.

413
[elvis@station elvis]$ head output.ps
%!PS-Adobe-3.0
%%BoundingBox: 18 18 558 720
%%Creator: Mozilla PostScript module (Galeon/2003022516)
%%DocumentData: Clean8Bit
%%DocumentPaperSizes: Letter
...

La siguiente línea de comandos puede utilizarse para ver el archivo con el intérprete Ghostscript.

[elvis@station elvis]$ gs output.ps


GNU Ghostscript 7.05 (2002-04-22)
Copyright (C) 2002 artofcode LLC, Benicia, CA. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Loading NimbusRomNo9L-Regu font from /usr/share/fonts/default/Type1/n021003l.pfb...
2410668 1054394 1642520 347466 0 done.
Loading NimbusSanL-Regu font from /usr/share/fonts/default/Type1/n019003l.pfb...
2785628 1380272 1662616 358654 0 done.

...

Loading StandardSymL font from /usr/share/fonts/default/Type1/s050000l.pfb...


4371596 2780842 1722904 370909 0 done.
>>showpage, press <return> to continue<<

GS>
El intérprete gs devuelve muchas líneas de tipos de fuente que carga, pero al final traduce la
imagen en una ventana X por separado. En la línea de comandos, el usuario es abandonado en un
intérprete de comandos interactivo Ghostscript GS> . Si el archivo PostScript contiene páginas
múltiples, un simple ENTER en el intérprete de comandos Ghostscript visualizará la próxima
página. Para aquellos que hablen PostScript, el intérprete puede utilizarse para entregar gráficas
de modo interactivo. Para aquellos que tengan menos conocimientos, un simple quit (o
CONTROL-D) hará salir al intérprete gs.

GS>quit
[elvis@station elvis]$

Traducción de PostScript a formatos alternos

Por defecto, el intérprete gs traduce los archivos PostScript a una ventana dentro del entorno X.
Sin embargo, como lo ilusta la salida de los dispositivos disponibles del comando gs --help, el
comando ejecutable gs puede representar un gran número de formatos gráficos.

414
[elvis@station elvis]$ gs --help
GNU Ghostscript 7.05 (2002-04-22)
Copyright (C) 2002 artofcode LLC, Benicia, CA. All rights reserved.
Usage: gs [switches] [file1.ps file2.ps ...]
Most frequently used switches: (you can use # in place of =)
-dNOPAUSE no pause after page | -q `quiet', fewer messages
-g<width>x<height> page size in pixels | -r<res> pixels/inch resolution
-sDEVICE=<devname> select device | -dBATCH exit after last file
-sOutputFile=<file> select output file: - for stdout, |command for pipe,
embed %d or %ld for page #
Input formats: PostScript PostScriptLevel1 PostScriptLevel2 PDF
Available devices:
x11 x11alpha x11cmyk x11gray2 x11gray4 x11mono bmpmono bmpgray bmpsep1
bmpsep8 bmp16 bmp256 bmp16m bmp32b deskjet djet500 laserjet ljetplus
ljet2p ljet3 ljet3d ljet4 ljet4d lj5mono lj5gray cdeskjet cdjcolor
cdjmono cdj550 pj pjxl pjxl300 uniprint ijs omni bj10e bj200 bjc600
bjc800 faxg3 faxg32d faxg4 pcxmono pcxgray pcx16 pcx256 pcx24b pcxcmyk
pbm pbmraw pgm pgmraw pgnm pgnmraw pnm pnmraw ppm ppmraw pkm pkmraw pksm
pksmraw tiffcrle tiffg3 tiffg32d tiffg4 tifflzw tiffpack tiff12nc
tiff24nc psmono psgray psrgb bit bitrgb bitcmyk pngmono pnggray png16
png256 png16m jpeg jpeggray pdfwrite pswrite epswrite pxlmono pxlcolor
bbox dmprt cdj880 ap3250 appledmp atx23 atx24 atx38 bmpa16 bmpa16m
bmpa256 bmpa32b bmpamono bmpasep1 bmpasep8 ccr cdj1600 cdj500 cdj670
cdj850 cdj890 cdj970 cfax cgm24 cgm8 cgmmono cljet5pr coslw2p coslwxl
cp50 declj250 dfaxlow dfaxhigh djet500c dl2100 dnj650c eps9high eps9mid
epson epsonc escp fs600 hl1250 hl7x0 ibmpro imagen inferno iwhi iwlo iwlq
jetp3852 la50 la70 la75 la75plus lbp8 lj250 lj3100sw lj4dith ln03 lp2563
lp8000 lq850 lxm5700m m8510 mgr4 mgr8 mgrgray2 mgrgray4 mgrgray8 mgrmono
miff24 necp6 oce9050 oki182 okiibm paintjet photoex pjetxl plan9bm sgirgb
r4081 sj48 st800 stcolor sunhmono t4693d2 t4693d4 t4693d8 tek4696 xes
x11cmyk2 x11cmyk4 x11cmyk8 x11rg16x x11rg32x ljet4pjl lj4dithp dj505j
picty180 pr201 pr150 pr1000 pr1000_4 jj100 bj10v bj10vh mag16 mag256
mj700v2c mj500c mj6000c mj8000c fmpr fmlbp ml600 lbp310 lbp320 lips2p
bjc880j lips4 lips4v escpage lp2000 npdl md50Mono md50Eco md1xMono DJ630
DJ6xx DJ6xxP DJ8xx DJ9xx DJ9xxVIP AP21xx pcl3 md2k md5k stp lxm3200
lx5000 lex7000 lex5700 lex3200 lex2050 gdi epl5800 epl2050 epl2050p
alc8500 alc2000 cups cljet5 cljet5c nullpage
...

Mientras algunos de estos "dispositivos" de salida tales como jpeg y png256, se refieren a los
formatos estándar para archivos gráficos, muchos de los dispositivos se refieren a formatos
gráficos de impresoras sin PostScript o fax. La utilidad gs puede utilizarse en modo de lote para
convertir un gran número de archivos PostScript en otro formato o filtrar un documento para
impresión en una impresora sin PostScript.

El siguiente cuadro resume algunos de las opciones de Ghostscripts más utilizadas.

Table 1. Opciones comunes para Ghostscript

Opción Efecto
-dNOPAUSE No hace pausa y espera un RETURN después de traducir cada página.
-dBATCH Sale automáticamente después de traducir la última página.
-q Opera "calmadamente" (no presenta un mensaje por cada página
traducida).

415
-sDEVICE=devname Utiliza el formato de salida devname
- Almacena la salida en el archivo filename. Si %d se incluye en el nombre
sOutputFile=filename de archivo, se remplazará con el número de página del documento multi-
página.
-rresolución Utiliza una resolución de resolución DPI (puntos por pulgada).

A manera de ejemplo, la siguiente línea de comandos convertiría el documento PostScript


output.ps en imágenes múltiples PNG llamadas output.pagenum.PNG.

[elvis@station elvis]$ gs -dNOPAUSE -dBATCH -q -sDEVICE=png256


-sOutputFile=outp
ut.%d.png output.ps
[elvis@station elvis]$ file output.*
output.1.png: PNG image data, 612 x 792, 8-bit colormap, non-interlaced
output.2.png: PNG image data, 612 x 792, 8-bit colormap, non-interlaced
output.ps: PostScript document text conforming at level 3.0

Ver gráficas PostScript con Ghostview

A pesar de su poder, el comando gs de la interfaz de usuario aún se puede mejorar. En lugar de


utilizar directamente gs muchos usuarios prefieren utilizar la aplicación Ghostview de GNOME,
ggv, la cual ofrece un dispositivo frontal para Ghostscript más fácil de usar.

[elvis@station elvis]$ ggv output.ps

Figure 1. Visor PostScript del Ghostview de GNOME

La aplicación Ghostview de GNOME ofrece principalmente las siguientes características.

1. Escala dinámica: La imagen puede hacerse a escala para ajustar la anchura y altura de la
ventana o un porcentaje arbitrario.
2. Paginación: Al utilizar un panel lateral se puede navegar fácilmente un documento multi-
páginas y seleccionar páginas individuales para extraer dentro de un archivo PostScript
independiente o imprimir mediante el menú File como se ilustra a continuación.

Figure 2. Extracción de páginas mediante el visor PostScript Ghoscript de GNOME

En teoría, la aplicación Ghostview también sirve para ver archivos PDF. En la práctica, ggv
ocasionalmente tiene problemas interpretando documentos PDF. Pronto veremos una aplicación
más estable para visualizar los PDF. Algunos documentos PostScript multi-páginas pueden
también confundir a ggv. En casos en que ggv tiene problemas para traducir un documento
PostScript, el traductor de PostScript gs puede utilizarse directamente.

Ver documentos PDF con xpdf

La aplicación xpdf es un simple visor de documentos PDF que sirve para ver, imprimir o convertir
documentos PDF en PostScript.

Figure 1. El visualizador de documentos PDF xpdf

416
Las flechas en la esquina inferior izquierda permiten al documento navegar una página o 10
páginas al mismo tiempo. El botón del icono de impresora abre el siguiente diálogo, el cual permite
al usuario especificar una línea de comando lpr o un destino de archivo PostScript.

Figure 2. Impresión desde xpdf

Otras alternativas para ver documentos PDF incluyen los comandos gs y ggv.

Conversión de documentos PDF

La utilidad gs puede utilizarse para convertir documentos PDF en cualquiera de los formatos de
salida listados anteriormente. Puesto que la sintaxis del comando gs puede ser tan engorrosa,
algunas utilidades frontales de línea de comando más sencillas están disponibles para convertir
PostScript en PDF: ps2pdf y amigos.

La sintaxis del comando ps2pdf es trivial, donde el primer argumento es la salida del nombre de
archivo PostScript (o un “-” para implicar la entrada estándar) y el segundo argumento es la salida
del nombre de archivo de salida PDF (o un “-” para implicar la salida estándar).

A manera de ejemplo rápido, elvis ahora utiliza el comando ps2pdf para convertir su archivo
output.ps en formato PDF, el cual es de calidad comparable, pero mucho más compacto.

[elvis@station elvis]$ ps2pdf output.ps output.pdf


[elvis@station elvis]$ file output.*
output.1.png: PNG image data, 612 x 792, 8-bit colormap, non-interlaced
output.2.png: PNG image data, 612 x 792, 8-bit colormap, non-interlaced
output.pdf: PDF document, version 1.2
output.ps: PostScript document text conforming at level 3.0
[elvis@station elvis]$ ls -s output.p*
80 output.pdf 1400 output.ps

Figure 1. Visor PostScript del Ghostview de GNOME

La aplicación Ghostview de GNOME ofrece principalmente las siguientes características.

1. Escala dinámica: La imagen puede hacerse a escala para ajustar la anchura y altura de la
ventana o un porcentaje arbitrario.
2. Paginación: Al utilizar un panel lateral se puede navegar fácilmente un documento multi-
páginas y seleccionar páginas individuales para extraer dentro de un archivo PostScript
independiente o imprimir mediante el menú File como se ilustra a continuación.

Figure 2. Extracción de páginas mediante el visor PostScript Ghoscript de GNOME

En teoría, la aplicación Ghostview también sirve para ver archivos PDF. En la práctica, ggv
ocasionalmente tiene problemas interpretando documentos PDF. Pronto veremos una aplicación
más estable para visualizar los PDF. Algunos documentos PostScript multi-páginas pueden
también confundir a ggv. En casos en que ggv tiene problemas para traducir un documento
PostScript, el traductor de PostScript gs puede utilizarse directamente.

417
Ver documentos PDF con xpdf

La aplicación xpdf es un simple visor de documentos PDF que sirve para ver, imprimir o convertir
documentos PDF en PostScript.

Figure 1. El visualizador de documentos PDF xpdf

Las flechas en la esquina inferior izquierda permiten al documento navegar una página o 10
páginas al mismo tiempo. El botón del icono de impresora abre el siguiente diálogo, el cual permite
al usuario especificar una línea de comando lpr o un destino de archivo PostScript.

Figure 2. Impresión desde xpdf

Otras alternativas para ver documentos PDF incluyen los comandos gs y ggv.

Conversión de documentos PDF

La utilidad gs puede utilizarse para convertir documentos PDF en cualquiera de los formatos de
salida listados anteriormente. Puesto que la sintaxis del comando gs puede ser tan engorrosa,
algunas utilidades frontales de línea de comando más sencillas están disponibles para convertir
PostScript en PDF: ps2pdf y amigos.

La sintaxis del comando ps2pdf es trivial, donde el primer argumento es la salida del nombre de
archivo PostScript (o un “-” para implicar la entrada estándar) y el segundo argumento es la salida
del nombre de archivo de salida PDF (o un “-” para implicar la salida estándar).

A manera de ejemplo rápido, elvis ahora utiliza el comando ps2pdf para convertir su archivo
output.ps en formato PDF, el cual es de calidad comparable, pero mucho más compacto.

[elvis@station elvis]$ enscript -r2 -E -G -o malloc.ps


/usr/include/malloc.h
[ 2 pages * 1 copy ] left in malloc.ps
[elvis@station elvis]$ ggv malloc.ps

El comando pdf2ps también existe para realizar la operación inversa.

Representación del texto para impresión con enscript

La utilidad enscript convierte archivos de texto en PostScript, a menudo representando el texto


con sintaxis resaltada (pretty printing), un encabezado o impresión de múltiples páginas de texto
por página impresa.

De un modo un poco torpe, el comando enscript envía un archivo de texto directamente al


comando predeterminado lpr, dando como resultado que los archivos enscript se impriman
inmediatamente. Puede utilizar la opción -o para especificar una salida del archivo PostScript en su
lugar.

Algunas de las opciones más comunes se encuentran en el siguiente cuadro.

Table 1. Opciones más comunes para enscript

418
Opción Efecto
-o filename Generar salida del archivo filename.
-2, Formatear texto en 2 (o num) columnas.
--columns=num
-a páginas Solamente imprime páginas páginas. páginas pueden ser de la forma
comienzo-fin, la palabra impar o par.
-b encabezado Utiliza el encabezado de texto como un encabezado de página. Un formato
elaborado es provisto para especificar nombre de archivo, número de página,
etc.
-d impresora Envia salida a la cola de impresiónimpresora.
-E [lang] Representa el texto con sintaxis resaltada apropiada para el lenguaje de
programación lang. Utiliza --help-pretty-print para listar los idiomas
soportados.
-G Representa páginas con un encabezado elegante.
-r Rota la página 90 grados.
-W lang Genera salida en idioma lang, que puede ser de PostScript, html,
superposición o rtf.

Existen muchas más opciones. Para mayor información, consulte la página de manual enscript(1).
A manera de ejemplo, la siguiente línea de comandos traduciría el archivo de encabezado C
malloc.h como PostScript con 2 columnas por página, rotado y representado con un encabezado
elegante y una sintaxis resaltada.

[elvis@station elvis]$ enscript -r2 -E -G -o malloc.ps /usr/include/malloc.h


[ 2 pages * 1 copy ] left in malloc.ps
[elvis@station elvis]$ ggv malloc.ps

Figure 1. Archivo de texto representado en PostScript con enscript

Reordenamiento de PostScript con mpage

El comando mpage puede utilizarse para extraer páginas desde la mitad de un documento
PostScript multi-páginas o reformatear el documento a imprimir con múltiples páginas por hoja.

El mpage acepta PostScript o texto como entrada. El texto se traduciría en PostScript antes de
administrar. Los argumentos se consideran archivos de entrada con la salida dirigida a la salida
estándar.

Table 1. Opciones de mpage

Opción Efecto
-o filename Generar salida del archivo filename.
-1, -2, -4, -8 Imprimir un número especificado de páginas por hoja impresa (4 por
defecto).
-j primero[-último] Sólo imprime un rango especificado de páginas incluyendo sólo los
[%intervalo] intervalo de páginas, si se especifican.
-l Cambia el modo de formato horizontal a vertical.
-o Cambia a imprimir borde alrededor de cada página (por defecto está
activo).
-P [impresora] Envía salida PostScript a la cola de impresión impresora.
-G Representa páginas con un encabezado elegante.

419
-r Rota la página 90 grados.
-G Representa páginas con un encabezado elegante.
-W lang Genera salida en idioma lang, que puede ser de PostScript, html,
superposición o rtf.

La siguiente línea convierte el archivo PDF RHEL3FamOverWPPdf.pdf en un archivo PostScript e


imprime cuatro páginas por hoja.

[elvis@station elvis]$ pdf2ps RHEL3FamOverWPPdf.pdf - | mpage > rhel3.ps


[elvis@station elvis]$ ggv rhel3.ps

Figure 1. Un documento PDF convertido en PostScript (4 Up)

Ejercicios en línea Lab Exercise Objetivo: Practicar la salida para impresión. Tiempo estimado:
20 minutos.

Especificaciones

1. Utilice el comando enscript para generar un documento PostScript del archivo


/usr/share/doc/bash-*/loadables/getconf.c nombre getconf.ps con dos páginas por hoja
impresa. Opcionalmente, haga que el comando enscript "pretty print" el texto (agregando
sintaxis resaltada).

420
2. Utilice el comando mpage para extraer las páginas 8 y 9 del archivo getconf.ps creado
anteriormente, almacénelas en un nuevo documento llamado getconf89.ps.

(Por defecto el comando mpage imprimirá 4 hojas por páginas de salida, confundiendo el
conteo de páginas. Incluya la opción apropiada para que sólo una página de entrada sea
impresa por página de salida).

3. Utilice el comando ps2pdf para convertir el archivo getconf89.ps en un documento PDF


titulado getconf89.pdf. Compare los tamaños de los dos documentos.
4. Cree un script de shell corto llamado ~/bin/ps2jpeg, el cual al ser llamado con un sólo
argumento especificando un archivo PostScript, utiliza el comando gs para convertir el
archivo en un documento JPEG llamado output.jpg.

Deliverables A title Question 1

No hay elemento para calificar este ejercicio.

1. Un documento de múltiples páginas PostScript getconf.ps que contiene el texto del archivo
/usr/share/doc/bash-*/loadables/getconf.c, impreso en 2 páginas por página de salida.
2. Un documento PostScript de dos páginas getconf89.ps que contiene las páginas 8 y 9
extraídas del documento getconf.ps.
3. El documento PDFgetconf89.pdf, el cual es el contenido del documento PostScript
getconf89.ps convertido en formato PDF.

Un script titulado ~/bin/ps2jpeg que cuando se invoca con un documento PostScript como
su único argumento, convertirá el documento en una imagen JPEG llamada output.jpg.

421
Sinopsis del correo electrónico

Conceptos clave

• La administración del correo electrónico implica dos agentes. Un agente de usuario de


correo (MUA, en inglés Mail User Agent), el cual se utiliza para presentar correo recién
enviado a un usuario y escribir nuevas respuestas al usuario y un agente de transporte de
correo (MTA, en inglés Mail Transport Agent), el cual administra la tarea de segundo plano
de intercambiar correo electrónico con otras máquinas remotas.
• Dependiendo de los detalles de acceso a Internet de un computador, el trabajo de
recepción de correo electrónico se puede delegar a un servidor de buzón, lo que permitiría
luego que el usuario tuviera acceso a su correo electrónico enviado mediante los
protocolos POP o IMAP.
• De nuevo dependiendo de los detalles de acceso a Internet de un computador, la tarea de
entregar correo electrónico se puede delegar a un servidor remoto saliente SMTP.
• Por lo general, el correo local entregado pero no leído se almacena temporalmente en el
archivo /var/spool/mail/$USER, en donde USER es el nombre de usuario del destinatario.
• Uno de los MUA más sencillos es el comando mail.

Discussion

Uso del correo electrónico

Es discutible que el servicio más popular ofrecido por Internet es el correo electrónico. El correo
electrónico es un concepto sencillo: Alicia escribe un archivo de texto y especifica enviarlo a Bob.
Cuando Bob revisa su correo, el archivo de texto estará esperando por él, etiquetado como enviado
por Alice. Sin embargo, en la práctica, el sistema de envío de correo electrónico debe ofrecer
soluciones a algunos problemas bastante complicados.

El software que Alice y Bob utilizan debe resolver los siguientes problemas.

1. La aplicación de correo electrónico de Alice de alguna manera determina cuál es el


computador de Bob.
2. Una vez determinada, la aplicación de Alice debe conectarse a la máquina de Bob y
transferir el mensaje. Si la máquina de Bob no puede ser contactada, la aplicación de Alice
debe almacenar temporalmente el mensaje pendiente y tener alguna estrategia para tratar
de contactar la máquina de Bob más tarde.
3. Como destinatario, la aplicación de correo electrónico de Bob debe tener alta capacidad,
por lo tanto cada vez que alguien (Alicia u otra persona) quiera enviarle un mensaje de
correo electrónico a Bob, su aplicación estará disponible para recibirlo.

En algunos casos, el recipiente de correo utiliza una máquina que no tiene una conexión
permanente de Internet o está detrás de un cortafuegos, lo que luego complicará las cosas. En
esta lección, trataremos varios procedimientos que ofrecen soluciones a estos problemas.

La solución fácil

La solución más sencilla es la apropiada para los usuarios de computadores con conexiones
deinternet bien conocidas y permanentes. En el momento en que muchos protocolos definían cómo
enviar correo electrónico, ésta fue la solución estándar. Dicha solución implica dos aplicaciones
separadas cuyos roles se identifican por TLA (acrónimos de tres letras). La primera aplicación se

422
conoce como MTA Agente de Transporte de Correo y la segunda se conoce como MUA, o Agente
de correo de usuario.

Figure 1. Envío de correo electrónico en computadores con conexiones de intenet


permanentes y bien conocidas

El MTA (Agente de transporte de correo)

El MTA suele operar en el segundo plano, realizando el trabajo de una oficina postal. El MTA
recibe correo electrónico para ser envíado desde programas en la máquina local, determina desde
la dirección del destinatario la máquina apropiada que debe contactar e intenta conectarse a un
MTA complementario ejecutando en la máquina de destinatarios, quienes deben estar escuchando
el puerto 25. Si el remitente de MTA no puede contactar el receptor de MTA, el correo se almacena
temporalmente en la máquina del remitente y el MTA de remitente intenta de nuevo más tarde.

El MTA también se enlaza al puerto local 25, donde recibe conexiones de otros MTA. Cuando éste
recibe correo desde un MTA remoto destinado a un usuario en una máquina local, recibe el correo
y lo almacena en un directorio de almacenamiento temporal conocido como el buzón de entrada
del usuario. En Linux (y Unix), el buzón predeterminado del usuario es /var/spool/mail/username
para que el correo en espera del usuario elvis se instale en el archivo /var/spool/mail/elvis.

El MTA por defecto de Red Hat Enterprise Linux es un demonio llamado sendmail.

El MUA (Agente de usuario de correo)

El MUA es la aplicación en la que la mayoría de la gente piensa cuando se refiere a correo


electrónico. El MUA recupera correo enviado desde un almacenamiento temporal (buzón de
entrada) y lo presenta al usuario como "correo nuevo". El MUA permite a los usuarios escribir
respuestas o nuevos mensajes y pasar estos mensajes al MTA local para envío.

Red Hat Enterprise Linux se distribuye con una amplia selección de MUAs, varios de los cuales se
describirán en ésta y en la siguiente lección.

423
Servidores de buzón

Aunque la solución anterior es simple, requiere que primero, todos los usuarios estén recibiendo
correo electrónico en una máquina conectada constantemente a Internet y segundo, que la
máquina tenga un nombre de equipo bien conocido y accesible a otros. Muchos usuarios que por
ejemplo, utilizan una conexión de "marcado" o de "alta velocidad" desde un ISP (Proveedor de
Servicios Internet) o que estén utilizando máquinas detrás de un cortafuegos de una institución, no
están en esta situación. Otra solución se ha desarrollado para servir a la gente en este caso: los
servidores de buzón.

Figure 1. Servidores de buzón

En el diagrama anterior, asumimos que elvis está utilizando una conexión de Internet de "alta
velocidad" para la cual se ha suscrito a la compañía "ISP.Net". Cuando se conecta al Internet, su
máquina ISP le emite a su máquina una dirección IP, pero elvis no puede predecir la dirección IP
que recibirá. El nombre del equipo, al cual se le asignó el ISP a la dirección IP, es probablemente
poco atractivo por ejemplo, dhcp-191-93.isx.isp.net, por lo tanto si elvis garantizara la recepción de
la misma dirección IP cada vez, no desearía publicar su nombre de equipo como su dirección de
correo electrónico.

En su lugar, elvis aprovecha una "cuenta de correo electrónico" que le ofrece su ISP. Es muy
probable que su cuenta exista en una máquina Linux o Unix del ISP conectada permanentemente a
Internet y se le asigne un nombre de host como por ejemplo pop.isp.net. El ISP ha clasificado todo
el correo electrónico destinado a direcciones de forma user@isp.net para ser enviado al MTA de
esta máquina. Cuando el MTA ejecutándose en pop.isp.net recibe correo para elvis, lo almacena
en un directorio de almacenamiento temporal dedicado a elvis (muy probable en el archivo
sendmail./var/spool/mail/elvis) y el correo electrónico se considera como entregado.

Dado que la máquina de ISP pop.isp.net tiene una conexión de Internet permanente y bien
conocida, es mejor candidata para recibir correo electrónico que la máquina de elvis en casa.
Cuando elvis está en casa, aún necesita tener acceso a su correo electrónico que está en su buzón
de entrada en pop.isp.net. Este acceso suele estar provisto en forma de un servidor POP
(Protocolo de servidor de correo) o servidor de IMAP (Protocolo de Servicio de Correo por Internet).

Servidores POP

Los servidores POP realizan un servicio muy sencillo. Permiten a los usuarios acceder al directorio
de almacenamiento temporal de un sólo usuario y transfieren su contenido a su MUA local. Los

424
servidores POP suelen enlazarse al puerto 110 y requieren que cualquier cliente se autentique
mediante un par de nombres de usuario-contraseña. La mayoría de los MUAs modernos actúan
como clientes POP y pueden configurarse para recuperar correo de un servidor especificado.

Si un servidor de buzón ejecuta el servicio POP, suele implicar que el servidor de buzón no intenta
almacenar de modo permanente, sino temporalmente hasta que el usuario "lo baje "a su máquina
local.

Servidores IMAP

Los servidores IMAP suelen ofrecer a los clientes administración de buzones de manera más
sofisticada. Los usuarios IMAP pueden mantener varias carpetas en el servidor de buzón no sólo
su buzón de entrada individual. En general, un servidor IMAP implica que un correo electrónico del
usuario sea almacenado de forma permanente en el servidor de buzón y los usuarios
ocasionalmente se conecten con un MUA desde una máquina remota para "navegar" su correo.
Los servidores IMAP suelen encontrarse en entornos institucionales y corporativos. Los demonios
IMAP se enlazan al puerto 143.

Envío de correo

Puesto que la máquina de elvis mantiene una conexión de Internet casi continua, elvis aún desea
utilizar su MUA local para enviar correo. Si el MUA local no puede conectarse temporalmente a la
máquina del destinatario, el MUA almacenará el correo temporalmente de modo local y tratará de
enviarlo más tarde.

Configuración predeterminada de Red Hat Enterprise Linux

Por defecto, Red Hat Enterprise Linux está configurado de modo apropiado para esta situación. El
MTA local se inicia, pero no aceptará conexiones a través del puerto 25 (excepto desde la dirección
de bucle local, 127.0.0.1). Sirve simplemente para entregar correo electrónico saliente. Se asume
que los usuarios tienen acceso a su correo electrónico desde un servidor POP o IMAP.

La configuración predeterminada puede cambiarse, pero la configuración necesaria va más allá del
alcance de este curso.

Servidores de correo saliente

Para máquinas que sólo tienen conexiones a Internet transitorias, el intentar entregar correo
electrónico mediante el MTA local puede no ser apropiado. En su lugar, los usuarios de conexiones
de "marcado" y similares suelen utilizar lo que se conoce como un SMTP (Protocolo sencillo de
transferencia de correo) o servidor de correo saliente. Muchos ISP e instituciones ofrecen
servidores SMTP salientes, a menudo con nombres como smtp.isp.net.

Figure 1. Servidor de correo saliente

425
El MTA en el servidor SMTP desea aceptar correo de máquinas "locales", a pesar de que no es el
destinatario final para el correo electrónico. En su lugar, el servidor SMTP transmite el correo y lo
reenvía a su destino. Si se presenta algún problema, el almacenamiento temporal y el reenvío de
correo pendiente es ahora responsabilidad del servidor SMTP.

Muchos MUAs permiten a los usuarios especificar un equipo remoto para que actúe como el
servidor SMTP del usuario (contrario a reenviar correo al MTA local para envío). [1]

Entrega local

Todos los casos anteriores asumen que el usuario está enviando correo electrónico desde su
máquina a un destinatario en una máquina remota. Linux (y Unix) también permite a los usuarios
en una máquina local enviar correo electrónico entre sí, donde el correo electrónico se dirige
únicamente al nombre de usuario tal como blondie.

Para entrega local no se requiere ninguno de los servidores locales POP o SMTP porque el correo
electrónico se entrega al instante por el MTA local.

El MUA mail

Quizás el MUA más sencillo es un comando llamado simplemente mail. El comando mail data de
los primeros días de Unix y por lo tanto depende altamente del MTA local. El comando mail no
puede ser configurado para acceder al correo desde un servidor POP o IMAP, ni puede ser
configurado para utilizar un servidor SMTP para correo saliente. En su lugar, puede esperar correo
que sea enviado al directorio de almacenamiento temporal y pasa al MTA de correo local para
envío.

No obstante, en situaciones tales como envío de correo a usuarios locales, el comando mail puede
ser bastante eficaz.

Envío de correo electrónico con mail

426
El comando mail puede utilizarse para enviar correo a destinatarios especificados como
argumentos en la opción de la línea de comandos. El cuerpo del mensaje se lee desde la entrada
estándar (la cual puede leerse desde una tubería, un archivo redirigido o desde un teclado
directamente, en donde CONTROL-D ("EOF") se utiliza para indicar el fin del mensaje).

Las opciones de línea de comandos en el cuadro siguiente pueden utilizarse para especificar una
línea de asunto, destinatario a, "Cc:", etc.

Table 1. Opciones de línea de comandos para el comando mail

Opción Efecto
-v Modo verboso. Imprime la comunicación entre el comando mail y el MTA local (o
remoto).
-s Especifica una línea de asunto.
asunto
-c addrs Envía copia a las direcciones especificadas.
-b addrs Envía copias ciegas a direcciones especificadas.

A manera de ejemplo, a continuación, elvis envía por correo el contenido del archivo lyrics.txt a
blondie.

[elvis@station elvis]$ mail -s "here they are" blondie < lyrics.txt

Uso de mail para leer correo

El comando mail puede también utilizarse para leer la correspondencia de un almacenamiento


temporal de correo de usuario local. Sin embargo, la interfaz es primitiva y por lo general se utilizan
en su lugar otros MUAS. Para mayor información vaya a la página de correo mail. Actualmente, el
comando mail se considera como una forma rápida y eficaz de enviar correo.

En el siguiente ejemplo, blondie está utilizando el comando mail sin argumentos para ver el correo
en su buzón y luego borrar el mensaje y salir.

[blondie@station blondie]$ mail


Mail version 8.1 6/6/93. Type ? for help.
"/var/spool/mail/blondie": 1 message 1 new
>N 1 elvis@redhat.com Thu Nov 13 00:08 16/653 "here they are"
& RETURN
Message 1:
From elvis@station.example.com Thu Nov 13 00:08:45 2003
Date: Thu, 13 Nov 2003 00:08:44 -0500
From: elvis@station.example.com
To: blondie@station.example.com
Subject: here they are

100 bottles of ink on the wall.


100 bottles of ink.
Take one down,
Pass it around.

& d
& q

427
Ejemplos: Envío de correo

Una forma fácil y rápida de enviar archivo de texto a otro usuario es con mail

[julius@station julius]$ mail -s "here's the file" nero < somefile

También es fácil con mail enviar la salida de un comando a otro usuario.

[julius@station julius]$ find . -name "*.old" | mail -s "find output" nero

Protocolo sencillo de transporte de correo

Mediante un simple comando de correo con la opción verbosa, un usuario puede observar el
proceso por el que pasa sendmail para entregar un mensaje.

[julius@station julius]$ mail -v -s hello elvis@localhost


this is only a test
.
elvis@localhost... Connecting to [127.0.0.1] via relay...
220 station.example.com ESMTP Sendmail 8.12.8/8.12.8; Sat, 12 Apr 2003 13:08:30
-0400
>>> EHLO station.example.com
250-station.example.com Hello localhost.localdomain [127.0.0.1], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-DELIVERBY
250 HELP
>>> MAIL From:julius@station.example.com SIZE=60
250 2.1.0 julius@station.example.com... Sender ok
>>> RCPT To:elvis@station.example.com
>>> DATA
250 2.1.5 elvis@station.example.com... Recipient ok
354 Enter mail, end with "." on a line by itself
>>> .
250 2.0.0 h3CH8U3j002250 Message accepted for delivery
elvis@localhost... Sent (h3CH8U3j002250 Message accepted for delivery)
Closing connection to [127.0.0.1]
>>> QUIT
221 2.0.0 station.example.com closing connection

Ejercicios en línea Lab Exercise Objetivo: Enviar correo electrónico a usuarios locales.
Estimated Time: 10 mins.

Especificaciones

428
1. Utilice el comando mail para enviar por correo el contenido del archivo /proc/cpuinfo a sus
cuentas primaria y alterna (i.e, los usuarios nombredeusuario_a y nombredeusuario_b,
donde nombre de usuario es el nombre de su cuenta primaria.
2. Cree el archivo ~/you_have_mail que contiene una lista ordenada de todos los usuarios en
su sistema local que actualmente tienen correo en sus "buzones de entrada" (i.e. su
directorio de almacenamiento temporal entregado pero no leído aún). Debe incluir usuarios
de "sistema" en su lista y listar un usuario por línea.

Deliverables A title Question 1

1. Sus cuentas alternas primera y segunda tienen el contenido del archivo /proc/cpuinfo en su
depósito de correo entregado.
2. El archivo ~/you_have_mail debería contener una lista ordenada de como los usuarios
tienen correo en espera en su depósito de correo, (obviamente, sus nombres de cuentas
alternas primera y segunda deben incluirse en esta lista).

429
El MUA Evolution

Conceptos clave

• El MUA evolution ofrece un entorno sofisticado para la administración de correo


electrónico.
• La ventana de composición permite la composición de mensajes ya sea en texto sin
formato o en formato HTML e incluye un corrector ortográfico y soporte para anexos.
• El correo electrónico de entrada puede procesarse automáticamente mediante un filtrado
sofisticado.
• evolution permite enviar correo desde el depósito de correo local y servidores POP o
IMAP.

Discussion

Evolution

Quizás el MUA más sofisticado que se distribuye con Red Hat Enterprise Linux es evolution. El
agente de usuario de correo es apenas un componente del administrador de la información
personal de evolution. En esta sección, presentamos algunas de las características clave de la
aplicación evolution e identificamos cómo configurar evolution para recibir correo electrónico
desde varias fuentes y cómo enviar correo mediante el servidor local MTA o el servidor remoto
SMTP.

De hecho, Evolution es mucho más que un MUA. En la toma de pantalla siguiente verá que
también tiene herramientas para administrar contactos, calendario de eventos y listas de tareas. Lo
invitamos a experimentar con estos elementos cuando el tiempo se lo permita, pero la lección se
enfocará en el uso de evolution para envío y recepción de correo.

Navegar correo electrónico

Figure 1. El agente usuario de correo Evolution

Desde la pantalla principal, el correo se puede clasificar en una jerarquía de carpetas navegables
mediante el recuadro en la parte superior izquierda. En la parte superior derecha del recuadro, se
presenta un resumen de mensajes almacenados en la carpeta actual seleccionada. En el recuadro
de la parte inferior derecha se visualiza el contenido del actual mensaje.

Haciendo "click derecho" en un mensaje, un menú emergente ofrece una variedad de acciones,
tales como almacenar el mensaje como archivo de texto, responder a un mensaje o reenviar el
mensaje, "marcando" el mensaje con una bandera particular, "etiquetando" el mensaje en un color
determinado o identificando el mensaje como correo basura.

Un mensaje se puede archivar en otra carpeta con sólo arrastrar el mensaje al sitio de la carpeta
deseada en el panel a mano izquierda.

Al elegir "Agregar remitente a agenda de direcciones" se pueden crear nuevos contactos


fácilmente.

430
Por último, los filtros se pueden crear al tratar correos electrónicos con características similares al
actual mensaje.

Escribir correo electrónico

La ventana de composición se utiliza para crear un nuevo mensaje, responder o reenviar un


mensaje.

Figure 1. La ventana de composición de correo electrónico Evolution

Como se puede ver en la toma de pantalla, la ventana de composición proporciona un editor


sencillo para componer texto y anexar archivos. Si se desea, los mensajes se pueden formatear
como "HTML", para permitir a los usuarios incorporar enlaces, imágenes, y elementos sencillos
HTML en el mensaje.

Como es texto escrito, las palabras no identificadas por el corrector ortográfico son subrayadas y
con un click derecho, se sugieren remplazos que pueden buscarse en el diccionario o palabras que
pueden agregarse al diccionario personal del usuario.

Al seleccionar el menú Security, los usuarios pueden elegir entre firmar o encriptar su mensaje
mediante un protocolo de clave pública encriptada.

Uso de Filtros Evolution

La aplicación evolution soporta muchas características que permiten administrar grandes


cantidades de correo electrónico. Una de las herramientas primarias son los filtros de correo
electrónico.

Como se ve a continuación, los filtros se componen de una selección de criterios coincidentes que
serán aplicados al correo electrónico recibido. Si un mensaje coincide con los criterios entonces se
pueden poner en práctica una norma o un grupo de normas.

Figure 1. Filtros de correo electrónico Evolution

Los mensajes se pueden seleccionar al combinar algunos de estos criterios.

• El remitente o el destinatario del mensaje contiene un texto especificado.


• La línea de asunto u otra línea de encabezado especificada, contiene un texto
especificado.
• El cuerpo del mensaje contiene texto especificado.
• La fecha en la que se envió o se recibió el mensaje o después del tiempo especificado.
• El mensaje se ha etiquetado o marcado para "seguimiento".
• El mensaje parece haber sido enviado desde una lista de correo especificada.
• El mensaje coincide con una expresión regular especificada.
• El mensaje cuando es entubado a un comando de shell arbitrario, devuelve un valor de
retorno especificado.

Cuando coincide, el mensaje puede estar sujeto a alguna combinación de los siguientes destinos.

• El mensaje puede ser copiado o movido automáticamente a una carpeta especificada.


• Se puede asignar al mensaje una bandera particular, una puntuación o una etiqueta.
• Puede reproducirse una campana de terminal o algún sonido personalizado.

431
• El mensaje puede entubarse a una shell de comando arbitraria.

Configuración de cuentas en Evolution

Evolution permite a los usuarios administrar múltiples cuentas, donde una cuenta representa un
origen particular de correo electrónico, un destino particular para correo electrónico, una identidad
particular de un remitente entre otras opciones.

Las cuentas se pueden crear, borrar, habilitar, inhabilitar o modificar mediante el siguiente diálogo,
el cual se obtiene seleccionando Herramientas: Configuración... y eligiendo el "Panel de cuentas de
correo".

Figure 1. Administración de cuentas Evolution

Especificación de la fuente del correo electrónico

Evolution, permite recuperar correspondencia desde varias fuentes como se puede apreciar en el
siguiente diálogo.

Figure 1. Especificación de fuentes de las cuentas de correo de Evolution

Las primeras dos selecciones especifican que el correo se debería recuperar desde los servidores
POP o IMAP. Para cada uno, el diálogo permite especificar el nombre de servidor, el nombre de
cuenta y la contraseña. Si el servidor de POP o IMAP soporta codificación, el encapsulado SSL
puede especificarse. También se ofrecen otros esquemas de autenticación (diferentes a un par de
nombre de usuario-contraseña), si el servidor los soporta.

El resto de las opciones permiten a evolution sacar correo directamente del depósito de correo
MTA o compartir carpetas con otros MTA como por ejemplo, mutt, pine y elm.

Especificar una técnica de entrega de correo electrónico

Para cada cuentase pueden especificar una de dos técnicas de entrega.

Figure 1. Especificar una técnica de entrega de cuenta de correo electrónico de Evolution

Si se debe utilizar un host SMTP, debe especificarse el nombre del host. Además se pueden
establecer soporte para conexiones encriptadas o autenticación de usuario si la máquina SMTP es
compatible o lo requiere.

La otra alternativa es hacer que evolution entregue correo simplemente pasándolo al MTA local
("enviar correo"), en cuyo caso no hay ninguna otra configuración.

432
Aplicaciones de diagnósticos de red

Conceptos clave

• /sbin/ifconfig presenta la configuración IP local.


• ping confirma la conectividad de red de bajo nivel entre hosts.
• host hace solicitudes directas de DNS.
• El comando netstat -tuna lista los servicios actuales activos de red y conexiones.
• /sbin/traceroute puede diagnosticar problemas de enrutado.

Discussion

Configuración requerida para el protocolo de internet

El protocolo de Internet o más común el protocolo IP es el estándar adoptado para entregar


información entre máquinas conectadas por una red. Para utilizar el protocolo IP, una máquina
debe configurarse de la siguiente manera.

Aunque la configuración de un sistema con la información IP de configuración apropiada requiere


privilegios de root, este cuaderno demuestra la forma de determinar la configuración de red de una
máquina local e introduce utilidades que sirven para confirmar que la infraestructura de red de la
máquina esté funcionando adecuadamente.

Dirección IP

Linux (y Unix) representa los dispositivos de red conectados a una máquina (tales como una tarjeta
Ethernet, una tarjeta Token-Ring, un módem utilizado para conexiones de marcado, etc...) como
una interfaz de red. Antes de que una interfaz pueda utilizarse para enviar o recibir tráfico, debe
configurarse con una dirección IP que sirve como la identidad de la interfaz.

Portal predeterminado

La mecánica de un protocolo IP organiza máquinas en subredes o subnets en inglés. Todas las


máquinas en una subred pueden intercambiar información directamente. Las subredes IP están a
su vez ligadas a otras subredes por máquinas que actúan como routers. Un router tiene múltiples
interfaces de red, por lo general cada uno participa en una subred distinta. Con el fin de
comunicarse con un equipo en otra subred, los datos deben pasarse a un router, el cual (con la
ayuda de otros routers) encamina la información a la subred apropiada y desde allí al host
apropiado.

Para comunicarse con las máquinas fuera de la subred local, su máquina debe conocer la
identidad de un router cercano. El router utilizado para encaminar paquetes fuera de su subred
local se conoce como un portal predeterminado.

Nameserver

Otras máquinas en internet a su vez se identifican por una dirección IP. La gente suele pensar en
términos de nombres, por lo tanto el protocolo se ha desarrollado para asignar nombres a las
direcciones IP. El protocolo se llama Servicio de Nombres de Dominio o más conocido como DNS.

433
El protocolo DNS requiere que cada máquina tenga disponible uno o más servidores DNS
(comúnmente llamados servidores de nombre), los cuales pueden servir tanto de base de datos
para asignar un nombre a direcciones locales IP como también de punto de partida para determinar
direcciones IP para nombres de dominio de los cuales el servidor no tiene conocimento directo.

Determinar su(s) dirección(es) IP: /sbin/ifconfig

En una lección anterior presentamos el comando hostname -i, el cual muestra la dirección IP en
su equipo local. En realidad una "máquina" no tiene una dirección IP, las interfaces de red sí. Esta
lección tratará el tema de direcciones IP de interfaces de red en mayor detalle.

En Linux (y Unix), cada dispositivo de red se representa como una interfaz de red, (por una vez,
¡encontramos algo que no es un archivo!). Linux nombra interfaces de acuerdo con el tipo de
dispositivo que representa. El siguiente cuadro lista algunos de los nombres más utilizados en
Linux.

Table 1. Interfaces de red Linux

Interfaz Dispositivo
ethn Tarjeta Ethernet
trn Tarjeta de Token-Ring
fddin Tarjeta de fibra óptica
pppn Conexión de marcado a través de módem
lo Dispositivo de bucle local

En cada caso, n se remplaza por un número entero para cada instancia de un dispositivo
determinado conectado a una máquina.

Confirmar la configuración de la interfaz de red

El comando ifconfig muestra la configuración de interfaces de red activas. Puesto que el comando
suele ser utilizado por root para configurar interfaces, éste vive dentro del directorio /sbin, el cual
está fuera de la RUTA predeterminada para los usuarios estándar. No obstante, los usuarios
estándar pueden usar el comando para ver información de configuración de interfaz, utilizando una
referencia absoluta como en el ejemplo a continuación.

[blondie@station blondie]$ /sbin/ifconfig


eth0 Link encap:Ethernet HWaddr 00:00:86:4D:F0:0C
inet addr:192.168.0.51 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1716503 errors:0 dropped:0 overruns:2 frame:0
TX packets:2146415 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:193489123 (184.5 Mb) TX bytes:1299754457 (1239.5 Mb)
Interrupt:11 Base address:0xd400

lo Link encap:Local Loopback


inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:206054 errors:0 dropped:0 overruns:0 frame:0
TX packets:206054 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:22911068 (21.8 Mb) TX bytes:22911068 (21.8 Mb)

434
A la interfaz eth0 se le asigna una dirección IP de 192.168.0.254.

El comando ifconfig presenta una estrofa de información de la configuración IP y las estadísticas


de uso para cada interfaz de red activa. En la mayoría de los casos, los usuarios esperarían ver
dos estrofas. Una estrofa con la configuración para una tarjeta Ethernet y otra con la configuración
para el dispositivo virtual de bucle local. La línea importante es la segunda línea, la cual visualiza la
dirección IP asignada a la interfaz. Si la línea que contiene la dirección IP falta o si la dirección no
parece razonable para su configuración de red local, podrá tener problemas para acceder la red.

Determinar su portal por defecto: /sbin/route

Como se mencionó al comienzo de la lección, para la comunicación con equipos en sus subredes
locales se utilizan procedimientos diferentes a la comunicación con hosts en una subnet separada.
El kernel de Linux, al igual que otras kernels, define las máquinas que deberían considerarse
locales y la gateway que debería usarse para ayudar a comunicarse con aquellas que no lo son.
Este cuadro se llama cuadro de enrutamiento.

Si usted es un usuario estándar, el comando route se puede utilizar para ver el cuadro de
enrutamiento del sistema. Si es un usuario root, el comando puede también utilizarse para
manipular el cuadro. Al igual que el comando ifconfig, el comando route vive en el directorio /sbin,
por lo tanto los usuarios estándar deben invocarlo mediante una referencia absoluta.

[blondie@station blondie]$ /sbin/route


Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default server1.example 0.0.0.0 UG 0 0 0 eth0

Un cuadro de ruta estándar visualiza dos tipos de entrada. El primer tipo define qué subredes se
deben considerar como locales. En general, debería haber una línea que especifique una subred
para cada interfaz activa. En la salida anterior, la primera línea define la subnet asociada con la
interfaz de Ethernet (con una dirección IP de 192.168.0.51) y la segunda línea define la subred
asociada con la interfaz de bucle local (con una dirección IP de 127.0.0.1).

El segundo tipo de entrada que sirve para definir gateways es el más importante para nuestra
discusión. Dichas entradas de gateway se pueden distinguir porque el host está definido en la
segunda columna ("Gateway") y la cuarta columna ("Banderas") contiene una "G". Cada cuadro de
ruta debe contener una entrada para la gateway "por defecto" y la segunda columna debe contener
el nombre del host del gateway.

La misma información se puede ver mediante la dirección IP en lugar de nombres del host
utilizando /sbin/route -n.

[blondie@station blondie]$ /sbin/route -n


Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 192.168.0.254 0.0.0.0 UG 0 0 0 eth0

435
Aquí, blondie determina que su máquina está utilizando el host 192.168.0.254 como su
gateway predeterminado.
La bandera "G" indica que esta línea se utiliza para definir una gateway, no una subred local.

Determinar su(s) nombre de usuario(s)

El Servicio de Nombres de Dominio permite a los usuarios referirse a los computadores de la red
mediante nombres de host en lugar de direcciones IP. A diferencia de los otros dos aspectos de
configuración de red, un servidor de nombre es hasta cierto punto opcional. Con el fin de
comunicarse con otras máquinas su equipo debe tener una dirección IP. Si desea comunicarse con
máquinas fuera de la subred, usted debe tener una gateway por defecto. Sin embargo, si los
usuarios quieren referirse a cada máquina por dirección IP en lugar de nombre de máquina, su
equipo puede comunicarse mediante el protocolo IP sin consultar el servidor de nombres.

No obstante, en la práctica los servidores de nombres parecen ser más necesarios (se le facilita
más memorizar academy.redhat.com o 66.187.232.51?). Convertir un nombre de host en una
dirección IP suele conocerse como resolver una dirección y la biblioteca que ejecuta el servicio de
nombre se llama la biblioteca resolv. Cuando la biblioteca intenta resolver una dirección suele
haber dos recursos disponibles.

Configuración DNS estática: /etc/hosts

El primer recurso es un archivo de texto sencillo llamado archivo /etc/hosts. Aunque sólo root
puede editar el archivo cualquier usuario puede observarlo.

[blondie@station blondie]$ cat /etc/hosts


# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost rha-server
192.168.0.254 server1.example.com server s
192.168.0.1 station1 station1.example.com www1 www1.example.com
192.168.0.51 station51 station51.example.com
192.168.129.201 z
160.168.170.24 rosemont.example.com dhcp-1116-114 r

El formato del archivo es sencillo. El primer símbolo en la línea debería ser una dirección IP y los
símbolos subsiguientes son nombres de hosts que deberían apuntar a la dirección IP. El caracter
estándar de comentario de Unix (“#”) también es compatible.

Si el equipo sólo se está comunicando con pocas máquinas o si un administrador desea crear un
atajo de nombres de host (tal como “s”) o si deseara anular el servidor de nombre local, las
entradas pueden agregarse al archivo /etc/hosts mediante un editor de texto sencillo.

Claro está que esta técnica no escala bien. Usted no puede esperar que el archivo /etc/hosts le
responda a todo.

Configuración DNS dinámica: /etc/resolv.conf

Cuando el /etc/hosts local no puede dar respuesta, la biblioteca resolv consulta un servidor de
nombres. Para determinar qué máquina consultar que esté ejecutando un servidor de nombres,
examina el archivo de configuración de la biblioteca de resolv, /etc/resolv.conf.

436
[blondie@station blondie]$ cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search example.com
nameserver 192.168.0.254
nameserver 207.175.42.153

El host 192.168.0.254 está actuando como el servidor de nombre primario.

El host 207.175.42.153 está actuando como el servidor de nombres secundario.

El archivo de configuración /etc/resolv.conf utiliza líneas que comienzan por la palabra clave
servidor de nombres para especificar las direcciones IP de máquinas ejecutando servidores de
nombre. Si se especifican varios servidores de nombres, se utilizará el primero por defecto. Si no
está disponible se utilizará el segundo y así sucesivamente. Por consiguiente, el primer servidor de
nombres listado suele llamarse servidor de nombres primario, el segundo servidor listado servidor
de nombres secundario y así sucesivamente.

Observe que el servidor de nombres no necesita estar cerca de la máquina. Cualquier equipo que
esté ejecutando el servidor de nombres y le permita solicitarlo, puede usarse como servidor de
nombres. En la práctica, el uso de un servidor de nombres local genera un mayor rendimiento.

Utilidades de diagnóstico de red

En las secciones anteriores, hemos esbozado las técnicas más directas para determinar su
configuración de red IP local de la máquina. En esta sección, presentaremos las utilidades de
diagnóstico que sirven para asegurar que las configuraciones están funcionando correctamente
con su entorno de red local.

Confirmación de conectividad IP: ping

El comando ping sirve para confirmar la conectividad IP entre dos equipos. El primer argumento
para ping puede ser el nombre del equipo o la dirección IP de la máquina que usted desearía
contactar.

[blondie@station blondie]$ ping 192.168.0.254


PING 192.168.0.254 (192.168.0.254) 56(84) bytes of data.
64 bytes from 192.168.0.254: icmp_seq=1 ttl=64 time=0.245 ms
64 bytes from 192.168.0.254: icmp_seq=2 ttl=64 time=0.180 ms
64 bytes from 192.168.0.254: icmp_seq=3 ttl=64 time=0.186 ms
CTRL-C

--- 192.168.0.254 ping statistics ---


3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.180/0.203/0.245/0.033 ms

El comando ping debería presentar una línea por segundo, incluyendo el número de secuencia y la
información de temporización sobre la demora de ida y vuelta, la cual reporta el tiempo necesario
para recibir una respuesta de la máquina remota. El comando ping continuará ejecutándose hasta
cancelarse con la secuencia de control CONTROL-C.

437
Si no hay respuesta para el comando ping, usted no podrá esperar que se presente ninguna
comunicación de red de alto nivel. El culpable suele ser un cable Ethernet que se ha desconectado
físicamente de la máquina o de la pared.

Las inconsistencias en la tasa en la que las líneas se presentan o la discontinuidad en los números
de secuencia son generalmente indicativos de una red congestionada o de una conexión ruidosa y
se puede esperar un bajo rendimiento de red de protocolos de alto nivel.

Examen de ruta: /usr/sbin/traceroute

Cuando se conecte a una máquina fuera de su subred, su paquete pasa de router a router a
medida que atraviesa varias subredes hasta que finalmente se envía a la subred que contiene la
máquina destino. La ruta del paquete, cuando pasa de router a router puede trazarse con el
comando /usr/sbin/traceroute.

El comando traceroute suele llamarse con un argumento, el nombre del equipo o la dirección IP de
la máquina destino.

[blondie@station blondie]$ /usr/sbin/traceroute www.whitehouse.gov


traceroute: Warning: www.whitehouse.gov has multiple addresses; using 12.129.72.144
traceroute to a1289.g.akamai.net (12.129.72.144), 30 hops max, 38 byte packets
1 server1 (192.168.0.254) 0.243 ms 0.162 ms 0.252 ms
2 10.44.160.1 (10.44.160.1) 8.563 ms 10.488 ms 7.642 ms
3 srp2-0.rlghncg-rtr1.nc.rr.com (24.25.1.99) 7.382 ms 10.162 ms 0.874 ms
4 srp4-0.rlghnca-rtr2.nc.rr.com (24.25.2.146) 10.008 ms 8.798 ms 15.931 ms
5 srp13-0.rlghncrdc-rtr2.nc.rr.com (66.26.33.178) 4.259 ms 10.079 ms 10.031 ms
6 son0-1-1.chrlncsa-rtr6.carolina.rr.com (24.93.64.81) 29.675 ms 9.950 ms 29.665 ms
7 pop1-cha-P4-0.atdn.net (66.185.132.45) 10.087 ms 21.045 ms 8.202 ms
8 bb2-cha-P2-0.atdn.net (66.185.132.42) 11.392 ms 20.371 ms 9.712 ms
9 bb2-ash-P13-0.atdn.net (66.185.152.50) 29.322 ms 26.192 ms 25.901 ms
10 pop2-ash-P1-0.atdn.net (66.185.139.211) 26.506 ms 26.485 ms 26.208 ms
11 ATT.atdn.net (66.185.140.250) 26.704 ms 27.127 ms 21.004 ms
12 tbr1-p014001.wswdc.ip.att.net (12.123.9.82) 38.888 ms 22.006 ms 28.123 ms13 gbr6-
p20.wswdc.ip.att.net (12.122.11.174) 29.880 ms 19.628 ms 31.080 ms
14 gar3-p370.wswdc.ip.att.net (12.123.9.69) 24.231 ms 29.829 ms 20.827 ms
15 mdf1-gsr12-2-pos-7-0.atl1.attens.net (12.122.255.154) 40.184 ms 50.815 ms
38.903 ms
16 mdf1-bi8k-2-eth-1-1.atl1.attens.net (12.129.64.246) 39.845 ms 39.803 ms 39.887 ms
17 12.129.72.144 (12.129.72.144) 39.856 ms 39.934 ms 39.898 ms

Usted hallará con frecuencia que los paquetes toman rutas sorpresivas para ir de un lugar a otro. El
número de routers que su paquete pasa suele conocerse como el número de saltos que ha hecho
el paquete. El paquete anterior hizo 17 saltos para alcanzar su destino.

Si su paquete no puede completar el primer salto, es probable que su gateway por defecto de su
máquina no haya sido determinada correctamente. Si su traceroute termina entre la primera pareja
o salta (sin alcanzar el destino final), el problema es un router local mal configurado y su
administrador de red local probablemente ayude a resolver el problema. Si el comando traceroute
se agota a más de cuatro o cinco saltos, es probable que el problema esté fuera de control de su
administrador de red local.

Realización de solicitudes DNS de modo manual: host

438
El comando host se puede utilizar para realizar directamente solicitudes DNS. Con un argumento,
el comando host sólo reportará la resolución DNS solicitada.

[blondie@station rha030]$ host academy.redhat.com


academy.redhat.com has address 66.187.232.51

Si la opción -a se incluye, el comando host presenta información detallada de la solicitud realizada


y la respuesta recibida en el formato de "registro de recursos". Además, la línea final identificará el
servidor de nombres que resolvió la solicitud y la cantidad de tiempo que se necesitó para ello.

[elvis@station rha030]$ host -a academy.redhat.com

Trying "academy.redhat.com"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53870
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 0

;; QUESTION SECTION:
;academy.redhat.com. IN ANY

;; ANSWER SECTION:
academy.redhat.com. 284 IN A 66.187.232.51

;; AUTHORITY SECTION:
redhat.com. 584 IN NS ns1.redhat.com.
redhat.com. 584 IN NS ns2.redhat.com.
redhat.com. 584 IN NS ns3.redhat.com.

Received 106 bytes from 192.168.0.254#53 in 30 ms

En este ejemplo, el servidor de nombres que respondió tiene una dirección IP de 192.168.0.254.

Ejemplos

Diagnóstico de dificultades de red

La usuaria madonna está teniendo problemas para que su navegador de red mozilla se conecte al
sitio www.yahoo.com y cree que la máquina local podría estar mal configurada. Procede a
examinar sus configuraciones de red local y confirma que parecen funcionales.

Siguiendo el consejo de iniciar con lo básico, madonna primero se asegura que la máquina tenga
una dirección IP, examinando su configuración de interfaz de red local.

439
[madonna@staton madonna]# /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:50:8B:0C:B1:D5
inet addr:109.125.90.86 Bcast:109.125.90.255
Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:513364 errors:0 dropped:0 overruns:0 frame:0
TX packets:319118 errors:0 dropped:0 overruns:0 carrier:0
collisions:5068 txqueuelen:100
RX bytes:78770024 (75.1 Mb) TX bytes:356094835 (339.5 Mb)
Interrupt:11

lo Link encap:Local Loopback


inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:63432 errors:0 dropped:0 overruns:0 frame:0
TX packets:63432 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6124991 (5.8 Mb) TX bytes:6124991 (5.8 Mb)

Convencida que su interfaz está activa y utilizando la dirección IP 109.125.90.86, examina su


información de ruta para determinar su gateway por defecto.

[madonna@station madonna]# /sbin/route -n


Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
109.125.90.0 * 255.255.255.0 U 0 0 0 eth0
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
0.0.0.0 109.125.90.1 0.0.0.0 UG 0 0 0 eth0

Luego utiliza el comando ping para confirmar si puede contactar la gateway.

[madonna@station madonna]# ping 109.125.90.1


PING 109.125.90.1 (109.125.90.1) from 109.125.90.86 : 56(84) bytes of
data.
64 bytes from 109.125.90.1: icmp_seq=1 ttl=255 time=2.92 ms
64 bytes from 109.125.90.1: icmp_seq=2 ttl=255 time=2.65 ms
CTRL-C

--- 109.125.90.1 ping statistics ---


2 packets transmitted, 2 received, 0% loss, time 1004ms
rtt min/avg/max/mdev = 2.652/2.788/2.924/0.136 ms

Satisfecha, cancela el comando y luego examina su configuración DNS.

[madonna@station madonna]# cat /etc/resolv.conf


search example.com
nameserver 109.125.90.75
nameserver 109.125.90.2
nameserver 66.218.71.63

440
Puesto que ella todavía no ha llamado el host externo de su subred local, intenta llamar a un
servidor de nombres terciario.

[madonna@station madonna]# ping 66.218.71.63


PING 66.218.71.63 (66.218.71.63) from 109.125.90.86 : 56(84) bytes of data.
64 bytes from 66.218.71.63: icmp_seq=3 ttl=54 time=11.2 ms
64 bytes from 66.218.71.63: icmp_seq=7 ttl=54 time=20.3 ms
64 bytes from 66.218.71.63: icmp_seq=11 ttl=54 time=27.7 ms
CTRL-C

--- 66.218.71.63 ping statistics ---


13 packets transmitted, 3 received, 76% loss, time 12045ms
rtt min/avg/max/mdev = 11.275/19.766/27.702/6.717 ms

Los resultados del comando ping son un poco problemáticos, porque la mayoría de sus paquetes
se han quitado. En su lugar ella intenta determinar el camino recorrido por los paquetes a la
máquina.

[madonna@station madonna]# /usr/sbin/traceroute -n 66.218.71.63


traceroute to 66.218.71.63 (66.218.71.63), 30 hops max, 38 byte packets
1 209.125.90.1 3.473 ms 2.276 ms 2.281 ms
2 10.252.86.221 8.836 ms 15.761 ms 16.423 ms
3 216.217.3.193 11.293 ms 20.227 ms 15.257 ms
4 216.217.3.153 13.123 ms 10.306 ms 7.699 ms
5 63.215.192.173 10.835 ms 6.679 ms 6.881 ms
6 64.159.2.169 6.789 ms 7.117 ms 7.520 ms
7 64.152.69.30 12.358 ms 7.087 ms 6.877 ms
8 66.218.71.63 9.680 ms 11.787 ms 9.963 ms

Puesto que traceroute retornó dicha solicitud de salida, madonna asume que cualquier problema
observado con el comando ping anterior debió haber sido transitorio.

Por último, ella confirma que su servidor de nombres es operacional al realizar unas pocas
solicitudes de DNS con el comando host.

[madonna@station madonna]$ host www.redhat.com


www.redhat.com has address 66.187.232.50
[madonna@station madonna]$ host hardware.redhat.com
hardware.redhat.com is an alias for enterprise.redhat.com.
enterprise.redhat.com has address 66.187.233.193
[madonna@station madonna]$ host www.yahoo.com
www.yahoo.com is an alias for www.yahoo.akadns.net.
www.yahoo.akadns.net has address 66.218.71.95
www.yahoo.akadns.net has address 66.218.70.48
...

Convencida de que todo parece estar bien, trata de nuevo el navegador de red mozilla y tiene
éxito. Sea cualquiera el problema que estaba teniendo debe haberse relacionado con la congestión
de red transitoria observada con el comando ping.

441
Ejercicios en línea Lab Exercise Objetivo: Determinar la configuración de red local. Tiempo
estimado: 15 minutos.

Especificaciones

Crear los siguientes archivos, cada uno de los cuales debería contener su dirección IP como un
"quad punteado".

Archivo Contenido
~/net_ipaddr La dirección IP asignada a la interfaz eth0.
~/net_gw La dirección IP preseterminada de su gateway.
~/net_ns La dirección IP del servidor de nombres primario.

Deliverables A title Question 1

Los tres archivos presentados arriba, cada uno de los cuales contiene la dirección IP especificada
como su única palabra.

442
Terminal de red y clientes FTP

Conceptos clave

• El cliente HTTP de terminal Elinks, invocado como el comando links se puede utilizar para
navegar páginas web desde un entorno gráfico.
• La aplicación curl es una aplicación de protocolo múltiple no interactivo (incluyendo HTTP,
HTTPS y FTP) que sirve para transferir archivos en modo de lote.
• La aplicación wget es una aplicación de protocolo múltiple no interactiva (incluyendo
HTTP, HTTPS y FTP) que sirve para transferir de modo recursivo páginas web, buscando
en todas las páginas las referencias de página web.

Discussion

¿Por qué terminales basadas en clientes?

Los usuarios probablemente están familizados con las aplicaciones gráficas tales como mozilla
para navegar la red o nautilus para tener acceso a servidores FTP. Aparte de estas aplicaciones,
Linux también ofrece una amplia colección de clientes basados en la línea de comandos. ¿Por qué
alguien estaría tentado a utilizar clientes basados en líneas de comandos en lugar de apuntar y
hacer click en las aplicaciones?

• La razón obvia: si no está ejecutando en un entorno gráfico X, estas son las únicas
utilidades disponibles.
• Las utilidades se pueden escribir en scripts. Si tiene que extraer información de forma
repetitiva del mismo sitio, debería considerar un script para que haga el trabajo repetitivo
por usted.
• Las utilidades de la línea de comandos requieren menos recursos. Si está tratando de
descargar un archivo largo en otras máquinas ocupadas, un proceso curl es mucho más
atractivo que un proceso mozilla, porque el primero consume 4 megabytes mientras que el
segundo consume 40 megabytes de memoria.
• La simplicidad tiende a motivar la estabilidad. Cuando se descargan archivos grandes,
como por ejemplo, imágenes ISO de 700 megabytes, muchas de las aplicaciones pueden
volverse inestables, (la lista de culpables incluye a Internet Explorer). Los clientes de línea
de comandos como curl tienden a generar resultados más estables.

Navegación de páginas web con Elinks

El texto Elinks de cliente HTTP (navegador de red) está diseñado para traducir páginas web en una
terminal, emulando la presentación de un navegador de red gráfico. En cuanto sea posible, los
cuadros y formas se presentan en escala. Observe que en la siguiente visualización de la página
de red asociada con Red Hat Network, los marcos y cuadros están traducidos correctamente.

Inicio de Elinks

Los Elinks se inician como el comando links especificando una URL para cargar como un
argumento. Observe el siguiente ejemplo.

[elvis@station elvis]$ links http://www.redhat.com

443
Figure 1. El navegador de texto Elinks

Cuando utilice links, la pantalla está activa y los enlaces pueden navegarse mediante teclas de
flechas o el ratón. Al utilizar la tecla ESC, se crea un menú que permite al usuario acceder a los
diálogos de favoritos, historial y personalización.

Aunque la opción -dump sirve para entregar una página en una salida estándar y la opción
-source hará lo mismo al contenido "Crudo" de la URL (a menudo botando HTML), el soporte para
interacciones de guiones es muy poco sofisticado comparado con otras utilidades tales como curl.
La potencia del navegador links es su capacidad para proporcionar una grata experiencia de
navegación de red en un entorno de texto.

Configuración de Elinks para utilizar un servidor Proxy

Si se establece la variable del entorno HTTP_PROXY, los Elinks utilizarán el servidor proxy
especificado, donde el servidor proxy (al igual que el navegador Elinks) puede especificarse
mediante la siguiente sintaxis.

http://servername:puerto

Buscar los recursos de red con curl

En contraste, el comando links, el cliente de red de la línea de comando curl no se esfuerza por
verter o navegar interactivamente las páginas web. En cambio, el desarrollo de curl se ha
enfocado en una amplia colección de opciones que se adaptan para la entrega automática de
archivos publicados mediante una red o un servidor ftp. Este texto tendría dificultades describiendo
curl, pero algo más efectivo y suscinto es referirse a la página del manual curl(1):

444
curl es un cliente que sirve para obtener documentos/archivos o enviar documentos a un
servidor, utilizando cualquiera de los protocolos compatibles (HTTP, HTTPS, FTP, GOPHER,
DICT, TELNET, LDAP o ARCHIVO). El comando está diseñado para funcionar sin
interacción de usuario u otra clase de interacción.

curl ofrece una carga de trucos útiles como soporte proxy, autenti-
cación de usuario, carga ftp, texto HTTP post, SSL conexiones (https:), cookies,
reanudar transferencia de archivo y más.

Inicio curl

Cuando se llame con una URL como su argumento, el comando curl recupera y descarga su
contenido en la salida estándar. Además, alguna información de temporización se escribe en el
error estándar, el cual se desecha en el siguiente ejemplo.

[elvis@station rha030]$ curl http://www.redhat.com 2>/dev/null | head


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Red Hat -- Linux, Embedded Linux and Open Source Solutions</title>
<meta name="MSSmartTagsPreventParsing" content="TRUE">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<style type="text/css" media="all">@import "/css/non_ns4.css";</style>


<link rel="stylesheet" TYPE="text/css" HREF="/css/homepage.css">

El siguiente cuadro lista algunas de las opciones que se pueden utilizar para modificar la conducta
de curl. Consulte la página de manual curl(1) para obtener la lista completa.

Table 1. Opciones para el comando curl

Opción Efecto
-b, --cookie filename Proporciona valores de cookie desde el archivo especificado.
-c, --cookie-jar filename Almacena las cookies recuperadas en el archivo especificado.
-C, --continue-at posición Reanuda la transferencia de un archivo grande en una
posición especificada. Si se da como “-”, curl tratará de
encontrar automáticamente la posición apropiada.
-d data Proporciona datos como si los enviara a solicitud POST.
-i Incluye encabezados HTTP en la salida.
-L, --location Sigue redirecciones a una nueva ubicación.
-m, --max-time segundos Mata la conexión después de que el número especificado de
segundos ha transcurrido.
-O, --remote-name Escribe salida al archivo del mismo nombre como archivo
citado en la URL.
-u, --user Autenticar con par de nombredeusuario/contraseña.
nombredeusuario:contraseña

Por ejemplo, la siguiente línea de comandos podría utilizarse para descargar las imágenes ISO
para el lanzamiento de Fedora-Core 1:

445
[elvis@station elvis]$ curl -C - -O -L "http://download.fedora.redhat.com/pub/fe
dora/linux/core/1/i386/iso/yarrow-i386-disc{1,2,3}.iso"

[1/3]: http://download.fedora.redhat.com/pub/fedora/linux/core/1/i386/iso/yarrow
-i386-disc1.iso --> yarrow-i386-disc1.iso
% Total % Received % Xferd Average Speed Time Curr.
Dload Upload Total Current Left Speed
0 629M 0 536k 0 0 13375 0 13:42:49 0:00:41 13:42:08 75883

Los siguientes detalles de la línea de comando curl deberían observarse:

• Observe el uso de la "sintaxis de expansión de paréntesis" en la URL citada. El comando


curl tratará de descargar tres archivos, yarrow-i386-disc1.iso, yarrow-i386-disc2.iso y
yarrow-i386-disc3.iso.
• Debido a la opción -O, los archivos se descargarán al directorio local con los mismos
nombres.
• Observe el tiempo que le queda a la capacidad actual: 13 horas. Si el comando necesita
abortarse y luego reiniciarse, la opción -C - pide a curl que examine las descargas
parciales existentes y recoja la transferencia donde se abandona.
• La opción -L le pide a curl continuar con cualquier redirección expedida por el servidor de
red (aunque no es evidente desde la salida, curl fue redirigido al servidor FTP).

Configuración de curl para utilizar un servidor Proxy.

Si se establece la variable de entorno http_proxy, curl utilizará el servidor especificado proxy,


donde el servidor proxy puede especificarse con la siguiente sintaxis.

http://servername:puerto

De modo recursivo descargar los recursos de la red con wget

La línea de comando del cliente de red wget diseñada para uso no interactivo de los protocolos
HTTP, HTTPS y FTP descarga recursos posiblemente de modo recursivo a las páginas citadas
desde las páginas descargadas.

Inicio de wget

Cuando se llama con una URL como su argumento, el comando wget recupera el contenido de la
URL y lo almacena en un archivo local en el directorio actual de trabajo del mismo nombre (o
index.html si el URL especificó un directorio).

El siguiente cuadro lista algunas de las opciones que pueden utilizarse para modificar la conducta
de wget. Encontrará una lista completa en la página del manual wget (1).

Table 1. Opciones del comando wget

Opción Efecto
-i, --input-file filename Lea la URL para buscar desde el archivo filename, el cual puede ser
un archivo HTML o liste en modo secuencial el URL como texto.
-B, --base URL Anteponga URL a todos los enlaces relativos.

446
--spider No descargue páginas, solamente confirme su presencia.
--http-user=user --http- Autentique con el nombre de usuario especificado y la contraseña.
passwd=passwd
-o filename Concatene el contenido de todos los archivos descargados al
archivo filename. El nombre de archivo - especial implica una salida
estándar.
-r, --recursive Permite recuperar de modo recursivo.
-l, --level depth No es recursivo más allá de depth niveles de recursividad.
-np, --no-parent Al recursar, sólo incluya enlaces bajo el URL padre.

Por ejemplo, la siguiente línea de comandos sirve para copiar el contenido del sitio
http://www.redhat.com/training.

[elvis@station mirror]$ wget -r http://www.redhat.com/training

[elvis@station mirror]$ wget -r http://www.redhat.com/training


--02:53:01-- http://www.redhat.com/training
=> `www.redhat.com/training.1'
Resolving www.redhat.com... done.
Connecting to www.redhat.com[66.187.232.50]:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.redhat.com/training/ [following]
--02:53:01-- http://www.redhat.com/training/
=> `www.redhat.com/training/index.html'
Connecting to www.redhat.com[66.187.232.50]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 29,575 [text/html]

100%[====================================>] 29,575 175.04K/s ETA 00:00

02:53:02 (175.04 KB/s) - `www.redhat.com/training/index.html' saved [29575/29575]

Loading robots.txt; please ignore errors.


--02:53:02-- http://www.redhat.com/robots.txt
=> `www.redhat.com/robots.txt'
Reusing connection to www.redhat.com:80.
HTTP request sent, awaiting response... 200 OK
Length: 262 [text/plain]

100%[====================================>] 262 255.86K/s ETA 00:00


...
Después de observar un rato, debería ser obvio que cuando se llamó de modo recursivo, el
comando wget suele recursar más allá de las expectativas. Después de cancelar el comando
anterior con CONTROL-C, los siguientes directorios demuestran que wget se desvió más allá de
los límites del sitio web www.redhat.com/training.

447
.
|-- certcities.com/
| `-- robots.txt
|-- rhn.redhat.com/
| `-- index.html
|-- secure.safaribooksonline.com/
| `-- promo.asp?code=ORA14&portal=oreilly
|-- www.europe.redhat.com/
| `-- robots.txt
|-- www.google.com/
| `-- robots.txt
|-- www.oreillynet.com/
| `-- robots.txt
`-- www.redhat.com/
|-- about/
| |-- careers/
| | `-- index.html
| |-- contact/
| | `-- index.html
| |-- corporate/
| | `-- wwoffices/
| | `-- index.html
| |-- index.html
| `-- presscenter/
| |-- 2002/
| | |-- press_bluepoint.html
| | |-- press_rhct.html
| | |-- press_training.html
| | `-- press_veterans.html
| `-- 2003/
| `-- press_rhacademy.html
|-- apps/
| |-- commerce/
| | `-- index.html
...

Utilicelo con cuidado.

Configuración de wget para utilizar un servidor Proxy

Igual al comando curl, wget utiliza la variable de entorno http_proxy para especificar un servidor
proxy, de nuevo utilizando la siguiente sintaxis.

http://servername:puerto

Ejemplos

Uso de utilidades de transferencia del archivo con base en la terminal

El comando wget con opciones para intentar de nuevo puede ser útil para buscar archivos desde
un sitio ftp ocupado.

448
[einstein@station einstein]$ wget --tries=50 --wait=30 ftp://updates.redhat.com/
8.0/en/os/i386/wget-1.8.2-5.i386.rpm

--16:19:24-- ftp://updates.redhat.com/8.0/en/os/i386/wget-1.8.2-5.i386.rpm
=> `wget-1.8.2-5.i386.rpm'
Resolving updates.redhat.com... done.
Connecting to updates.redhat.com[66.187.232.52]:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done. ==> PWD ... done.
==> TYPE I ... done. ==> CWD /8.0/en/os/i386 ... done.
==> PORT ... done. ==> RETR wget-1.8.2-5.i386.rpm ... done.
Length: 365,737 (unauthoritative)

100%[====================================>] 365,737 4.83K/s ETA 00:00

16:20:40 (4.83 KB/s) - `wget-1.8.2-5.i386.rpm' saved [365737]

Al utilizar wget para copiar un sitio web, usted puede limitar el número de niveles de recursión.

[einstein@station einstein]$ wget --recursive --level=1 --convert-links


http://www.redhat.com/training/

Ejercicios en línea Lab Exercise Objetivo: Familiarizarse con la terminal basada en clientes
de red. Estimated Time: 10 mins.

Configurar

Si utiliza un servidor proxy para acceder a Internet, necesitará configurar sus clientes de red al
establecerhttp_proxy y/o las variables de entorno HTTP_PROXY. Su instructor le guiará.

Si este es el caso, coloque su configuración en el archivo ~/.bash_profile, para que la configuración


tenga lugar automáticamente en el inicio de shell.

Especificaciones

1. Cree el directorio ~/wget y cd dentro de éste. Utilice el comando wget para descargar de
modo recursivo el sitio www.redhat.com, pero utilice la opción -Q 256k para limitar su
descarga a un máximo de 256 kilobytes. Cuando haya terminado, su directorio ~/wget
debería contener el directorio www.redhat.com y posiblemente otros.
2. La CIA publica un libro mundial de datos de los países del mundo en el sitio
http://www.odci.gov/cia/publications/factbook/index.html. Más específicamente, URLs tales
como http://www.odci.gov/cia/publications/factbook/geos/ca.html se refieren a páginas del
país específico, en donde los países se especifican mediante un abreviatura de dos letras
en la porción del nombre de archivo de la URL.

Utilice el navegador de elinks para examinar una hoja de datos de todos los países
especificando la URL para la página del país directamente desde la línea de comandos.

Abbreviation País
as Australia

449
ch China
ni Nigeria

Después de familiarizarse con el formato de cada paǵina, escriba un script corto llamado ~/
bin/get_birthrate que combine los comandos curlygrep. El script debería esperar como su
único argumento una abreviatura de dos letras del país. Además, debería descargar la
página del país y reducir la salida a una línea que contenga la ¡nformación de la tasa de
natalidad del país.

Cuando haya terminado, el script debería generar una salida similar a la siguiente.

[student@station student]$ get_birthrate au


9.43 births/1,000 population (2003 est.)
[student@station student]$ get_birthrate ch
12.96 births/1,000 population (2003 est.)
[student@station student]$ get_birthrate ni
38.75 births/1,000 population (2003 est.)

Deliverables A title Question 1

1. El directorio ~/wget que contiene los primeros 256 Kbytes (o más) de una descarga
recursiva del sitio web http://www.redhat.com

El script ~/get_birthrate, el cual cuando se invoca con una abreviatura de país de dos
letras, extrae la línea apropiada desde la URL
http://www.odci.gov/cia/publications/factbook/geos/ca.html (donde “ca.html” debería
remplazarse con la abreviatura apropiada).

450
Comandos remotos de shell

Conceptos clave

• Las aplicaciones remotas de shell le permiten a los usuarios ejecutar comandos arbitrarios
en máquinas remotas y tener salida estándar retornada de manera local. De modo alterno,
se puede iniciar una shell interactiva.
• La aplicación Secure Shell ofrece una shell remota, donde todas las transacciones son
encriptadas y los usuarios pueden autenticarse mediante contraseñas tradicionales o
esquemas de autenticación de clave pública.
• Para utilizar los esquemas de claves de autenticación pública, debe generarse un par de
claves pública-privada con el comando ssh-keygen.
• Debido a que los servidores de Secure Shell tienen sus propios servidores de pares de
claves pública-privada, los servidores pueden autenticarse para los clientes como también
los clientes se pueden autenticarse para los servidores.

Discussion

La shell remota original: rsh y la autenticación de Rhosts

Shells remotas con rsh

Las shells de Linux (y Unix) estan diseñadas con interfaces sencillas. Leen entrada desde el flujo
de la salida estándar. Como resultado, las interfaces se implementan fácilmente a través de
conexiones de red. Simplemente al sustituir una conexión TCP para un dispositivo de terminal, una
shell puede operar en una máquina remota de un modo tan fácil como la máquina local. En Linux (y
Unix), las aplicaciones que proporcionan esta funcionalidad se conocen como shells remotas.

La primera shell remota más utilizada fue la aplicación rsh. Si una máquina remota se configura
adecuadamente los usuarios pueden utilizar la línea de comandos rsh parecida a la siguiente para
invocar una shell remota.

[elvis@station elvis]$ rsh -l elvis server1 ls /tmp


jd_sockV4
lost+found
orbit-root
ssh-WjMO1585
[elvis@station elvis]$

Al traducir este comando dice "como el usuario elvis en el servidor 1 host, ejecuta el comando ls
/tmp". El comando se ejecuta en la máquina remota (server1), pero la salida estándar es enviada a
la máquina local (station). Cuando el comando termina, el intérprete de comandos de elvis implica
que aún está en la estación host.

Si elvis no especifica el comando a ejecutar, la utilidad rsh abre una shell interactiva en el server1
host. Al prestar atención al intérprete de comandos de bash en el siguiente extracto, observe qué
comandos se ejecutan y en qué máquina.

451
[elvis@station elvis]$ rsh -l elvis server1
Last login: Sat Nov 8 18:23:49 from station.example.com
[elvis@server1 elvis]$ hostname
server1.example.com
[elvis@server1 elvis]$ who
root tty1 Nov 8 16:56
root tty2 Nov 8 16:56
root pts/0 Nov 8 16:57 (:0.0)
elvis pts/4 Nov 8 18:28 (station)
[elvis@server1 elvis]$ exit
rlogin: connection closed.
[elvis@station elvis]$

Autentificación de Rhosts: ~/.rhosts

En cada caso, elvis no necesitó expedir una contraseña. No obstante, antes de poder acceder a su
cuenta remota mediante rsh, necesitó configurar la cuenta para que le permitiera acceder desde su
máquina local. Para rsh, la configuración de control de acceso es tan trivial como agregar una línea
a un archivo. En una cuenta remota, elvis creó el archivo ~/.rhosts y agregó la línea con el host y el
nombre del usuario para cada cuenta externa a la cual quisiera otorgarle acceso. Además, el
servidor rsh requiere que los permisos de archivo le prohiban leer el archivo a todos con excepción
del usuario propietario. Así como se ilustra con el siguiente comando, elvis ya tiene configurado su
archivo .rhosts en la máquina remota.

[elvis@station elvis]$ rsh -l elvis server1 cat .rhosts


station elvis
[elvis@station elvis]$ rsh -l elvis server1 ls -l .rhosts
-rw------- 1 elvis elvis 16 Nov 8 18:23 .rhosts

La autenticación depende de un archivo de configuración ~/.rhosts configurado de modo adecuado


conocido como la autenticación rhost.

La Shell segura

El método de autenticación rhost es lamentable. En esencia, depende del DNS (Servidor de


Nombres de Dominio) para autenticar un usuario. Con el fin de explotar la configuración ~/.rhosts
de elvis, todos tendrían que separar la estación host real desde la red y traer otra máquina
configurada con la dirección IP de la estación. La falla no es de elvis, sino del diseño del protocolo
de autenticación rhost.

Además, rsh es un protocolo de texto sin formato. El intercambio de información a través de una
red en texto sin formato es esencialmente el equivalente a enviar correo en postales: todo el
mundo puede llevar la información de aquí a allá y no estar al tanto de su contenido.

La Shell segura se desarrolló para abordar estos dos defectos del comando rsh y agregar nuevas
capacidades mientras que aún ofrece toda la conveniencia de rsh. Si se asume que una máquina
remota está ejecutando el servicio ssh (i.e. el demonio sshd), elvis podría invocar una shell en la
máquina remota como se muestra a continuación.

452
[elvis@station elvis]$ ssh elvis@server1 ls /tmp
elvis@server1's password:
jd_sockV4
lost+found
orbit-root
[elvis@station elvis]$

La nueva sintaxis del comando ssh para especificar el nombre de usuario de la cuenta remota es
un poco más fácil que la de rsh, aunque la opción -l también se ejecuta (para ser completamente
compatible con los anteriores).

En el ejemplo anterior, elvis se autentica al proveer una contraseña en lugar de configurar un


archivo ~/.rhosts. En la siguiente sección, encontramos que la Shell segura puede utilizar una
técnica de clave pública más madura para otorgar una cuenta a los usuarios "libre de contraseña".
Sin embargo, cuando la clave de autenticación pública no se ejecuta, ssh vuelve a la autenticación
de contraseña tradicional. [1]

Autenticación de clave pública shell segura

Aparte de la autenticación tradicional, la aplicación Shell segura puede utilizar una clave
criptográfica para autenticar usuarios. Los algoritmos de clave pública encriptada se relacionan con
dos grandes números conocidos como "claves" a fin de que la información encriptada con una
clave solo pueda ser descrifada con la otra. Cualquiera que quiera utilizar criptografía de clave
pública debe generar primero un par de claves. La mayoría de los protocolos de clave pública
llaman una clave como clave pública y la complementaria como una clave privada. A su clave
pública usted la trata como su número telefónico, el cual comparte con quien desee comunicarse y
que puede listar en directorios públicos. Su clave privada, por otra parte, no la comparte con nadie.
Toda la seguridad provista por los protocolos de clave privada dependen del hecho que sólo usted
conoce su clave privada.

Generación de un par de clave pública-privada: ssh-keygen

Al utilizar ssh se puede generar un par de clave pública-privada con el comando ssh-keygen. La
shell segura puede utilizar diferentes algoritmos esenciales de encripción y el comando ssh-
keygen forzará a especificar uno con la opción -t. Para nuestros propósitos, utilizaremos el
algoritmo RSA, el cual se especifica con-t rsa. En el siguiente ejemplo, elvis utiliza ssh-keygen
para generar un par de clave pública-privada ssh-keygen.

[elvis@station elvis]$ ssh-keygen -t rsa


Generating public/private rsa key pair.
Enter file in which to save the key (/home/elvis/.ssh/id_rsa): RETURN
Enter passphrase (empty for no passphrase): RETURN
Enter same passphrase again: RETURN
Your identification has been saved in /home/elvis/.ssh/id_rsa.
Your public key has been saved in /home/elvis/.ssh/id_rsa.pub.
The key fingerprint is:
e0:71:43:df:ed:40:01:0b:44:54:db:c2:80:f2:33:aa elvis@station

Al usuario elvis primero se le pidió el nuevo nombre de archivo de clave (privada) para lo cual elvis
simplemente pulsó ENTER para aceptar el nombre de archivo predeterminado: ~/.ssh/id_rsa.
Luego, elvis tuvo la oportunidad de agregar una passphrase a su clave privada. Al pulsarENTER

453
otra vez (dos veces), elvis eligió no agregarla (más adelante trataremos las frases de acceso en
detalle).

Cuando el comando retorna, elvis tiene dos nuevos archivos en su directorio ~/.ssh. El primero
contiene su clave privada, la cual no la comparte con nadie (desde luego no la publica en un texto
en línea).

[elvis@station elvis]$ cat .ssh/id_rsa


-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQClJnymgdK0myP41/DcIyR9aam0DZQJUT20RLfqQb8ptk90jXSL
FrcIR2Ia59W/kJVLo4pqwJDsEJetWdhYiKUVJTANxbV2Pv21OACMlYcM316YLTOm
IeoEZj128yjZcehs2aBBhNEVW/Y0E1MDn9mm34yXT4z367OWnGXTc9yMWQIBIwKB
gQCW/p3aEEudz6vcMyVbjdg4JheADGoXJbTCEvFLNMwI4TKztIfPn71JZdYJ+Ijp
qMMDU7HAsA94vraP3R2SxhNFEEauYF+BXTae21MMKhU9JfgB1mQiYRaWrlU2j7cW
oF0vLnqYmTUV6CF9eJ8gMrgA28LymCpKhV/bng8l2uhnCwJBANNERHxLoKcTsANA
cmPs7iu1FtxuDk6Z4SctrkTVx+HtOE4JjpE/FKsJVpJK8oi/d0WEnpk2G7+67TSG
zsfHcqcCQQDIHnqQAWAZ9kd03UTjkuPSIj9OSBI5H25wYpUBItDQlUjwwJwL//C7
CDxFGgXfoO6pqr9f6JqqF9Ey/nNEpuj/AkAMEoeSEvM8v0vi7b1ky7XWnKI4e1FG
Ue+b1rmARrr295zRQl/rCus8+TglneH5L4MoizxDROukjlayi1xF7iPPAkBsotTR
1Nxl3Xc/cM2gHIpNgE5AcERoJwFwNYQWjz4oFoaulHH34rXh3+Y0JBHRK3o+2QjN
qigTMYAxoBKwPVnpAkEAvHl24SepSlAuSIwgtbluJApOfaDTizIAHh/G8PPFvH1e
p0J+MM7d/qFjg9gpcqZN34LOW8lD7Ab/GTQGl/XsWw==
-----END RSA PRIVATE KEY-----

Él es libre de compartir su segunda clave (la clave pública) con quien se la pida.

[elvis@station elvis]$ cat .ssh/id_rsa.pub


ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEApSZ8poHStJsj+Nfw3CMkfWmptA2UCVE9tES36kG/KbZP
dI10ixa3CEdiGufVv5CVS6OKasCQ7BCXrVnYWIilFSUwDcW1dj79tTgAjJWHDN9emC0zpiHqBGY9dvMo
2XHobNmgQYTRFVv2NBNTA5/Zpt+Ml0+M9+uzlpxl03PcjFk= elvis@station

Permiso de acceso de cuenta: ~/.ssh/authorized_keys

El acceso de SSH a una cuenta se otorga obteniendo una copia de clave pública de la persona a
quien se le va a otorgar acceso y almacenándola en el archivo ~/.ssh/authorized_keys de la
cuenta. Como el archivo ~/.rhosts, el archivo ~/.ssh/authorized_keys debe ser legible sólo por el
usuario propietario del archivo. La forma de obtener una clave pública no interesa. Podría enviarse
por correo electrónico scp o transferirse desde una terminal a otra utilizando las utilidades de cortar
y pegar del ratón.

Cuando se manejan claves públicas, se debe tener mucho cuidado de asegurarse que la clave se
coloca en un archivo sin espacio incorporado, incluyendo líneas nuevas. Aunque es demasiado
para visualizar como tal, las claves públicas SSH, siempre se almacenan como una línea de texto
sencilla. A la mayoría de la gente puede otorgársele acceso a una cuenta simplemente agregando
sus claves públicas a los archivos ~/.ssh/authorized_keys, una clave pública en cada línea.

Figure 1. Autenticación de clave pública SSH

454
En el siguiente ejemplo, elvis utiliza ssh, redirección y algunas comillas colocadas cuidadosamente
para agregar su clave pública (en la station host) al archivo authorized_keys en su cuenta en el
server1 host.

[elvis@station elvis]$ ssh elvis@server1 "cat >> .ssh/authorized_keys" <


.ssh/id_rsa.pub
elvis@server1's password:

¿Por qué son necesarias las comillas? Si las comillas se hubieran incluido, la salida del comando
cat se hubiera agregado al archivo .ssh/authorized_keys en la máquina local. Las comillas sirven
para pasar la sintaxis de redirección "en" la shell de red.

Habiendo colocado su clave pública en el archivo ~/.ssh/authorized_keys en la máquina remota,


elvis espera ahora poder examinar el contenido del archivo sin tener que expedir una contraseña.

[elvis@station elvis]$ ssh elvis@server1 "cat .ssh/authorized_keys"


elvis@server1's password:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEApSZ8poHStJsj+Nfw3CMkfWmptA2UCVE9tES36kG/KbZP
dI10ixa3CEdiGufVv5CVS6OKasCQ7BCXrVnYWIilFSUwDcW1dj79tTgAjJWHDN9emC0zpiHqBGY9dvMo
2XHobNmgQYTRFVv2NBNTA5/Zpt+Ml0+M9+uzlpxl03PcjFk= elvis@station

Algo no concuerda, porque a elvis se le solicitó otra vez su contraseña. Al recordar que los
permisos en el archivo ~/.ssh/authorized_keys deben ser 600, elvis ejecuta el comando chmod
apropiado en la máquina remota. Después, puede observar los nuevos permisos sin tener que
emitir una contraseña.

[elvis@station elvis]$ ssh elvis@server1 chmod 600 .ssh/authorized_keys


elvis@server1's password:
[elvis@station elvis]$ ssh elvis@server1 ls -l .ssh/authorized_keys
-rw------- 1 elvis elvis 225 Nov 22 22:29
.ssh/authorized_keys
[elvis@station elvis]$
Éxito.

Detalles de autenticación de la clave pública

Con el fin de desarrollar una apreciación de la robustes de la autenticación de la clave pública,


utilizaremos algunos minutos para tratar el protocolo. Cuando la aplicación Secure Shell ejecuta la

455
autenticación de clave pública, utiliza un procedimiento similar al siguiente. En nuestra discusión,
se utilizarán los siguientes símbolos.

Symbol Interpretación
S El contenido de la clave privada ("secreta") de elvis
P El contenido de la clave pública de elvis
R Una cadena de texto aleatoria
P(R) Una cadena de texto aleatoria encriptada por la clave pública de elvis
S(P(R)) = La cadena de texto es primero encriptada por la clave pública de elvis y luego
R descifrada por la clave privada de elvis.

Primero, el cliente ssh en la station host solicita una conexión al demonio sshd en el server1 host.
Tras recibir la solicitud de conexión, el demonio sshd busca una clave pública registrada en el
archivo ~/.ssh/authorized_keys de la cuenta de destino.

Si se descubre una clave pública relevante, el demonio sshd inicia la autenticación de clave
pública generando una cadena de texto aleatoria R. Luego encripta el guión aleatorio con la clave
pública de elvis P (obtenida desde el archivo ~/.ssh/authorized_keys) y envía el guión aleatorio
encriptado P(R) a través de la red al cliente ssh.

Figure 1. Algoritmo de autenticación de la clave pública (1 de 3)

Tras recibir la cadena de texto encriptada de modo aleatorio P(R), el cliente ssh utiliza la clave
privada de elvis S para descifrala. Una vez se recupera la cadena de texto original aleatoria el
cliente ssh retorna al demonio sshd.

Figure 2. Algoritmo de autenticación de la clave pública (2 de 3)

456
Si el demonio sshd recibe del cliente ssh la misma cadena de texto aleatoria con la cual inició, el
cliente se autentica y la conexión puede continuar.

Figure 3. Algoritmo de autenticación de la clave pública (3 de 3)

Un par de aspectos sobre este algoritmo que vale la pena mencionar.

• El cliente ssh no se autentica con su nombre de host o con su dirección IP sino


únicamente con una clave privada, (si el cliente no puede acceder a la clave privada
apropiada, no podría decriptar la cadena de texto encriptada aleatoria que se le entrega).
• La única información que pasó por alto la red es una cadena aleatoria encriptada y una
cadena aleatoria (los símbolos en rojo en las gráficas). Cualquiera que intercepte la
conversación no aprendería nada útil.

En la práctica, el algoritmo real utilizado es más complicado. Sin embargo, el protocolo esbozado
anteriormente ilustra la mayoría de las características de la autenticación de protocolo de clave
pública.

457
Transferencia de archivos de modo seguro y fácil: scp

Como se ilustra en la discusión anterior, los archivos se pueden transferir de una máquina a otra
mediante ssh con el comando cat y una redirección cuidadosa. Afortunadamente, hay una forma
más fácil y menos propensa al error: scp.

El comando scp utiliza una sintaxis casi idéntica a la del comando cp, pero cualquier archivo o
archivos de origen o destino pueden estar en una máquina remota, que ha tenido acceso a través
de una cuenta especificada [1]. Cuando se refiera al archivo en una máquina remota, se utiliza la
siguiente sintaxis.

user@host:ruta

El usuario y host son simplemente el equipo en donde reside el archivo y el usuario cuya cuenta se
utiliza para acceder el archivo. Si la ruta del archivo comienza con un “/”, se considera como una
referencia absoluta. Si no, se considera como una referencia relativa del directorio de inicio del
usuario. Si no se provee una ruta, se asume que es el directorio de inicio del usuario.

A manera de ejemplo, la siguiente línea de comandos transferiría el archivo /etc/services desde el


directorioserver1 al directorio ~/cfg/server1/etc/ en el directorio de inicio de elvis.

[elvis@station elvis]$ scp elvis@server1:/etc/services cfg/server/etc/


services 100% |*****************************| 19936 00:00

Dado que elvis ha configurado correctamente la autenticación de clave pública con su cuenta en
server1, puede transferir el archivo sin emitir una contraseña. ¿Qué sucede si trata de transferir el
archivo /etc/shadow?

[elvis@station elvis]$ scp elvis@server1:/etc/shadow cfg/server/etc/


scp: /etc/shadow: Permission denied

El usuario elvis en el server1 host no tiene permisos para leer el archivo /etc/shadow, por lo tanto
no puede ser transferido naturalmente. Sin embargo, si el usuario elvis conoce la contraseña de la
cuenta de root en la máquina remota, puede acceder el archivo a través de ella.

[elvis@station elvis]$ scp root@server1:/etc/shadow cfg/server/etc/


root@server1's password:
shadow 100% |*****************************| 2588 00:00

Puesto que elvis no tiene una clave de acceso pública autenticada para la cuenta de root server1,
ssh utilizó la autenticación tradicional de contraseña.

La opción -r (de "recursivo") se debe especificar al copiar un directorio completo (y sus


subdirectorios). A continuación, elvis copia de modo recursivo el directorio /etc/sysconfig desde su
máquina local (station) al directorio /tmp de la máquina server1.

458
[elvis@station elvis]$ scp -r /etc/sysconfig elvis@server1:/tmp
ifup-aliases 100% |*****************************| 13137 00:00
ifcfg-lo 100% |*****************************| 254 00:00
ifdown 100% |*****************************| 3676 00:00
ifdown-ippp 100% |*****************************| 820 00:00
ifdown-ipv6 100% |*****************************| 4076 00:00
...

Cuando el comando scp ejecuta la transferencia, este presenta la información de temporización de


la transferencia para cada archivo.

Autenticación de host de la Shell asegurada

La primera vez que el cliente ssh (o scp) se utiliza para conectarse a un servidor Secure Shell
sshd, se presenta un mensaje similar al siguiente:

[elvis@station elvis]$ ssh elvis@server1 who


The authenticity of host 'server1 (192.168.0.254)' can't be established.
RSA key fingerprint is fc:c8:87:90:f0:39:af:4f:de:99:cc:30:ce:64:b2:8e.
Are you sure you want to continue connecting (yes/no)?

Si la respuesta del usuario es sí (la única respuesta que permite continuar a la conexión), la
conexión continúa con la siguiente advertencia.

Warning: Permanently added 'server1,192.168.0.254' (RSA) to the list of known hosts.


root tty6 Nov 8 22:03
root pts/1 Nov 8 22:17 (:0.0)

En conexiones subsiguientes, el mensaje ya no aparece.

[elvis@station elvis]$ ssh elvis@server1 who


root tty6 Nov 8 22:03
root pts/1 Nov 8 22:17 (:0.0)
[elvis@station elvis]$

La Secure Shell no sólo autentica clientes a servidores, sino también servidores a clientes,
mediante la autenticación de clave pública. Así como los usuarios pueden crear pares de clave
pública-privada con el comando ssh-keygen, el demonio sshd mantiene su propio par de claves
pública-privada conocido como su host key. La primera vez que un cliente ssh se conecta a un
demonio sshd, añade una copia de la clave del host público del demonio remoto al archivo local
~/.ssh/known_hosts.

[elvis@station elvis]$ cat .ssh/known_hosts


server1,192.168.0.254 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAvaQ4ILVi9lceyBuGo9KUFY
ksKtPT8BsLPkLZYLIRVxmXDtG1+W+qxiAgw6qCROX8fAvBkdGS4gegt06NVpKItW87K5Wq6OMIlUfwfX
OmPNOWrdA+1Wym0LXYnkUDEOV8xvTUtGzy4MRIl0Phi92uJYEJkKsHMOCWGazN/DclBZk=

459
Como el cliente se utiliza para conectarse a varias máquinas, el archivo ~/.ssh/known_hosts crece,
registrando una clave pública para cada máquina contactada. La próxima vez que el cliente se
conecta a un host, silenciosamente emplea el mismo protocolo de clave pública utilizado para
autenticar usuarios, invertido, para autenticar el host al cual se está conectando.

¿Qué sucedería si el host remoto no tiene la misma identidad complementaria de la clave pública
almacenada en el archivo de cliente ~/.ssh/known_hosts? El cliente rehusa conectarse y en su
lugar emite la siguiente advertencia.

[elvis@station elvis]$ ssh elvis@server1 ls /tmp


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
c8:96:41:69:84:38:57:4c:18:55:7a:16:04:33:4d:f1.
Please contact your system administrator.
Add correct host key in /home/elvis/.ssh/known_hosts to get rid of this message.
Offending key in /home/elvis/.ssh/known_hosts:1
RSA host key for server1 has changed and you have requested strict checking.
Host key verification failed.
[elvis@station elvis]$

Aquí, el cliente ssh está identificando la línea desde el archivo ~/.ssh/known_hosts con la
clave que ya no complementa el servidor.

Suele haber una explicación razonable para el cambio de identidad del servidor. Por ejemplo, el
servidor pudo haber sido actualizado con una versión más reciente de su sistema operativo y como
resultado, generó un nuevo par de clave pública-privada. Si hay una explicación razonable para
que un servidor cambie de identidad, el cliente ssh puede ser forzado a quitar la línea incorrecta
del archivo ~/.ssh/known_hosts y recoger una nueva clave para el host.

[elvis@station elvis]$ rm ~/.ssh/known_hosts


[elvis@station elvis]$ ssh elvis@server1 ls /tmp
The authenticity of host 'server1 (192.168.0.254)' can't be established.
RSA key fingerprint is c8:96:41:69:84:38:57:4c:18:55:7a:16:04:33:4d:f1.
Are you sure you want to continue connecting (yes/no)? si
Warning: Permanently added 'server1,192.168.0.254' (RSA) to the list of known hosts.
jd_sockV4
lost+found
orbit-root
ssh-ayfI2751
sysconfig
Ejemplos

Acceso a una cuenta remota

El emperador julius recientemente se ha suscrito a la línea DSL en la casa y quisiera tener acceso
a la información en su máquina principal desde el trabajo. En su máquina principal, agregó una
cuenta para él mismo utilizando su apodo,jules. No sabe el nombre de host del computador en su

460
casa, pero antes de salir a trabajar anotó su dirección IP 69.57.97.126. En la oficina, utiliza una
máquina con un nombre de host emporer.rome.gov y su nombre de cuenta es julius.

Primero confirma si puede conectarse a su máquina principal con el cliente ssh.

[julius@emperor julius]$ ssh jules@69.57.97.126


The authenticity of host '69.57.97.126 (69.57.97.126)' can't be established.
RSA key fingerprint is 89:01:b1:55:7e:6f:da:0c:bc:fc:19:62:af:84:d6:7f.
Are you sure you want to continue connecting (yes/no)?

Como esta es la primera vez que ha tenido acceso a su máquina principal utilizando ssh, acepta la
clave del host al contestar si. En la siguiente solicitud de contraseña, entra la contraseña para su
cuenta de inicio de sesión.

Warning: Permanently added '69.57.97.126' (RSA) to the list of known hosts.


jules@69.57.97.126's password:
/usr/X11R6/bin/xauth: creating new authority file /home/jules/.Xauthority
[jules@localhost jules]$

Ahora Julius está contento porque puede tener acceso a su cuenta de inicio.

Configuración de la autenticación de la clave pública

Ahora que Julius sabe que puede acceder a su cuenta de inicio de sesión, desearía configurar la
autenticación de la clave pública, para poder ordenar directamente a su máquina principal desde la
oficina, sin tener que emitir una contraseña. Inicia generando un par de clave pública-privada en su
máquina de trabajo, mediante el algoritmo RSA. Puesto que la configuración por defecto es
apropiada para él, escasamente pulsa la tecla ENTER para todas las preguntas asociadas.

[julius@emperor julius]$ ssh-keygen -t rsa


...

Después de confirmar que sus archivos de clave pública-privada existen, utiliza el comando scp
para copiar su clave pública desde su equipo de trabajo al archivo .ssh/authorized_keys en su
máquina principal, autenticándose otra vez con su contraseña.

[julius@emperor julius]$ ls .ssh/


id_rsa id_rsa.pub known_hosts
[julius@emperor julius]$ scp .ssh/id_rsa.pub
jules@69.57.97.126:.ssh/authorized_keys
jules@69.57.97.126's password:
scp: .ssh/authorized_keys: No such file or directory

Aparentemente, ~/.ssh no existe aún. Julius remedia el problema y luego transfiere el archivo con
éxito. Por último, establece los permisos en el directorio remoto ~/.ssh y su contenido para que
sólo puedan estar disponibles para el usuario propietario.

461
[julius@emperor julius]$ ssh jules@69.57.97.126 mkdir .ssh
jules@69.57.97.126's password:
[julius@emperor julius]$ scp .ssh/id_rsa.pub
jules@69.57.97.126:.ssh/authorized_keys
jules@69.57.97.126's password:
id_rsa.pub 100% |*****************************| 226 00:00
[julius@emperor julius]$ ssh jules@69.57.97.126 chmod -R go-rwx .ssh
jules@69.57.97.126's password:

Con su autenticación de clave pública ahora configurada, Julius puede acceder fácilmente a su
máquina principal.

[julius@emperor julius]$ ssh jules@69.57.97.126 uptime


11:01:12 up 7:55, 1 user, load average: 0.08, 0.12, 0.09

Realizar copias de seguridad remotas con SSH

En su máquina principal. Julius tiene un directorio llamado archivos, el cual contiene documentos
importantes. El desearía hacer una copia de seguridad del archivo en su máquina de trabajo.
Desde su máquina de trabajo, emite la siguiente línea de comandos.

[julius@emporer julius]$ ssh jules@69.57.97.126 "tar czf - archive" >


jules.archive.tgz

Julius coloca un “-” donde sería especificado el nombre de archivo del archivo que se va a crear.
Este le pide al comando tar botar el archivo a la salida estándar en lugar de ponerlo en un archivo.
Localmente, la salida estándar fue redirigida al archivo jules.archive.tgz, Julius ha creado ahora
un archivo local del archivo remoto ~/archive como se confirma con el siguiente comando.

[julius@emporer julius]$ tar tvzf jules.archive.tgz


-rw-r--r-- jules/jules 112 2003-10-24 15:19:04 archive/named
-rw-r--r-- jules/jules 18 2003-10-26 08:00:11 archive/java
-rw-r--r-- jules/jules 204 2003-10-30 21:24:33 archive/quagga
...

Ejercicios en línea

Lab Exercise Objetivo: Utilizar correctamente la aplicación Secure Shell. Estimated Time: 30
mins.

Especificaciones

1. Configurar sus cuentas alternas primera y tercera (nombredeusuario_a y


nombredeusuario_c, respectivamente) para que usted pueda tener acceso a las cuentas
desde su cuenta primaria mediante ssh sin tener que proporcionar una contraseña.
Recuerde que todos los clientes de la red pueden contactar los servicios de red locales
mediante el nombre del host localhost.

462
2. Mediante su cuenta primaria, cree un script llamado ~/bin/send_to_a que copiará un
archivo regular como su único argumento en su directorio de inicio de su primera cuenta
alterna.
3. Mediante su cuenta primaria, cree un script llamado ~/bin/backup_c, el cual crea un archivo
tar gzipped del contenido de su directorio de inicio de la tercera cuenta alterna dentro del
archivo /tmp/backup_c.tgz.

Deliverables A title Question 1

1. La configuración correcta para que su cuenta primaria puede tener acceso a su primera y
tercera cuenta mediante ssh sin especificar una contraseña.
2. En su cuenta primaria, un script llamado ~/bin/send_to_a, el cual copiará un archivo regular
especificado como su único argumento dentro de sus primeras cuentas primarias de
directorio de inicio.
3. En su cuenta primaria, un script llamado ~/bin/backup_c, el cual crea un archivo tar
gzipped del contenido de su tercera cuenta alterna del directorio de inicio dentro del
archivo /tmp/backup_c.tgz.

463
Network Applications
Navegación del sistema de archivos

Conceptos clave

• El sistema de archivos de Linux es un "árbol invertido"de directorios y archivos con un


directorio raíz llamado "/".
• Todo proceso tiene un directorio actual de trabajo con frecuencia llamado "cwd".
• El comando pwd muestra el cwd de la shell bash.
• El comando cd cambia el cwd de la shell bash.
• Los archivos se pueden reseñar tanto por referencias absolutas como por referencias
relativas.
• parent home

Discussion

El árbol invertido del sistema de archivos

El concepto de un sistema de archivos organizado en directorios es común en muchos sistemas


informáticos. A un archivo individual se le asigna un nombre (un nombre de archivo), y los nombres
de archivo se organizan en un directorio (denominado como directorio en algunos sistemas
operativos). Sin embargo, los directorios son en sí mismos un tipo de archivo para que también
puedan ser recopilados en otros directorios. Este proceso puede continuar, nivel tras nivel, hasta
crear un entorno altamente estructurado.

Por ejemplo, la usuaria alice podría tener varias canciones almacenadas en archivos con nombres
como song1.midi y song2.midi. Estas canciones se podrían agrupar en un directorio llamado songs.
La usuaria alice también podría tener algunas fotos almacenadas en los archivos picture1.png y
picture2.png y a su vez, podría haberlos agrupado en un directorio llamado photos. Los dos
directorios songs y photos se pueden organizar en un directorio llamado media. Este nuevo
directorio puede ser uno de tantos en el directorio website.

Una manera de visualizar esto es por medio de una estructura ramificada de árbol. El directorio
website puede contener los subdirectorios html, formsy media. Junto con los directorios y los
archivos nombrados anteriormente, este orden se puede bosquejar como aparece en la gráfica 1-1.

Figure 1. Ejemplo de un árbol de directorios

464
-- html
|
website -- -- forms
|
| -- song1.midi
| |
| -- songs --
| | |
| | -- song2.midi
| |
-- media --
| -- picture1.png
| |
-- photos--
|
-- picture2.png

De la apariencia de ramificaciones de este diagrama es de donde surge la idea de árbol de


directorios. Por lo general se dibuja con las ramas hacia abajo y con la raíz del árbol en la parte
superior (website en este caso) y por lo tanto, se le llama estructura de directorio de árbol invertido.

Linux utiliza un sólo árbol de directorios para toda su colección de archivos y directorios, todas las
ramas de una sola raíz "/" (léase como "barra oblicua") llamada directorio raíz. Este árbol de
directorios se puede ver, en parte, como se muestra en la gráfica 1-2.

Figure 2. Árbol de directorios iniciando en /

-- bin...
|
/ -- -- etc...
|
| -- mystuff...
| |
| -- alice --
| | |
| | -- website...
| |
-- home --
| | -- docs...
| | |
| -- elvis --
| |
| -- graphics...
...

Las elipses en el diagrama sugieren que hay muchos archivos y directorios que no se muestran
aquí. Por ejemplo, puede ver que el directorio website trazado anteriormente puede adjuntarse
para extender el diagrama. La característica más importante del diagrama en este punto es la
estructura arbórea que se desprende de / y no el contenido específico.

465
Al nombrar un archivo o directorio, comience desde la raíz del árbol del sistema de archivos Linux y
liste todas las ramas del directorio hasta el archivo o directorio deseado, separando cada parte con
una barra oblicua (/). Esto se conoce como el nombre completamente calificado o FQN. Por
ejemplo, el FQN del directorio website, mencionado anteriormente, sería /home/alice/website. El
archivo song1.midide la usuaria alice se identificaría como /home/alice/website/songs/song1.midi.
La cadena de nombres de directorios que le llevan al nombre de archivo es la ruta del archivo. Este
tipo de nominación, ayuda a garantizar que cada archivo y directorio tenga un nombre único
completamente calificado. En la práctica real, los atajos y las suposiciones por defecto se utilizan
para simplificar el tecleado de los nombres de los archivos.

Exploración del árbol de directorios utilizando Nautilus

En el entorno gráfico X de Red Hat Enterprise Linux, los usuarios pueden utilizar Nautilus como
una herramienta sofisticada para navegar en el sistema de archivos. En el escritorio de Red Hat
Enterprise Linux, se puede abrir una ventana de Nautilus al hacer doble clic (izquierdo) en el icono
de inicio que se encuentra en la esquina superior izquierda.

Figure 1. Ventana Nautilus

Como una alternativa, usted puede utilizar el navegador Nautilus (puede ser más sencillo para
aquellos que han tenido contacto con lanzamientos previos de Red Hat Enterprise Linux) al
seleccionar el "navegador de archivos" desde el menú principal de Aplicaciones. [1]

Figure 3. El navegador Nautilus

Para poder explorar el árbol de directorios utilizando Nautilus, primero tenemos que activar el panel
lateral de Nautilus. Esto puede hacerse seleccionando el "panel lateral" desde el menú "ver".

Figure 4. Activación del panel lateral de Nautilus

La aplicación de panel lateral deNautilus se utiliza para diferentes propósitos. En este momento,
estamos interesados en explorar el árbol de directorios, así que seleccione "árbol" en el panel
lateral superior del menú.

Figure 5. Selección del panel lateral del árbol en Nautilus

El panel lateral de Nautilus le debe mostrar ahora la lista de directorios (carpetas) en forma de
árbol con el directorio superior llamado simplemente /. Un directorio se puede expandir al hacer clic
(en el botón izquierdo del ratón) en el triángulo al lado del icono de la carpeta. Cuando haga click

466
en el icono de la carpeta o en el nombre de carpeta, podrá ver el contenido de la carpeta en el
panel principal de Nautilus.

Figure 6. Exploración del árbol de directorios con Nautilus

Tenga en cuenta que cuando se selecciona un directorio particular para ver, la entrada de "Buscar"
que se encuentra justo arriba del panel principal, muestra una referencia absoluta (FQN) para el
directorio que se está viendo. Dedique un poco de tiempo para explorar el sistema de archivos con
Nautilus y para ver el contenido de varios directorios. Intente ver el contenido del archivo
/etc/sysconfig/network-scripts/ifcfg-lo, primero seleccionando el directorio /etc/sysconfig/network-
scripts en el panel lateral y después, haciendo doble clic (en el botón izquierdo del ratón) en el
icono ifcfg-lo en el panel principal.

Ahora que ha dedicado un poco de tiempo explorando el concepto de árbol de directorios y la


forma como se construyen las referencias absolutas a los directorios y los archivos, hablaremos un
poco sobre algunos de los conceptos relacionados con el sistema de archivos de Linux.

El directorio de trabajo actual (cwd)

A cada proceso Linux (por ejemplo,un programa o un comando) cuando se ejecuta, se le asigna un
directorio por defecto. Este directorio por defecto se utiliza para completar el FQN para cualquier
archivo cuyo nombre no se especifique como un FQN. Esto tiene dos efectos. Primero, le permite
al proceso referirse a los archivos de una manera más sencilla sin tener que utilizar nombres
demasiado largos. Segundo, le permite al proceso operar con mayor flexibilidad ya que sus
acciones dependen en parte del directorio por defecto. Si cambia el directorio por defecto, la acción
del proceso también cambiará. A este directorio por defecto se le conoce como el directorio actual
de trabajo ó cwd, para el proceso.

Un método común que puede utilizarse con los directorios es el considerar un directorio como un
lugar más que una cosa. Desde este punto de vista entonces el cwd para un proceso se puede
considerar como la ubicación actual de un proceso. Si un proceso cambia de cwd entonces se ha
movidode un directorio a otro. Esta manera de ver un directorio como un "lugar" es tan común en el
mundo de Linux que la palabra lugar es bastante dominante en el lenguaje. Por ejemplo, los
usuarios hablan de navegar el sistema de archivos cuando se mueven de un directorio a otro.

En primer lugar, el padre del proceso que lo inicia le asigna un cwd al proceso. Sin embargo, un
proceso no está sujeto todo el tiempo a un determinado cwd cuando ejecuta. Cuando sea
necesario, un proceso puede cambiar su cwd a otro directorio antes de continuar su trabajo.

¿En dónde estoy? El comando pwd

Uno de los procesos que se encuentra en ejecución en un sistema de Linux es la shell de


comandos. Si usted inicia la sesión en el sistema a través de una terminal virtual, o inicia un
programa de terminal en X, verá el intérprete de comandos en donde puede introducir comandos
para que el sistema actúe. Este intérprete de comandos es producido por la shell de comandos, el
cual es el proceso responsable de la lectura e interpretación de comandos. Por defecto, la shell de
comandos para los sistemas de Red Hat Enterprise Linux es la shell de comandos bash (del inglés
Bourne-again shell).

Como cualquier otro proceso, la shell bash se mantiene al tanto de su cwd mientras está
ejecutando. El directorio de trabajo actual afecta los comandos que usted escribe en el intérprete
de comandos y se convierte en su cwd mientras ejecutan. Básicamente entonces, el cwd de la
shell bash es su cwd, y puede considerarse como el lugar en donde usted se encuentra dentro del
sistema. Obviamente, es importante estar al tanto del cwd. Afortunadamente, hay ayuda disponible.

467
Primero, el mismo intérprete de comandos muestra el último directorio de la ruta al cwd. Por
ejemplo, la usuaria alice, al trabajar en su directorio website, puede ver un intérprete de comandos
como éste:

[alice$station website]$

El intérprete de comandos le recuerda que ha iniciado la sesión con el nombre de usuario "alice" en
la "estación," del computador y se encuentra en el directorio website. Pero pueden haber otros
directorios website en alguna otra parte del sistema. La ruta completa (o absoluta) del directorio de
trabajo actual se puede visualizar con el comando pwd (del inglés print working directory).

Uso:

pwd

La usuaria alice quiere verificar si se encuentra en el directorio correcto. Podría utilizar pwd.

[alice@station student]$ pwd


/home/alice/website

Cambio de sitio- El comando cd

Como se anotó anteriormente, los procesos pueden cambiar sus cwd cuando sea necesario. Esto
incluye la shell de comando bash, la cual proporciona el comando cd (del ingleś change directory)
para cambiar el directorio actual desde el intérprete de comandos.

Uso:

cd [DIRECTORIO]

Si no se especifica, DIRECTORIO utiliza por defecto el directorio de inicio del usuario.

Considere la siguiente secuencia de comandos:

[alice@station website]$ pwd


/home/alice/website
[alice@station website]$ cd /home
[alice@station home]$ pwd
/home
[alice@station home]$ cd /home/alice/website/songs
[alice@station songs]$ pwd
/home/alice/website/songs

Observe cómo cambia el resultado del comando pwd y la última parte del intérprete de comandos
para reflejar el nuevo cwd después de cada comando cd.

Puesto que navegar por los directorios es tan importante, hay abreviaturas especiales para hacer
referencia a ciertos directorios:

468
Table 1. Nombres de directorios especiales

Symbol Significado
. The current working directory
.. El directorio padre
~ The user's home directory
- El directorio de trabajo anterior

Las entradas en esta tabla requieren poca explicación. Primero, bash reconoce todos menos el
último nombre simbólico en la mayoría de los contextos, no sólo en el comando cd. Segundo, el
árbol de directorios se describe generalmente utilizando la analogía padre/hijo. Si dir1 contiene a
dir2, entonces se dice que dir2 es el directorio hijo de dir1 y que el dir1 es eldirectorio padre del
dir2. Por lo tanto, el directorio .. está a un nivel más cerca de la raíz del árbol de lo que se
encuentra el cwd. Después se le asigna un directorio de inicio a cada cuenta de usuario,
usualmente un subdirectorio de /home que coincide con su nombre de usuario (este tema se
explicará más detalladamente en el siguiente capítulo). El directorio ~ representa ese directorio.
Finalmente, la raya (-) es una opción especial del comando cd que se refiere al directorio de
trabajo anterior, facilitando el cambio entre directorios hacia adelante y hacia atrás.

De nuevo, considere la siguiente secuencia de comandos:

[alice@station songs]$ pwd


/home/alice/website/songs
[alice@station songs]$ cd ~
[alice@station alice]$ pwd
/home/alice
[alice@station alice]$ cd -
[alice@station songs]$ pwd
/home/alice/website/songs
[alice@station songs]$ cd ..
[alice@station website]$ pwd
/home/alice/website
[alice@station website]$ cd
[alice@station alice]$ pwd
/home/alice

La última serie de comandos en el ejemplo anterior muestra que por defecto el comando cd usa el
directorio ~ si no se le asigna un directorio.

Referencias absolutas y relativas

Esta sección describe dos maneras de identificar la ubicación de un archivo. En esta sección, como
casi en cualquier otra parte de estas lecciones, es importante recordar que en Linux un directorio
es un tipo de archivo, así que todo lo que se diga sobre nominación de archivos, también aplica a
directorios y a archivos comunes de datos.

Para identificar un archivo, se debe proporcionar suficiente información para localizar el archivo
dentro del sistema de archivos. Esta ubicación se puede proporcionar de dos maneras: como
referencia absoluta(o ruta absoluta) o como referenciarelativa.

Las referencias absolutas inician con una barra oblicua (/) y asignan el FQN del archivo. Es decir,
la referencia absoluta nombra cada rama del árbol de directorio del sistema de archivos, a partir

469
de /, la cual se debe recorrer hasta llegar al archivo. Sin importar en dónde se encuentre usted en
el sistema de archivos, (en otras palabras, sin importar el valor del cwd), una referencia absoluta
identifica claramente el recurso específico. Ya hemos discutido varios ejemplos de referencias
absolutas en esta lección.

Una referencia relativa no describe la ruta al archivo desde /, sino que describe la ruta a partir del
directorio actual. Por ejemplo, si el cwd es /home/alice, entonces la referencia relativa a song1.midi
puede ser website/songs/song1.midi. Esta es una referencia relativa ya que no comienza con /.
Esta referencia sólo nombra los directorios que se deben recorrer iniciando desde /home/alice, no
desde /. Para que una referencia relativa sea válida debe iniciar nombrando un directorio (o
archivo) en el cwd.

Todos los directorios en Linux contienen dos entradas especiales, los directorios . y .., los cuales
representan el directorio actual y el directorio padre, respectivamente. Por lo tanto, en la discusión
previa acerca del comando cd, el ejemplo cd .. era en realidad sólo un uso de una referencia
relativa.

La tabla 1-2 muestra algunos ejemplos adicionales sobre referencias relativas. Cada uno de estos
es una referencia al archivo /home/alice/sample.txt con FQN. Algunos de estos ejemplos son
intencionalmente "ineficaces."

Table 1. Ejemplos de referencias relativas a /home/alice/sample.txt

cwd Referencia relativa


/home/alice sample.txt o ./sample.txt
/home/alice/website/songs ../../sample.txt
/home/elvis/docs ../../alice/sample.txt
/home alice/sample.txt
/home ../home/alice/website/../sample.txt

Sí, el último ejemplo es bastante tonto, pero es perfectamente válido.

Ejemplos

Descubrir el directorio de inicio

Hogan acaba de inciar sesión y no se ha dado cuenta de que, por defecto, su directorio de inicio se
encuentra asignado como su cwd. Además, tampoco se ha dado cuenta de que su directorio de
inicio es /home/hogan. Se dispone a descubrir cuál es su directorio de inicio y también quiere ver si
de hecho su cwd por defecto es su directorio de inicio.

Hogan sabe que


[hogan@station el cwd termina
hogan]$ cd ~ en hogan (desde el intérprete de comandos), pero no sabe si
éste es su directorio
[hogan@station hogan]$ de pwd
inicio. Utiliza el comando cd con el directorio ~ para cambiar a su
directorio de inicio.
/home/hogan
[hogan@station
Después, Hogan hogan]$ cd para
utiliza pwd - ver el FQN de su directorio de inicio. Sabe que /home/hogan
/home/hogan
es el directorio de inicio, pero ¿es de ese directorio de donde empezó?
Para ver desde dónde empezó, Hogan utiliza de nuevo el comando cd esta vez para regresar
al directorio de trabajo anterior.
El comando cd - muestra el comando cwd después de hacer el cambio (¿por qué es este
comportamiento razonable?). Ahora Hogan sabe que su sistema le da inicio con su directorio
de inicio establecido como directorio de trabajo inicial.

470
Subir y bajar del árbol

Alice necesita editar algunos de los archivos html en su sitio web. Después de iniciar la sesión
necesitará cambiarse al subdirectorio apropiado bajo su directorio de inicio. Cuando lo haya hecho,
deberá ir a /etc para examinar el archivo de configuración. Finalmente, tendrá que devolverse a su
directorio de inicio para empezar a trabajar en otra tarea.

[alice@station alice]$ cd website/html


[alice@station html]$
... (edits the html files) ...
[alice@station html]$ cd /etc
[alice@station etc]$
... (examines the configuration file) ...
[alice@station etc]$ cd
[alice@station alice]$
... (continues with other tasks) ...
• Alice utiliza una ruta relativa para cambiar al directorio /home/alice/website/html ya que es
más corta que el FQN, pero cualquiera de los dos habría funcionado.
• Después de terminar su trabajo en los archivos html, Alice utiliza una referencia absoluta
para cambiar los directorios a /etc. En este caso, la ruta absoluta es mucho más corta y
más fácil de entender que la referencia relativa equivalente, ../../../../etc.
• Observe que el intérprete de comandos no contiene una / antes del nombre de directorio
etc. El bash por defecto sólo muestra el componente final del cwd.
• Al haber terminado su trabajo en /etc, alice regresa a su directorio de inicio utilizando la
conducta predetermianda del comando cd.

Ejercicios en línea

Explorar el sistema de archivos Lab Exercise Objetivo: Demostrar el uso de cd.Estimated Time:
10 mins.

Especificaciones

En este ejercicio tendrá que configurar el directorio actual de trabajo de cuatro shells bash
ejecutando de manera simultánea. Si está utilizando el entorno gráfico X puede simplemente abrir
cuatro terminales. Si está utilizando consolas virtuales, puede utilizar cuatro de las seis consolas
virtuales provistas.

Abra cuatro terminales con shells bash (como se describió anteriormente) utilizando su cuenta
primaria. Utilice el comando cdpara establecer los directorios de trabajo actuales de las shells en
los siguientes cuatro directorios:

1. ~/..
2. /tmp
3. /etc/sysconfig
4. /usr/share/gnome

Deliverables A title Question 1

1. Cuatro shells bash ejecutando de manera simultánea con cada directorio de trabajo actual
de shell establecido en uno de los cuatro directorios listados anteriormente.

471
Possible Solution

El siguiente comando configura el directorio de trabajo actual de la shell al primer directorio de


trabajo listado anteriormente.

472
Directorios importantes

Conceptos clave

• A toda cuenta de usuario se le asigna un directorio de inicio.


• El directorio /tmp se utiliza como espacio global para borradores.
• Los directorios /bin y /usr/bin comúnmente contienen archivos ejecutables.
• El directorio /etc contiene archivos de configuración del sistema.
• El directorio de inicio de /root, no se debe confundir con el directorio raíz del sistema de
archivos, /.

Discussion

Esquema estándar de directorios de Linux

Linux se puede utilizar para soportar muchos tipos diferentes de sistemas informáticos: servidores,
estaciones de desarrollo, sistemas de escritorio personales, etc. Para poder estandarizar la
estructura del directorio del sistema de archivos a través de este variado rango de sistemas, la
mayoría de los sistemas Linux emplean un esquema de nominación y utilización común que
facilitan el uso y el mantenimiento de los sistemas. Al utilizar el mismo tipo de diagrama arbóreo
empleado en el último capítulo, parte de la primera capa del árbol de directorios se vería así:

Figure 1. Árbol parcial de directorios iniciando en /

-- bin...
|
-- etc...
|
-- home...
|
-- root...
/ --|
-- sbin...
|
-- tmp...
| -- bin
-- usr --|
| -- sbin
-- var...

Este capítulo presenta una breve descripción (a veces muy breve) del papel de cada uno de estos
directorios.

El directorio de inicio del usuario

A cada usuario del sistema Linux se le asigna un directorio especial llamado su directorio de inicio
y representa su espacio "privado" en el sistema. Comúnmente éste es un subdirectorio bajo el
directorio /home, cuyo nombre coincide con el nombre de inicio de sesión del usuario (se vieron
varios ejemplos anteriormente /home/alice o /home/hogan). La única excepción importante a esto
es el superusuario (o el usuario root) cuyo directorio de inicio usualmente es /root. Para cualquier

473
usuario, el caracter (~) representa el FQN del directorio de inicio del usuario cuando se utiliza como
el primer caracter de una referencia de archivo o directorio.

El propósito más obvio para el directorio de inicio de un usuario es brindar un espacio privado para
datos, un lugar en donde se pueden guardar archivos separados de los archivos de otros usuarios.
Normalmente, los usuarios son libres de crear subdirectorios bajo su directorio de inicio y de
organizar sus datos como les parezca (sujetos a las restricciones de cuotas que deben haber). Dos
usuarios diferentes pueden incluso asignar el mismo nombre a archivos y directorios sin causar
ningún conflicto ya que cada uno almacena en su propio espacio. Por ejemplo, tanto Alice como
Hogan pueden tener cada uno su subdirectorio public_html, /home/alice/public_html y
/home/hogan/public_html respectivamente. El mantener el espacio de cada uno separado de los
otros, ofrece también más seguridad a los usuarios.

Otro aspecto importante del directorio de inicio de un usuario es que proporciona un lugar para
almacenar archivos de configuración específicos para cada usuario. Por ejemplo, cuando Blondie
inicia la sesión puede que necesite un entorno diferente al de Prince. Puede que Blondie prefiera
diferentes colores en su pantalla, diferentes atajos de comandos e inclusive un entorno de
escritorio de trabajo completamente diferente al de Prince. Los archivos de configuración locales
específicos para cada usuario hacen que esto sea posible. Muchos de estos archivos de
configuración se crean automáticamente por defecto cuando se crea la cuenta de un usuario o al
utilizar por primera vez un recurso en particular del sistema.

Normalmente se le da a los usuarios un control relativamente completo sobre sus directorios de


inicio mientras que se les restringe el acceso al resto del sistema. Por ejemplo, hay una gran
probabilidad de que alice no pueda modificar o borrar ningún archivo de configuración en el
directorio /etc aunque es posible que sí pueda leerlos. Además, es muy probable que no pueda
leer, modificar o borrar ninguno de los archivos en los directorios de los usuarios del sistema.

Cuando un usuario inicia sesión en el sistema por primera vez se le ubica "en" su directorio de
inicio, es decir, el sistema configura su directorio de inicio como su directorio de trabajo inicial.

El directorio temporal /tmp

Además de su espacio personal en sus directorios de inicio, se le da acceso a los usuarios para
compartir espacio de "borrador", en el directorio /tmp. Un programa que necesite almacenar datos
comprimidos puede almacenar resultados parciales en /tmp, sólo poniendo los resultados finales
en el directorio de inicio del usuario cuando haya terminado de hacerlo. Con frecuencia los
sistemas Linux implementan cuotas en cuentas de usuarios para prevenir que cualquier usuario
consuma una proporción injusta del espacio disponible. El directorio /tmp le da a todos los usuarios
acceso a espacio adicional para cumplir con necesidades a corto plazo sin cargar el espacio en su
cuota. Esto es especialmente importante, ya que los usuarios no siempre son conscientes de
cuánto espacio extra necesita un servicio y algunos servicios (tal como X) no pueden ejecutar si no
hay espacio temporal disponible de almacenamiento. Este espacio de borrador "global" se
encuentra disponible para todos los procesos en el sistema así como para todos los usuarios. El
sistema borra automáticamente los archivos puestos en este directorio después de unos días.

El directorio de configuración /etc

Una de las características únicas de un sistema Linux es su flexibilidad. Prácticamente todo


aspecto del sistema puede configurarse de alguna forma editando un archivo de configuración.
Estos archivos de configuración normalmente se colocan en /etc o en un subdirectorio de /etc. Por
ejemplo, el programa sendmail, a menudo utilizado para ejecutar un servidor de correo, utiliza los
archivos de configuración que se colocan en /etc/mail. Los scripts de arranque del sistema se
encuentran en /etc/rc.d, mientras que los archivos de configuración de la red se encuentran en /etc/

474
sysconfig. Obviamente, los usuarios comunes no pueden modificar los archivos en /etc (o incluso
leerlos, en algunos casos), pero los administradores de sistemas invierten bastante de su tiempo
trabajando con los archivos almacenados aquí.

Los directorios de comandos /bin y /usr/bin

La mayoría de los comandos del sistema se encuentran almacenados como archivos binarios en
un formato legíble para la máquina. Los comandos apropiados para el uso de usuarios comunes se
suelen ubicar en los directorios binarios /bin o /usr/bin. Las utilidades más importantes como ls, cd,
cp, mv y el editor de texto vi, sin los cuales no se podría usar el sistema van en /bin. Las utilidades
adicionales como los compiladores, su navegador de web y la suite de oficina van en /usr/bin, los
cuales se pueden poner a disposición de otros sistemas a través de la red. Considere /bin y /usr/bin
como directorios de comandos no privilegiados ya que no se necesitan privilegios especiales para
utilizar los comandos que se encuentran en ellos.

Considere /bin y /usr/bin como directorios de archivos no privilegiados puesto que no se requieren
privilegios especiales para utilizar los comandos que se encuentran en ellos.

Los directorios de comandos /sbin y /usr/sbin

Así como /bin y /usr/bin almacenan archivos de comando para usuarios comunes, también /sbin y /
usr/sbin almacenan archivos de comandos para que el superusuario root los utilice. Estos incluyen
comandos para adjuntar y quitar hardware, para iniciar y detener el sistema y para realizar
mantenimiento del sistema. Estos comandos privilegiados también se encuentran almacenados en
dos directorios separados por las mismas razones que para /bin y /usr/bin.

El directorio "variable" /var

Las colecciones de comandos y de archivos de configuración que se encuentran en lugares como /


bin o /etc cambian muy poco día a día, si es que cambian del todo. Estos archivos tienden a ser
muy estables. Sin embargo, algunos archivos cambian con frecuencia. Estos incluyen correo
electrónico entrante y saliente, registros del sistema, sitios web, archivos ftp y similares. Estos
archivos y directorios con contenido variable suelen recopilarse en el directorio /var. El colocar
dichos archivos aquí hace más fácil asignarles espacio y proteger los archivos más estables que se
encuentran en alguna otra parte del sistema.

root vs./rootvs./ (la raíz del sistema de archivos)

Es un desafortunado accidente de la historia que el término raíz tenga un papel tan importante y a
la vez confuso en Linux. La raíz o el "root" en inglés, es el nombre de usuario del superusuario, es
decir, el usuario con autoridad suprema sobre el sistema. También es el nombre del directorio de
inicio de ese usuario, /root. Igualmente, es el término que se utiliza para la base (¿la parte
superior?) del árbol de directorios del sistema de archivos, el directorio /. Normalmente, el
significado del término se puede deducir del contexto, pero una oración tal como el "directorio raíz"
puede llegar a ser ambigua. Trate de anticipar y de evitar tal confusión en su propia comunicación y
busque aclaración si el significado de la palabra no se puede deducir fácilmente del contexto.

Ejemplos

El directorio /tmp

475
Alice acaba de aprender que algunos de los procesos utilizan automáticamente /tmp como espacio
de borrador y quiere ver si algo de lo que ha hecho ha utilizado ese espacio. También quiere
probar si realmente puede crear archivos allí.

Para crear un archivo, Alice utilizará el comando touch.

[alice@station alice]$ cd /tmp


[alice@station tmp]$ ls
orbit-alice ssh-XXDg4ke3
[alice@station tmp]$ ls -l
total 8
drwx------ 2 alice alice 4096 Mar 16 08:04 orbit-alice
drwx------ 2 alice alice 4096 Mar 16 07:07 ssh-XXDg4ke3
[alice@station tmp]$ touch newfile
[alice@station tmp]$ ls -l
total 8
-rw-rw-r-- 1 alice alice 0 Mar 16 14:14 newfile
drwx------ 2 alice alice 4096 Mar 16 08:04 orbit-alice
drwx------ 2 alice alice 4096 Mar 16 07:07 ssh-XXDg4ke3

Después de cambiar a /tmp, Alice usa ls y ls -l para ver el contenido del directorio /tmp.
Aunque ls -l produce un listado largo, ella no está segura y ve su nombre de usuario tantas
veces que se convence de que algunos programas que ejecutó dejaron archivos en /tmp,
como le habían dicho antes. De hecho, tanto orbit-alice como ssh-XXDg4ke3 fueron colocados
allí cuando ella inició su entorno de escritorio.
Alice utiliza el comando touch para crear un nuevo archivo vacío llamado newfile en /tmp.
Como muchos de los comandos Linux cuando touch lo logra, lo hace de manera silenciosa
(sin ningun aviso en la pantalla). Alice verifica que touch sí funcionó con otro ls -l.

Búsqueda de comandos en /bin y /usr/bin

Hogan quiere ver si algunos de los comandos comunes que utiliza se encuentran en alguno de los
directorios de los comandos binarios /bin o /usr/bin. Decide probar cp, mozilla, cd y fdisk.

Hogan puede utilizar ls para buscar estos comandos, pero en su lugar quiere probar un nuevo
comando, which.

Uso sencillo:

which PROGRAM

Muestra el FQN del archivo del comando PROGRAM que se utilizará si el usuario ejecuta el
comando.

476
[hogan@station hogan]$ which cp
/bin/cp
[hogan@station hogan]$ which mozilla
/usr/bin/mozilla
[hogan@station hogan]$ which cd
/usr/bin/which: no cd in
(/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/hoga
n/bin:)
[hogan@station hogan]$ which fdisk
/usr/bin/which: no fdisk in (/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/
home/h
ogan/bin:)
[hogan@station hogan]$ ls /sbin
...
ether-wake ldconfig portmap usbmodules
extendfs lilo poweroff vboxd
fdisk logdump pppoe vgcfgbackup
...

Hogan ve que cp se encuentra en el directorio /bin, lo cual le parece posible ya que los archivos
en /bin son los archivos que los usuarios normales desearían que siempre estuvieran presentes en
el sistema.
Hogan encuentra mozilla (el navegador que escogió) en /usr/bin. Esto también parece estar bien
ya que los archivos en /usr/bin son archivos que un usuario normal podría querer que no siempre
estuviesen disponibles.
Hogan está sorprendido de los resultados de cd, lo cual parece decir que el comando cd no está
en el sistema. Estaba esperando ver una respuesta como /bin/cd. (¿Por qué?) Lo que Hogan no
sabe es que cd es un ejemplo de un comando interno, provisto por el comando de la shell bash.
Por otro lado, si revisara, encontraría bash en /bin.
Hogan también está sorprendido de los resultados de fdisk. Sabe que es un comando
importante, pero peligroso, utilizado para particionar discos y sólo debe estar disponible para el
superusuario así que estaba esperando una respuesta de /sbin. Incluso puede ver fdisk en /sbin
cuando lo examina utilizando ls. Al mirarlo más detenidamente, descubre que which ni siquiera
buscó fdisk en /sbin. Después Hogan aprenderá sobre la ruta de comandos y descubrirá el porqué
esto tiene perfecto sentido.

Ejercicios en línea

Exploración de directorios importantes Lab Exercise Objetivo: Explore algunas de las


características de los directorios importantes discutidas en este capítulo. Tiempo estimado: 15
minutos.

Configuración

En este ejercicio necesitará utilizar touch para crear archivos. Este comando se demostró en los
ejemplos de este capítulo. Necesitará utilizar which para ubicar los archivos de comando. Este
comando también se demostró en los ejemplos.

Especificaciones

1. Abra una nueva terminal o una nueva consola virtual (esto se necesita para la evaluación
de su trabajo en línea).

477
Quiere probar si en realidad puede utilizar touch para crear archivos en varios directorios.
Espera que esto funcione en su directorio de inicio y en /tmp, pero no en otros directorios.
Use el comando touch newfile.username (en donde el username se remplaza con su
nombre de usuario) en cada uno de los siguientes directorios.

a. ~
b. /tmp
c. /bin
d. /root

Claramente, cabe esperar que algunos de sus esfuerzos no den resultado. Regrese a su
directorio de inicio cuando haya terminado.

2. Utilizando which, determine el FQN del archivo del comando binario para cada uno de los
siguientes: pwd, ls y whoami. Ejecute cada uno de estos comandos de manera "cruda"
utilizando el FQN en el intérprete de comandos. Finalmente, ejecute exit, salga de la
terminal o de la consola virtual.

Cuando haya terminado, salga de su shell para que se guarde la historia de sus comandos en el
archivo ~/.bash_history.

Deliverables A title Question 1

1. Dos archivos llamados ~/newfile.username y /tmp/newfile.username, en donde username


es su nombre de cuenta primaria.

Possible Solution

La siguiente secuencia de comandos demuestra el uso de which y touch, y la ejecución de un


comando utilizando su referencia absoluta.

[student@station student]$ touch /tmp/newfile.student


[student@station student]$ which pwd
/bin/pwd
[student@station student]$ /bin/pwd
/home/student

478
Administración de archivos

Conceptos clave

• Se pueden crear archivos (o agregar) de una manera fácil utilizando el redireccionamiento


de la shell.
• El comando cp copia archivos.
• El comando mv mueve archivos.
• El comando rm borra archivos.
• Los archivos pueden ser "sobrescritos" como resultado de redireccionar, mover o copiar.

Discussion

Redirección

Muchos de los comandos producen salidas “visibles”. Normalmente, la salida se mostrará en la


pantalla. Por ejemplo, observe la salida de pwd para Julius:

[julius@station julius]$ pwd


/home/julius
[julius@station julius]$

A Linux le gusta pensar que todo es un archivo. En el ejemplo anterior, pwd envió la salida al
archivo de salida estándar, o STDOUT, el cual es por defecto la pantalla para los usuarios que han
iniciado sesión en el sistema.

Una de las características de la shell de comandos bash es que la salida que normalmente es
dirigida a la pantalla a través de STDOUT, también puede ser redireccionada a algún otro archivo.
Esto se hace utilizando el símbolo especial de redireccionamiento, , como se muestra en este
ejemplo:

[julius@station julius]$ ls
[julius@station julius]$ pwd > results.txt
[julius@station julius]$ ls
results.txt

En este ejemplo, los resultados usuales del comando fueron dirigidos al archivo results.txt, creando
el archivo durante el proceso. Un comando útil que nos puede servir para verificar lo que ha
pasado es el comando cat (concatenar).

Uso:

cat [OPCIONES] [ARCHIVO...]

ConcatenarARCHIVO(s) a la salida estándar.

479
El comando cat copia cada uno de los archivos listados a la salida estándar. Si se lista más de un
archivo, esto concatena efectivamente los archivos. Como para cualquier otro comando, esta salida
se mostrará en la pantalla por defecto, pero también se puede redireccionar a un archivo. Lo
utilizaremos para mostrar un archivo nombrando un sólo archivo y no redireccionando los
resultados.

[julius@station julius]$ pwd > results.txt


[julius@station julius]$ ls
results.txt
[julius@station julius]$ cat results.txt
/home/julius
Esta vez, Julius capturó la salida de pwd redireccionando los resultados a results.txt y después
mostró results.txt con cat.

Si el archivo ya existe, el redireccionamiento borrará y re-creará el archivo vacío y luego capturará


la nueva salida. Sin embargo, si se utiliza un doble símbolo (>>) la nueva salida se añadirá al
archivo. Si se utiliza >> y el archivo destino no existe, éste se crea como si se hubiese utilizado >.
El símbolo > es un ejemplo de un meta-caracter de shell, es decir, un símbolo con significado
especial que la shell bash ve e interpreta antes de actuar sobre el resto del comando. Hay muchos
de éstos como veremos en las próximas lecciones y todos requieren atención.

El comando más sencillo de todos que produce una salida visible es echo. El comando echo toma
cualquier texto que se teclee como parte del comando y lo repite a la salida estándar (usualmente
la pantalla). Este comando sencillo junto con el redireccionamiento, se puede utilizar para crear
archivos de texto.

Uso:

echo [OPCIONES] [STRING...]

Repite la cadena de caracteres en la salida estándar.

Example 1:

[julius@station julius]$ echo Hello > greetings.txt


[julius@station julius]$ echo How are you >> greetings.txt
[julius@station julius]$ cat greetings.txt
Hello
How are you

Ejemplo 2:

[julius@station julius]$ ls
[julius@station julius]$ pwd > results.txt
[julius@station julius]$ cat results.txt
/home/julius
[julius@station julius]$ ls >> results.txt
[julius@station julius]$ cat results.txt
/home/julius
results.txt

480
Copie archivos con cp

Se pueden crear duplicados de archivos con el comando cp (del inglés copy).

Uso:

cp [OPCIONES] {FUENTE} {DESTINO}

cp [OPCIONES] {FUENTE...} {DIRECTORIO}

De la primera manera, se hace una copia del archivo FUENTE como DESTINO. De la segunda
manera, se pueden copiar uno o más archivos al mismo tiempo a un directorio. Se hace una copia
del archivo FUENTE, ..., en el DIRECTORIO y se nombra DIRECTORIO/FUENTE, .... Con las
opciones apropiadas (no se discutirán aquí - intente man cp), puede copiar árboles de
subdirectorios completos de una sola vez.

Ejemplos:

1. Haga una copia de mysong.midi y nombre la copia backup.midi:

cp mysong.midi backup.midi

2. Haga una copia de mynovel.txt en /tmp:

cp mynovel.txt /tmp

El archivo resultante se llamará /tmp/mynovel.txt.

3. Copie los archivos songs.tar y novels.tgz en el directorio /tmp:

cp songs.tar novels.tgz /tmp

Nombre los archivos resultantes /tmp/songs.tar y /tmp/novels.tgz.

4. Haga una copia de webpage.html desde su directorio de inicio a su directorio actual:

cp ~/webpage.html .

El archivo resultante se llamará ./webpage.html.

Mueva/renombre archivos con mv

Puede mover archivos de un directorio a otro o de un nombre a otro (renombrarlos) con el


comando mv (mover).

Uso:

mv [OPCION...] {FUENTE} {DESTINO}

481
mv [OPCION...] {FUENTE...} {DIRECTORIO}

. En la primera forma, el archivo FUENTE es renombrado como DESTINO. De la segunda forma,


uno o más archivos pueden ser movidos a un directorio al mismo tiempo. Los archivos
FUENTE, ..., se mueven al DIRECTORIO y se nombran DIRECTORIO/FUENTE, .... FUENTE
puede ser un directorio, en tal caso el directorio se mueove o se renombra.

El comando mv es particularmente interesante , pues la manera en que funciona encierra un hecho


crítico sobre los sistemas de archivos Linux: Linux trata el nombre de archivo como algo
completamente diferente del contenido del archivo. Aunque el comando mv proviene de la palabra
"mover," de hecho mv raras veces mueve datos. En su lugar, el sistema de archivos simplemente
graba un cambio de nombre. Si el nombre cambia de /somedir/somefile a /somedir/newname,
vemos esto como una "renombramiento" del archivo. Si el nombre cambia de /somedir/somefile a /
newdir/somename, vemos esto como "mover" el archivo. Si el nombre cambia de /somedir/somefile
a /newdir/newname, vemos esto como un cambio doble, mover y renombrar. Pero para Linux todos
estos son la misma cosa, un cambio en el FQN del archivo.

Ejemplos:

1. Renombre mysong.midi como backup.midi:

mv mysong.midi backup.midi

2. Mueva mynovel.txt a /tmp:

mv mynovel.txt /tmp

El archivo resultante se llamará /tmp/mynovel.txt.

3. Mueva songs.tar y novels.tgz a /tmp:

mv songs.tar novels.tgz /tmp

Nombre los archivos resultantes /tmp/songs.tar y /tmp/novels.tgz.

4. Mueva webpage.html de su directorio de inicio al directorio de trabajo actual:

mv ~/webpage.html .

El archivo resultante se llamará ./webpage.html.

5. Renombre el subdirectorio html del directorio actual de trabajo a public_html:

mv html public_html

Renombra ./html como ./public_html, asumiendo que ./public_html no existe de antemano -


vea el siguiente ejemplo.

6. Su cwd es su directorio de inicio. Tiene dos subdirectorios ~/images y ~/html. Mueva el


directorio images al directorio html:

482
mv images html

El directorio resultante se llamará ~/html/images. Observe la similitud entre este ejemplo y


el anterior. La diferencia crítica es que en este caso el directorio destino ~/html ya existía,
asi que mv movió el directorio fuente dentro (bajo) el directorio destino. En el ejemplo
anterior, el directorio destino no existía aún, así que mv renombró el directorio fuente con
el nuevo nombre.

Suprima (borre) archivos con rm

Se pueden suprimir (eliminar, borrar) archivos con el comando rm (remover).

Uso:

rm [OPCIONES] {ARCHIVO...}

Suprime el (los) ARCHIVO(s) del sistema de archivos. Técnicamente, desenlaza el (los)


ARCHIVO(s), una diferencia que se aclarará más adelante. Con las opciones apropiadas (no
discutidas aquí - intente ejecutar man rm) se pueden borrar árboles de subdirectorios de una sola
vez.

Note

rm no puede borrar un directorio a menos de que se utilicen opciones especiales del


comando. Hay un comando especial para este propósito: rmdir.
Warning

Sí, el comando rm puede suprimir árboles enteros de directorios de una sola vez. En las
manos del susperusuario puede borrar el contenido completo de un sistema de archivos -- no
siempre es lo que se pretende hacer.
Warning

La documentación para rm incluye la siguiente frase: "Observe que si utiliza rm para suprimir
un archivo, usualmente es posible recuperar el contenido de ese archivo." Aunque esto pueda
ser verdad requiere un nivel de habilidad más allá del proposito de este curso, así que para
todos los propósitos prácticos, debe tratar este comando como si no fuese reversible.

Ejemplos:

1. Borrar mysong.midi:

rm mysong.midi

2. Borre songs.tar y novels.tgz:

rm songs.tar novels.tgz

3. Borre photos.html de su directorio de inicio:

rm ~/photos.html

483
Sobrescribir archivos (¡uy!)

Algunas de las advertencias incluídas en la sección anterior insinúan algunos de los comandos
potencialmente peligrosos como cp, mv y rm. Infortunadamente, aunque por lo general, mientras
vemos pasar las corrientes del rio, con frecuencia olvidamos las rocas que se encuentran bajo el
agua y Linux también es el mismo caso. Este es el precio que hay que pagar por el poder de un
sistema operativo como Linux. En esta sección resaltamos uno de esos peligros: sobrescribir
archivos.

La redirección de comandos con > y los comandos cp y mv, pueden nombrar los archivos destino.
Normalmente, estos son nombres de archivos nuevos y los comandos crean los archivos. Pero si
se nombra un archivo existente como destino de la redirección, cp o mv, el archivo existente será
destruido sin advertencia. Esto se conoce como sobrescribir un archivo. Puesto que este problema
puede llegar a ser tan sorprendentemente sutil para un nuevo usuario, le vamos a mostrar varios
ejemplos.

Ejemplo 3:

[julius@station julius]$ pwd > file1


[julius@station julius]$ cat file1
/home/julius
[julius@station julius]$ ls > file1
[julius@station julius]$ cat file1
mycwd
Aquí no hay muchas sorpresas si ha puesto atención -- simplemente observe la manera en que la
segunda redirección remplazó el contenido anterior de file1 sin ningún mensaje de advertencia. El
archivo file1 se ha sobrescrito.

Ejemplo 4:

[julius@station julius]$ touch file1


[julius@station julius]$ ls
file1
[julius@station julius]$ pwd > file2
[julius@station julius]$ ls
file1 file2
[julius@station julius]$ cat file2
/home/julius
[julius@station julius]$ mv file2 file1
[julius@station julius]$ ls
file1
[julius@station julius]$ cat file1
/home/julius

Aquí tampoco hay sorpresas -- observe como mv remplazó el contenido previo de file1 sin ninguna
advertencia. De nuevo, file1 ha sido sobrescrito. cp habría remplazado file1 de la misma manera.

Para poder entender completamente nuestro último ejemplo, necesitamos aprender un poco más
acerca de redireccionamiento. En particular, necesitamos aprender cuándo se sucede la
redirección.

484
Ejemplo 5:

[julius@station julius]$ touch file1


[julius@station julius]$ ls
file1
[julius@station julius]$ ls > file2
[julius@station julius]$ ls
file1 file2
[julius@station julius]$ cat file2
file1 file2

¿Por qué file2 lista file1 y file2, cuando el primer ls sólo muestra file1? Respuesta: debido a la
secuencia en que tuvieron lugar los pasos críticos. Evento 1: bash vio la redirección al archivo file2
y lo creó como un archivo vacio (vea la discusión anterior sobre redireccionamiento). Evento 2: ls
generó un listado de archivos mostrando el archivo creado anteriormente file1 y el que se acaba de
crear file2. Evento 3: la salida de ls se envió a file2.

Ejemplo 6:

[julius@station julius]$ pwd > mycwd


[julius@station julius]$ cat mycwd
/home/julius
[julius@station julius]$ cp mycwd mycwd
cp: `mycwd' and `mycwd' are the same file
[julius@station julius]$ cat mycwd
/home/julius
[julius@station julius]$ cat mycwd > mycwd
cat: mycwd: input file is output file
[julius@station julius]$ cat mycwd
[julius@station julius]$

Esto necesita una explicación. Primero, Julius crea mycwd usando pwd y presenta su contenido
con cat. Después utiliza cp para tratar de copiar el archivo a sí mismo pero cp detecta el "error,"
muestra un mensaje y no hace nada (mv hubiese hecho lo mismo). El cat en la línea siguiente
verifica que mycwd no ha tenido cambios. Está bien hasta ahora. Sin embargo, la siguiente
secuencia produce una gran sorpresa. Julius usa cat con redireccionamiento para tratar de copiar
un archivo a sí mismo. cat también se queja de los archivos fuente (entrada) y del destino (salida)
al ser el mismo y pareciese que no hace nada. Pero el cat final de mycwd no produce ninguna
respuesta -- ¡el contenido del archivo se perdio! ¿Por qué? Debido a la secuencia en la que
tuvieron lugar los eventos. Evento 1: bash ve la redirección a un archivo que ya existe, borra el
archivo y lo re-crea vacío (vea la discusión anterior sobre redirección) -- mycwd es sobrescrito.
Evento 2: ya no importa lo que cat haga puesto que el archivo fuente mycwd ya ha sido destruído y
re-creado. Es demasiado tarde para evitar el error.

Existen algunas pocas opciones de comandos y características especiales de la shell de comando


que se pueden utilizar para mitigar este comportamiento de alguna manera, pero el objetivo de este
capítulo simplemente es aprender cómo funcionan estos comandos y en esta sección
específicamente, la manera como funcionan en archivos existentes. Esta es una característica no
un error que necesario entender y utilizar de manera correcta.

485
parent home

Ejemplos

Mover/Archivar un sitio web simple

Madonna intentó configurar un sitio web personal simple, pero después de terminar su ISP le dijo
que había puesto todos los archivos del sitio web en un directorio equivocado. Puso los archivos en
~/html y debieron haber sido puestos en ~/public_html. Necesita mover los archivos al directorio
correcto. Mientras lo hace, también necesita hacer una copia de seguridad de los archivos que se
encuentran en el directorio archive, por si acaso daña o borra accidentalmente uno de los archivos
en ~/public_html. El directorio archive ya existe.

[madonna@station madonna]$ ls
html archive
[madonna@station madonna]$ mv html public_html
[madonna@station madonna]$ cd public_html
[madonna@station public_html]$ ls
index.html photo.jpeg
[madonna@station madonna]$ cp index.html photo.jpeg ../archive

Para mover los archivos todo lo que Madonna tuvo que hacer fue renombrar el directorio. Para
hacer copias de seguridad utilizó la habilidad del comando cp para copiar más de un archivo a la
vez.

Mover un sitio web simple

Nero intentó configurar un sitio web personal simple, pero después de terminar su proveedor de
servicios de internet (ISP por sus siglas en inglés) le dijo que habia puesto todos los archivos del
sitio web en el directorio equivocado. Puso los archivos en su directorio de inicio y deben estar en
~/public_html. Necesita mover los archivos al directorio correcto. Su problema es más complicado
que el de Madonna, puesto que no puede renombrar un subdirectorio simplemente. El directorio
public_html fue creado por su ISP.

[nero@station nero]$ ls
index.html photo1.jpeg photo2.jpeg public_html
[nero@station nero]$ mv index.html photo1.jpeg photo2.jpeg public_html
[nero@station nero]$ ls
public_html
[nero@station nero]$ cd public_html
[nero@station public_html]$ ls
index.html photo1.jpeg photo2.jpeg

Para mover los archivos Nero utilizó la habilidad del comando mv para mover más de un archivo a
la vez.

Suprimir robots.txt

Elvis nota un archivo en su directorio ~/public_html que no reconoce, un archivo llamado robots.txt.
Decide borrarlo.

486
[elvis@station elvis]$ ls
public_html
[elvis@station elvis]$ ls public_html
index.html robots.txt
[elvis@station elvis]$ rm public_html/robots.txt
[elvis@station elvis]$ ls public_html
index.html

Ejercicios en línea

Crear un sitio web Lab Exercise Objetivo: Utilizar la redirección, cp y mv para crear un sitio web
simple y archivar el sitio web. Tiempo estimado: 15 minutos.

Configuracion

En este ejercicio necesitará trabajar con los directorios ~/html y ~/archive. Inicie sesión con su
cuenta y utilice los siguientes comandos para crear estos dos directorios:

[student@station student]$ mkdir ~/html


[student@station student]$ mkdir ~/archive

Especificaciones

Quiere crear un sitio web personal simple utilizando las técnicas que se demostraron en la sección
de ejemplos de este capítulo.

1. Cree una página web "en construcción" en ~/index.html.


2. Mueva este archivo a ~/html.
3. Renombre el directorio html como public_html.
4. Haga una copia de su archivo index.html en ~/archive.

Note

La página web resultante puede ser o no visible con un navegador, dependiendo de las
características adicionales de la configuración de su sistema. Su instructor le dirá si puede
ver los resultados de su trabajo de este modo.

Deliverables A title Question 1

Dos archivos ~/public_html/index.html y ~/archive/index.html, cada uno de los cuales tiene un


contenido idéntico (el texto "en construcción" posiblemente con una etiqueta HTML).

Possible Solution

The following sequence of commands provides one possible solution to this exercise.

487
[student@station student]$ mkdir html archive
[student@station student]$ echo '<h1>' > index.html
[student@station student]$ echo 'Under construction' >> index.html
[student@station student]$ echo '</h1>' >> index.html
[student@station student]$ mv index.html html
[student@station student]$ mv html public_html
[student@station student]$ cp public_html/index.html archive
[student@station student]$ ls public_html
index.html
[student@station student]$ ls archive
index.html

Investigar la opción "noclobber" Lab Exercise Objetivo: Investigar las consecuencias de la opción
bash "noclobber". Estimated Time: 10 mins.

Especificaciones

Desea investigar las consecuencias del sobrescribir archivos y de la opción bash "noclobber".

1. Abra una nueva terminal o una nueva consola virtual (esto se necesita para la evaluación
de su trabajo en línea).
2. Cree un archivo llamado source que incluya la palabra "fuente" y un archivo llamado target
que incluya la palabra "destino."
3. Use cp para sobrescribir target con source. Verifique el efecto con cat.
4. Re-cree target.
5. Sobrescriba target de nuevo haciendo cat en source y redireccionando la salida. Verifique
los resultados.
6. Active la opción bash "noclobber" con el siguiente comando mágico:

[student@station student]$ set -o noclobber

7. Ensaye de nuevo ambos tipos de sobrescritura y observe los resultados.


8. Desactive la opción bash "noclobber" con el siguiente comando mágico:

[student@station student]$ set +o noclobber

9. Termine la sesión en la terminal o en la consola virtual.

Deliverables A title Question 1

1. Un archivo ~/.bash_history que tiene el récord de sus opciones de activación y


desactivación de la opción noclobber.

Possible Solution

The following sequence of commands provides one possible solution to this exercise.

488
[student@station student]$ echo source > source
[student@station student]$ echo target > target
[student@station student]$ cp source target
[student@station student]$ cat target
source

[student@station student]$ echo target > target


[student@station student]$ cat source > target
[student@station student]$ cat target
source
[student@station student]$ echo target > target

[student@station student]$ set -o noclobber


[student@station student]$ cp source target
[student@station student]$ cat target
source

[student@station student]$ echo target > target


[student@station student]$ cat source > target
-bash: target: cannot overwrite existing file

[student@station student]$ set +o noclobber


[student@station student]$ exit

489
Administración de directorios

Conceptos clave

• Se puede examinar el contenido de árboles de directorios completos con el comando ls -R.


• El comando mkdir crea directorios.
• El comando rmdir borra directorios (vacíos).
• cp -r copia directorios recursivamente.
• rm -r suprime directorios recursivamente.

Discussion

Creación de directorios (nuevos, vacíos): mkdir

La organización de archivos dentro de directorios requiere la habilidad para crear los directorios
que necesita. En Linux, el comando para hacer un directorio nuevo es el comando mkdir (del
inglés make directory).

Uso:

mkdir [OPCIONES] {DIRECTORIO...}

Crea el(los) DIRECTORIO(s) si no existe(n). Falla y emite un mensaje de error si uno o más de los
DIRECTORIO(s) existen, pero los nuevos directorios restantes son aún creados.

Para crear un subdirectorio ~/public_html Elvis puede proceder así:

[elvis@station elvis]$ ls
[elvis@station elvis]$ mkdir public_html
[elvis@station elvis]$ ls
public_html

Después Elvis puede crear un subdirectorio de public_html:

[elvis@station elvis] ls public_html


[elvis@station elvis] mkdir public_html/images
[elvis@station elvis] ls public_html
images

Sin embargo, observe que por defecto, mkdir no creará un subdirectorio si el directorio padre no
existe de antemano:

[elvis@station elvis] ls work


ls: work: No such file or directory
[elvis@station elvis] mkdir work/spreadsheets
mkdir: cannot create directory `work/spreadsheets': No such file or
directory

490
Sólo si Elvis utiliza mkdir -p (como 'padre') puede crear un árbol de directorios completo de una
sola vez:

[elvis@station elvis] ls work


ls: work: No such file or directory
[elvis@station elvis] mkdir -p work/spreadsheets
[elvis@station elvis] mkdir -p work/images/logos
[elvis@station elvis] mkdir -p work/images/advertising
[elvis@station elvis] ls work
images spreadsheets
[elvis@station elvis] ls work/images
advertising logos

A title

Listado de árboles de directorios

Por ahora, tenga en cuenta que cuando se da un directorio como argumento al comando ls, éste
lista el contenido del directorio. ¿Pero qué pasa si el directorio contiene otros directorios? Por
defecto, el comando ls sólo mostrará el contenido del directorio del nivel más alto. Si también
quiere que el comando ls liste los subdirectorios, puede añadir la opción -R.

Cuando un comando se repite a través de una estructura, operando en cada elemento de la


estructura de la misma manera que en el elemento superior, se dice que el comando actúa de
modo recursivo. La opción -R especifica que el comando ls debería listar con recursion.

Por ejemplo, hogan está explorando la configuración de red de la máquina y sospecha que el
directorio /etc/sysconfig/networking es un directorio importante. Para poder descubrir los archivos y
los subdirectorios que contiene, hogan lista el contenido del directorio de modo recursivo.

[hogan@station hogan]$ ls -R /etc/sysconfig/networking/


/etc/sysconfig/networking/:
devices ifcfg-lo profiles

/etc/sysconfig/networking/devices:
ifcfg-eth0

/etc/sysconfig/networking/profiles:
default netup

/etc/sysconfig/networking/profiles/default:
hosts ifcfg-eth0 network resolv.conf

/etc/sysconfig/networking/profiles/netup:
hosts ifcfg-eth0 network resolv.conf

ls -R también se puede combinar con cualquiera de las opciones de línea de comando vistas
anteriormente, tales como ls -sR para incluir los tamaños de archivos, o ls -lR para incluir los
atributos de archivos.

491
Borrar directorios (vacíos): rmdir

El comando para borrar un directorio es rmdir. (remover directorio).

Uso:

rmdir [OPCIONES] {DIRECTORIO...}

Suprime el (los) DIRECTORIO(s) si están vacíos. Emite un mensaje de error si uno o más del (los)
DIRECTORIO(s) no está(n) vacío(s), pero los directorios que quedan (vacíos) se borran. Tenga en
cuenta que un directorio que contiene sólo un subdirectorio no se considera como vacío.

Para borrar su subdirectorio ~/public_html/images Elvis puede proceder así:

[elvis@station elvis]$ ls
public_html
[elvis@station elvis]$ rmdir public_html/images
[elvis@station elvis]$ ls
[elvis@station elvis]$

Como lo señalamos antes, observe de nuevo que los comandos tales como mkdir y rmdir
funcionan de manera silenciosa. Como dice el dicho el silencio es oro.

Listado de árboles de directorios

Por ahora, tenga en cuenta que cuando se da un directorio como argumento al comando ls, éste
lista el contenido del directorio. ¿Pero qué pasa si el directorio contiene otros directorios? Por
defecto, el comando ls sólo mostrará el contenido del directorio del nivel más alto. Si también
quiere que el comando ls liste los subdirectorios, puede añadir la opción -R.

Cuando un comando se repite a través de una estructura, operando en cada elemento de la


estructura de la misma manera que en el elemento superior, se dice que el comando actúa de
modo recursivo. La opción -R especifica que el comando ls debería listar con recursion.

Por ejemplo, a elvis le gustaría tener una lista de archivos y directorios más detallada en su
directorio ~/work. Recuerde que elvis antes tenía que emitir un comando ls por separado para cada
subdirectorio de ~/work con el fin de ver el contenido de subdirectorio. Ahora en su lugar, puede
utilizar la opción ls -R.

[elvis@station elvis]$ ls -R work


work/:
images spreadsheets

work/images:
advertising logos

work/images/advertising:

work/images/logos:

work/spreadsheets:

492
Observe que el comando anterior mostrará archivos así como directorios. En este ejemplo,
casualmente no hay ningún archivo para mostrar.

ls -R también se puede combinar con cualquiera de las opciones de línea de comando vistas
anteriormente, tales como ls -sR para incluir los tamaños de archivos, o ls -lR para incluir los
atributos de archivos.

Copiar árboles de directorios: cp -r

En el capítulo anterior cuando se introdujo cp, señalamos que con las opciones correctas el
comando cp serviría para copiar árboles de directorios completos. Aquí analizamos dicha opción: -r
(de recursive) (Muchos de los comandos tienen la opción de actuar de modo recursivo es decir,
recorriendo todas las ramas de un sub-árbol de directorio, actuando en cada subdirectorio a su
vez).

Considere la siguiente estructura en el directorio de inicio de Hogan:

Figure 1. Estructura del directorio antes de copiar

-- html
|
hogan -- website -- -- forms
|
| -- song1.midi
| |
| -- songs --
| | |
| | -- song2.midi
| |
-- media --
| -- picture1.png
| |
-- photos--
|
-- picture2.png
Aunque este árbol de directorios contiene muchas ramas y archivos, se puede copiar con una sóla
orden:

[hogan@station hogan]$ cp -r website archive

Figure 2. Estructura del directorio después de copiar

493
-- html
|
-- website -- -- forms
| |
| | -- song1.midi
| | |
| | -- songs --
| | | |
| | | -- song2.midi
| | |
| -- media --
| | -- picture1.png
| | |
hogan -- -- photos--
| |
| -- picture2.png
|
| -- html
| |
-- archive -- -- forms
|
| -- song1.midi
| |
| -- songs --
| | |
| | -- song2.midi
| |
-- media --
| -- picture1.png
| |
-- photos--
|
-- picture2.png

Recuerde la diferencia en el comportamiento de cp cuando el último argumento es un directorio


existente: se hace una copia del (los) archivo(s) fuente(s) dentro del directorio destino. En la
demostración anterior el directorio archive no existía previamente así que fue creado. Pero si el
directorio archive ya hubiese existido el efecto hubiera sido diferente.

Figure 3. Estructura del directorio antes de copiar

494
-- html
|
-- website -- -- forms
| |
| | -- song1.midi
| | |
| | -- songs --
| | | |
| | | -- song2.midi
hogan -- | |
| -- media --
| | -- picture1.png
| | |
| -- photos--
| |
| -- picture2.png
-- archive

Hogan usa exactamente el mismo comando que antes para copiar:

[hogan@station hogan]$ cp -r website archive

Figure 4. Estructura del directorio después de copiar con cp -r websitearchive

495
-- html
|
-- website -- -- forms
| |
| | -- song1.midi
| | |
| | -- songs --
| | | |
| | | -- song2.midi
| | |
| -- media --
| | -- picture1.png
| | |
hogan -- -- photos--
| |
| -- picture2.png
|
| -- html
| |
-- archive -- website -- -- forms
|
| -- song1.midi
| |
| -- songs --
| | |
| | -- song2.midi
| |
-- media --
| --
picture1.png
| |
-- photos--
|
--
picture2.png

En esta segunda demonstración, el directorio website es recreado dentro del directorio archive.

Borrar árboles de directorios: rm -r

En el capítulo anterior cuando se introdujo rm, señalamos que con las opciones correctas, el
comando rm puede borrar por completo árboles de directorios. De nuevo, para cp la opción es -r
(derecursivo).

Considere la siguiente estructura en el directorio de inicio de Hogan:

Figure 1. Estructura del directorio antes de borrarlo

496
-- html
|
hogan -- website -- -- forms
|
| -- song1.midi
| |
| -- songs --
| | |
| | -- song2.midi
| |
-- media --
| -- picture1.png
| |
-- photos--
|
-- picture2.png

Si Hogan quisiera borrar el sub-árbol media, podría utilizar un sólo comando:

[hogan@station hogan]$ rm -r website/media

Figure 2. Estructura del directorio después de borrar

-- html
|
hogan -- website --
|
-- forms

Vale la pena anotar una vez más que, en general, el borrar archivos no tiene reversa. Si se utiliza
de manera negligente el comando rm -r es muy peligroso.

Ejemplos

Hacer una copia de seguridad de un árbol de directorios

El usuario hogan ha estado trabajando bastante en un reporte, el cual tiene varios archivos que ha
organizado en subdirectorios bajo un directorio llamado report.

497
report/
|-- chapter01/
| |-- figures/
| | |-- image01.png
| | `-- image02.png
| |-- section01.html
| `-- section02.html
`-- chapter02/
|-- figures/
| |-- image01.png
| `-- image02.png
|-- section01.html
`-- section02.html

4 directories, 8 files

Está a punto de utilizar un corrector ortográfico para chequear y remplazar las palabras mal
escritas. Ya que esta es la primera vez que utiliza este corrector ortográfico, quiere hacer una copia
de seguridad de su trabajo antes de continuar. Primero trata de hacer una copia de seguridad con
el comando cp.

[hogan@station hogan]$ cp report report.bak


cp: omitting directory `report'

Al darse cuenta de su error añade la opción -r para decirle al comando cp que copie de modo
recursivo.

[hogan@station hogan]$ cp -r report report.bak

Ahora el contenido del directorio report es copiado de modo recursivo al directorio report.bak.

498
.
|-- report/
| |-- chapter01/
| | |-- figures/
| | | |-- image01.png
| | | `-- image02.png
| | |-- section01.html
| | `-- section02.html
| `-- chapter02/
| |-- figures/
| | |-- image01.png
| | `-- image02.png
| |-- section01.html
| `-- section02.html
`-- report.bak/
|-- chapter01/
| |-- figures/
| | |-- image01.png
| | `-- image02.png
| |-- section01.html
| `-- section02.html
`-- chapter02/
|-- figures/
| |-- image01.png
| `-- image02.png
|-- section01.html
`-- section02.html

10 directories, 16 files

Una vez que hogan haya usado el corrector ortográfico y que esté contento con los resultados,
quiere suprimir el directorio de copia de seguridad report.bak. Primero utiliza el comando rmdir.

[hogan@station hogan]$ rmdir report.bak/


rmdir: `report.bak/': Directory not empty

Recuerde que rmdir sólo funciona en directorios vacíos así que en su lugar utiliza rm -r.

[hogan@station hogan]$ rm -r report.bak/


[hogan@station hogan]$ ls
report

Creación de una copia local de los archivos de ejemplo

El usuario ventura está interesado en programar con el lenguage python. Descubrió scripts de
muestra en el directorio /usr/share/doc/pygtk2-1.99.14/examples/. Le gustaría jugar con los scripts
para poder probar nuevas ideas, pero no tiene permiso de escritura en los archivos. Decide hacer
una copia local de los scripts.

499
[ventura@station ventura]$ cp -r /usr/share/doc/pygtk2-1.99.16/examples/ .
[ventura@station ventura]$ ls -R examples/
examples/:
atk gl glade gobject ide neil pango pygtk-demo simple

examples/atk:
atk-demo.py

examples/gl:
cone.py dots.py gears.py README

examples/glade:
glade-demo.py README test.glade

examples/gobject:
properties.py signal.py

examples/ide:
break.xpm edit.py gtkdb.py next.xpm README step.xpm
browse.py edit.xpm gtkprof.py pyide.py return.xpm
...

Observe el uso del nombre de directorio . para referirse a "el directorio local". Cuando cp
recibe un directorio como destino (el último argumento) copia a ese directorio, preservando los
nombres de los archivos originales. En este caso, el directorio examples fue copiado al
directorio ..
El comando ls -R genera una lista recursiva de todo archivo en el directorio recién creado
example.

Ahora ventura tiene una copia a nivel local de los scripts python, lo que significa que los puede
modificar cuando quiera.

Ejercicios en línea

Administración de directorios Lab Exercise Objetivo: Listar, copiar, mover y suprimir directorios de
manera eficiente. Tiempo estimado: 20 minutos.

Especificaciones

Se le ha despertado el interés en gdm, una aplicación que proporciona la pantalla de inicio de


sesión gráfica de su sistema y desea explorar su diseño.

1. Utilice el comando ls (con las opciones apropiadas) para obtener un listado recursivo,
incluyendo tamaños (-s) del contenido del directorio /usr/share/gdm. Redireccione la salida
del comando a un archivo en su directorio de inicio llamado lsgdm.txt (debido a propósitos
evaluativos es importante que especifique el directorio como una referencia absoluta, por
ejemplo, no share/gdm).
2. Haga un copia (recursiva) del directorio /usr/share/gdm en su directorio de inicio. El
directorio copiado también se debe llamar gdm.
3. Haga una segunda copia del directorio recién creado en su directorio de inicio. gdm,
llamado gdm.bak.

500
4. Desde su copia de seguridad, suprima (de modo recursivo) el subdirectorio
gdm.bak/themes/circles.
5. De nuevo desde su copia de seguridad, mueva el subdirectorio gdm.bak/themes/Bluecurve
a su directorio de inicio (el directorio todavía se debe llamar Bluecurve).

Deliverables A title Question 1

1. Un archivo en su directorio de inicio llamado lsgdm.txt, el cual contiene la salida


redireccionada de un listado recursivo, inclyendo el tamaño del directorio /usr/share/gdm.
2. Un directorio en su directorio de inicio llamado gdm, el cual es una copia exacta del
directorio /usr/share/gdm.
3. Un directorio en su directorio de inicio llamado gdm.bak, el cual es una copia exacta del
directorio gdm, con el subdirectorio gdm.bak/themes/circles borrado y con el subdirectorio
gdm.bak/themes/Bluecurve/ movido a su directorio de inicio.
4. Un directorio en su directorio de inicio llamado Bluecurve, el cual es el resultado del
resultado anterior.

Limpieza

Los directorios creados son bastante grandes, así que si quiere conservar espacio de disco puede
borrarlos cuando haya terminado.

501
Nombres y comodines de archivos

Conceptos clave

• Los nombres de archivos pueden contener casi cualquier caracter a excepción de /.


• Aunque los nombres de archivos pueden contener casi cualquier caracter eso no significa
que deban contenerlos.
• Los archivos que comienzan con . son archivos "ocultos".
• Los caracteres *, ?, [...], y [^...] se pueden utilizar para encontrar los archivos con nombres
de archivos similares por medio de un proceso llamado "comodines de archivo".

Discussion

Nombres de archivo

Muchos sistemas operativos restringen el número y tipo de caracteres que se pueden utilizar al
nombrar archivos. En Linux, virtualmente cualquier caracter imprimible se puede utilizar en el
nombre de archivo y los nombres pueden ser casi de cualquier longitud.

Los nombres de archivos de Linux pueden tener hasta 255 caracteres, excluyendo cualquier
componente de directorio. Cuando se utiliza en un comando, un nombre de archivo absoluto o
relativo, incluyendo los componentes del directorio, pueden tener hasta de ¡4095 caracteres! Esto
permite que los nombres de archivo y directorios puedan ser bastante descriptivos.

Los nombres de archivos de Linux pueden contener cualquier caracter imprimible (y algunos que
no lo son) a excepción de la barra oblicua /. Esta barra no puede ser parte del nombre de archivo,
puesto que es el caracter utilizado para separar los componentes del nombre de un directorio en un
nombre relativo o completamente calificado. Como la mayoría de los caracteres "inusuales" son
meta-caracteres de shell, deben estar protegidos entre comillas para poderlos utilizar en un nombre
de archivo:

[julius@station julius]$ touch 'a and b'


[julius@station julius]$ touch '"'
[julius@station julius]$ touch "'"
[julius@station julius]$ touch '!@#$%^&*()_+=-|\}]{[:;?>.<,~`'
[julius@station julius]$ ls
!@#$%^&*()_+=-|\}]{[:;?>.<,~` ' " a and b
[julius@station julius]$

Como lo puede ver, se crearon cuatro archivos con nombres un poco extraños.

Warning
El ejemplo anterior es sólo a manera de ilustración. Muchos de los caracteres utilizados en
este ejemplo son meta-caracteres shell, cuyo significado aún no se ha discutido aquí. Debe
evitar utilizar signos de puntuación en los nombres de archivos, pues si los utiliza de manera
inapropiada puede producir resultados desastrosos.

La advertencia anterior no se debe olvidar. En general, los nombres de archivos deben estar
compuestos de caracteres alfabéticos y numéricos (A-Z, a-z, 0-9) y signos de puntuación ._-+~

502
(punto, guión bajo, guión, más, tilde). Normalmente, los nombres de archivos deben iniciar con un
caracter alfanumérico o con un punto (vea la siguiente sección sobre archivos ocultos). Aunque
encontrará nombres de archivos con espacios incrustados no se recomienda utilizarlos.

Figure 1. Caracteres "seguros" para nombres de archivos

A-Z a-z 0-9 . _ - + ~


Aquí hay dos ejemplos que le mostrarán el daño que puede causar el uso de caracteres no-
significativos. Vamos a abusar de dos meta-caracteres de shell: el espacio y el signo mayor que.

Ejemplo 1: ¡Tenga cuidado con esos espacios!

[hogan@station hogan]$ mkdir bad dir


[hogan@station hogan]$ touch this and that
[hogan@station hogan]$ mv this and that bad dir
[hogan@station hogan]$ ls
dir

Hogan intenta crear un directorio llamado 'bad dir,' pero sin saber creó dos directorios, uno
llamado 'bad' y otro llamado 'dir'.
Después, Hogan trata de crear un archivo llamado 'this and that' con touch, pero en realidad
crea tres archivos llamados 'this', 'and', y'that'.
Ahora Hogan intenta mover el archivo que él cree que se llama 'this and that' al directorio que
el piensa que se llama 'bad dir', pero lo que hace es mover todos los cuatro 'directoriosthis',
'and', 'that', y 'bad' (tres archivos comunes y un directorio) al directorio dir.
Puesto que todos los comandos anteriores se ejecutaron "con éxito", sólo hasta este momento
Hogan se da cuenta de que algo ha salido mal.

Es obvio que, si Hogan hubiese encerrado entre comillas los nombres como se mostró en las notas
explicativas, las cosas hubiesen funcionado como él lo quería. Hecho que vale la pena recordar, ya
que encontrará nombres de archivos con espacios encrustados. En relación a esto, un nombre de
archivo que contiene espacios al principio y al final es legal, pero es muy difícil de identificar en un
listado de archivos.

Ejemplo 2: Una pequeña equivocación de dirección

[hogan@station hogan]$ mkdir bad- > dir


[hogan@station hogan]$ touch this
[hogan@station hogan]$ mv this bad- > dir
[hogan@station hogan]$ ls
bad- dir

Hogan finalmente decide evitar los espacios. Esta vez intenta crear un directorio llamado 'bad-
> dir' pero sin querer crea un directorio llamado 'bad-' y un archivo llamado 'dir' (¿por qué?).
Después Hogan crea un archivo llamado 'this' con touch. ¡Este paso lo hace bien!

Ahora Hogan trata de mover un archivo llamado 'this' al directorio que el piensa que se llama
'bad->dir,' pero en vez de lograr esto, mueve 'this' al directorio bad-, redireccionando la salida
(no hay ninguna) al archivo 'dir'.

503
De nuevo, sólo hasta ahora Hogan se da cuenta de que algo ha salido mal.

Como antes, si Hogan hubiese utilizado las comillas para encerrar los nombres de archivos, las
cosas habrían salido como él quería. Las comillas enmascaran una multitud de pecados, pero no
utilice esto como excusa para crear nombres de archivos inapropiados. Muchas de las tareas que
aún tenemos que aprender se hacen más fáciles si se utilizan nombres "normales" para los
archivos.

Archivos ocultos

Los nombres de archivos y directorios (recuerde un directorio es un tipo de archivo) que comienzan
por un punto son archivos "ocultos". Estos archivos no aparecen en los listados de directorio
producidos por ls a menos que se utilice la opción de comando especial -a (del inglés all) o a
menos que se especifique el punto inicial como parte del nombre. Se hace posible reducir la
aglomeración de elementos y la confusión manteniendo ciertos archivos" fuera de vista y de
consideración".

En la próxima sección aprenderemos a nombrar múltiples archivos por medio de una técnica
conocida como uso de "comodines". En general, los archivos ocultos tampoco aparecen en un
"comodín" a no ser que el punto inicial sea listado específicamente.

Aparte de ocultar el archivo, el punto inicial no tiene otra importancia y los archivos y directorios
ocultos se pueden utilizar como cualquiera de los otros.

[alice@station alice]$ mkdir .secret


[alice@station alice]$ touch sample
[alice@station alice]$ ls
sample
[alice@station alice]$ ls -a
. .. sample .secret
[alice@station alice]$ mv sample .secret
[alice@station alice]$ ls
[alice@station alice]$ ls .secret
sample
[alice@station alice]$ cd .secret
[alice@station .secret]$ ls
sample
[alice@station .secret]$

"Comodines"

Con frecuencia es necesario emitir un comando que actúe en más de un archivo. Los comandos
como cp -r y rm -r funcionan en sub-árboles enteros de directorios, sin embargo, Linux cuenta con
una manera más flexible de identificar grupos de archivos. La shell de comando bash trata algunos
de sus meta-caracteres especiales como comodines. Cuando bash lee la línea de comando, la
shell realiza un proceso llamado expansión de meta-caracteres o expansión de comodines, lo cual
genera una lista de nombres de archivos que coinciden con el patrón descrito por la expresión del
comodín y luego pasa la lista generada al comando. Esto se conoce comúnmente como
"comodines de nombres de archivos."

504
Table 1. Comodines

Caracter Efecto
* coincide con cero o más caracteres (a excepción del punto inicial)
? coincide exactamente con un caracter (a excepción del punto inicial)
[...] coincide exactamente con un caracter de la lista o rango
[^...] coincide exactamente con un caracter no incluido en la lista o rango

El uso de * y ? es más bien sencillo. Los comodines de listas son un poco más complicados, pero
también bastante poderosos y útiles.

El comodín de parentesis representa una lista de caracteres individuales. Por lo tanto, [aeiou]
coincide con cualquier vocal. Un rango contiguo de caracteres se puede representar utilizando un
guión como en [a-z] para el alfabeto en minúsculas. Una ^ inicial, niega la lista de manera que
[^aeiou] sea cualquier caracter menos una vocal. Un guión "real" se puede representar escapando
los caracteres utilizando una barra invertida (\) (más adelante se abordará este tema). Por lo tanto,
la expresión [a\-z] coincide con a, z o un guión sólamente. Se pueden mezclar caracteres
individuales y rangos. El patrón [A-Za-z0-9._\-+~] coincide con cualquiera de los caracteres
"seguros" de nombres de archivos mencionados anteriormente en la gráfica 5-1.

Suponga que el directorio actual contiene los siguientes archivos:

image1.jpg image10.jpeg page1.html page3.htm script1.pl


image2.jpg image11.jpeg page2.html page40.htm

La siguiente tabla ilustra el uso de estos comodines.

Table 2. Ejemplos de comodines

Patrón Genera la lista


* todos los archivos en la lista
*.html page1.html page2.html
page*.htm* page1.html page2.html page3.htm page40.htm
image?.* image1.jpeg image2.jpeg
[ps]* page1.html page2.html page3.htm page40.htm script1.pl
[^ps]* image1.jpeg image2.jpeg image10.jpeg image11.jpeg

Los comodines se pueden utilizar con cualquier comando que espera el nombre de un archivo. Por
ejemplo, el comando

[bob@station bob] mv *.htm public_html

es lo mismo que el comando

[bob@station bob] mv page3.htm page40.htm public_html

asumiendo que el directorio de inicio de Bob contiene los archivos listados anteriormente.

505
[Nota técnica: muchos de los comandos se comportan de manera diferente cuando no aparecen
archivos en la lista, contrario a cuando uno o más archivos se dan como parte del comando.
Entonces, ¿qué sucede en dicho comando si se utiliza un patron de comodín de modo que el
listado de archivos esté vacío? En el caso especial donde la shell bash intenta expandir una
expresión de comodín y no coincide con nada, ésta deja la expresión como parte del comando.
Esto se ilustra a continuación:

[bob@station bob]$ rm
rm: too few arguments
Try `rm --help' for more information.
[bob@station bob]$ rm z*
rm: cannot lstat `z*': No such file or directory

En el primer rm, el comando vio cero nombres de archivos y falló presentando un mensaje de
error. En la segunda versión, la shell no pudo generar una lista de nombres del patrón z* y por lo
tanto la cadena z*se envió a rm como el nombre de archivo mismo. Como Bob no tiene un archivo
llamado z* en su directorio, el comando falló con un mensaje diferente].

Ejemplos

Búsqueda de ese archivo de configuración

Alice estaba revisando recientemente el archivo de configuración del DNS (Servicio de Nombres de
Dominio), pero olvidó el nombre. Recuerda que el archivo terminaba en .conf. Con el fin de reducir
el número de archivos a tomar en consideración, utilizó los comodines para listar todos los archivos
en el directorio /etc terminados en .conf.

[alice@station images]$ ls /etc/*.conf


/etc/aep.conf /etc/lftp.conf /etc/pnm2ppa.conf
/etc/aeplog.conf /etc/libuser.conf /etc/pwdb.conf
/etc/cdrecord.conf /etc/logrotate.conf /etc/resolv.conf
/etc/esd.conf /etc/lpd.conf /etc/rndc.conf
/etc/fam.conf /etc/ltrace.conf /etc/scrollkeeper.conf
/etc/gpm-root.conf /etc/modprobe.conf /etc/sysctl.conf
/etc/grub.conf /etc/mtools.conf /etc/syslog.conf
/etc/host.conf /etc/named.conf /etc/updatedb.conf
/etc/initlog.conf /etc/nscd.conf /etc/updfstab.conf
/etc/jwhois.conf /etc/nsswitch.conf /etc/warnquota.conf
/etc/krb5.conf /etc/ntp.conf /etc/webalizer.conf
/etc/krb.conf /etc/pam_smb.conf /etc/wvdial.conf
/etc/ldap.conf /etc/pbm2ppa.conf /etc/xinetd.conf
/etc/ld.so.conf /etc/pine.conf /etc/yp.conf
Mirando un poco más reconoce el archivo de configuración resolv.conf.

Listado de bibliotecas estáticas

Bob ha estado aprendiendo la diferencia entre bibliotecas enlazadas estáticamente y


dinámicamente que los programas utilizan. El sabe que las bibliotecas enlazadas estática y
convencionalmente tienen el nombre de libalgo.a, en donde algo es el nombre de la biblioteca.
También sabe que las bibliotecas se encuentran por lo general en el directorio /usr/lib.

506
Cuando echa un vistazo a las bibliotecas estáticas instaladas en su sistema, encuentra cerca de
1000 archivos en el directorio /usr/lib. Para reducir el número de archivos a examinar trata de listar
todos los archivos terminados en a.

[bob@station bob]$ ls /usr/lib/*a


/usr/lib/liba2ps.a /usr/lib/libimlib-ps.a
/usr/lib/libacl.a /usr/lib/libimlib-tiff.a
/usr/lib/libanl.a /usr/lib/libimlib-xpm.a

...

/usr/lib/mozilla:
plugins

/usr/lib/samba:
vfs

Muchas de las líneas de este listado largo han sido borradas, pero se han dejado las suficientes
para ilustrar el problema, el "comodín" de bob no fue lo suficientemente específico y capturó
también algunos de los directorios terminados en a. Refinando un poco más la lista obtiene lo que
quiere.

[bob@station bob]$ ls /usr/lib/lib*.a


/usr/lib/liba2ps.a /usr/lib/libimlib-ps.a
/usr/lib/libacl.a /usr/lib/libimlib-tiff.a
/usr/lib/libanl.a /usr/lib/libimlib-xpm.a

...

/usr/lib/libimlib-jpeg.a /usr/lib/libz.a
/usr/lib/libimlib-png.a /usr/lib/libzvt.a
/usr/lib/libimlib-ppm.a

Luego, bob sospecha que las bibliotecas utilizadas con más frecuencia tienen nombres cortos y
eficientes (tal vez descriptivos). Procede a listar todas las bibliotecas que tengan nombres de una,
dos o tres letras.

507
[bob@station bob]$ ls /usr/lib/lib?.a
/usr/lib/libc.a /usr/lib/libl.a /usr/lib/libz.a
/usr/lib/libg.a /usr/lib/libm.a
[bob@station bob]$ ls /usr/lib/lib??.a
/usr/lib/libdl.a /usr/lib/libgd.a /usr/lib/librt.a
/usr/lib/libfl.a /usr/lib/libmp.a
[bob@station bob]$ ls /usr/lib/lib???.a
/usr/lib/libacl.a /usr/lib/libgdk.a /usr/lib/libosp.a
/usr/lib/librle.a
/usr/lib/libanl.a /usr/lib/libgif.a /usr/lib/libpam.a
/usr/lib/librpm.a
/usr/lib/libapm.a /usr/lib/libgmp.a /usr/lib/libpbm.a
/usr/lib/libSDL.a
/usr/lib/libbfd.a /usr/lib/libgpm.a /usr/lib/libpci.a
/usr/lib/libssl.a
/usr/lib/libbsd.a /usr/lib/libgtk.a /usr/lib/libpgm.a
/usr/lib/libttf.a
/usr/lib/libefs.a /usr/lib/libIDL.a /usr/lib/libpng.a
/usr/lib/libusb.a
/usr/lib/libesd.a /usr/lib/libnsl.a /usr/lib/libpnm.a
/usr/lib/libxml.a
/usr/lib/libgal.a /usr/lib/libogg.a /usr/lib/libppm.a
/usr/lib/libzvt.a

¿Hay alguna forma fácil de utilizar los comodines para que bob pudiese haber listado las
bibliotecas con uno, dos o tres caracteres de nombres con una sola expresión?

Listado de las páginas man

La usuaria alice descubrió que los archivos que contienen las páginas man se encuentran
instalados en el directorio /usr/share/man en los subdirectorios relacionanados con los capítulos de
las páginas man.

[alice@station man]$ ls /usr/share/man/


cs de_DE fr hu it man1 man3 man5 man7 man9 pl ru sv
de es fr_FR id ja man2 man4 man6 man8 mann pt_BR sk

Como usuaria regular del sistema, sabe que los capítulos que más le interesan son el 1, 5 y 7.
Utiliza una expresión con comodines para enumerar sólo el contenido de esos directorios.

[alice@station man]$ ls /usr/share/man/man[157]


/usr/share/man/man1:
:.1.gz pbmtolj.1.gz
[.1.gz pbmtoln03.1.gz
411toppm.1.gz pbmtolps.1.gz
a2p.1.gz pbmtomacp.1.gz

...

groff.7.gz wireless.7.gz
groff_char.7.gz x25.7.gz
groff_diff.7.gz

508
Si alice hubiese estado interesada en todas las páginas man de los capítulos numerados, pero no
en los capítulos impares "n" podría haber utilizado la expresión de rango con comodines.

[alice@station man]$ ls /usr/share/man/man[1-9]


/usr/share/man/man1:
:.1.gz pbmtolj.1.gz
[.1.gz pbmtoln03.1.gz
411toppm.1.gz pbmtolps.1.gz
a2p.1.gz pbmtomacp.1.gz

...

named-checkconf.8.gz zic.8.gz
named-checkzone.8.gz

/usr/share/man/man9:

Ejercicios en línea

Administración de archivos con comodines Lab Exercise Objetivo: Administrar archivos de modo
eficiente por medio del uso de comodines de archivo.Tiempo estimado: 20 minutos.

Especificaciones

Este laboratorio utilizará comodines de archivo para administrar un gran número de archivos que
tienen nombres vagamente estructurados. Todos los archivos se encuentran en el directorio
/usr/share/tcl8.4/encoding.

1. Cree los siguientes directorios en su directorio de inicio: cp_even, cp_mid, cp_thousand,


iso_mid, mac y xxxn.
2. Examine los archivos en el directorio /usr/share/tcl8.3/encoding. Copie todos los archivos
que comienzan con mac en el directorio mac.
3. Copie todos los archivos que comienzan con cp y que tengan un número par en el
directorio cp_even.
4. Copie todos los archivos que comienzan con cp y que tengan un número mayor a 1000 en
el directorio cp_thousand.
5. Copie todos los archivos que comienzan con cp y que tengan un número mayor a 800,
pero menor que 1000 en el directorio cp_mid.
6. Copie todos los archivos que comienzan con iso8859- y que tengan un número después
del guión entre 3 y 8 (inclusive) en el directorio iso_mid.
7. Copie todos los archivos cuyos primeros cuatro caracteres estén compuestos de
exactamente tres letras seguidas por un número dentro del directorio xxxn.

Deliverables A title Question 1

Si ha realizado el ejercicio correctamente, debe tener los seis directorios con los siguientes
archivos.

509
[bob@station bob]$ ls *
cp_even:
cp1250.enc cp1256.enc cp852.enc cp864.enc cp932.enc
cp1252.enc cp1258.enc cp860.enc cp866.enc cp936.enc
cp1254.enc cp850.enc cp862.enc cp874.enc cp950.enc

cp_mid:
cp850.enc cp857.enc cp862.enc cp865.enc cp874.enc cp949.enc
cp852.enc cp860.enc cp863.enc cp866.enc cp932.enc cp950.enc
cp855.enc cp861.enc cp864.enc cp869.enc cp936.enc

cp_thousand:
cp1250.enc cp1252.enc cp1254.enc cp1256.enc cp1258.enc
cp1251.enc cp1253.enc cp1255.enc cp1257.enc

iso_mid:
iso8859-3.enc iso8859-5.enc iso8859-7.enc
iso8859-4.enc iso8859-6.enc iso8859-8.enc

mac:
macCentEuro.enc macDingbats.enc macJapan.enc macThai.enc
macCroatian.enc macGreek.enc macRoman.enc macTurkish.enc
macCyrillic.enc macIceland.enc macRomania.enc macUkraine.enc

xxxn:
big5.enc iso8859-13.enc iso8859-2.enc iso8859-7.enc jis0212.enc
iso2022.enc iso8859-14.enc iso8859-3.enc iso8859-8.enc koi8-r.enc
iso2022-jp.enc iso8859-15.enc iso8859-4.enc iso8859-9.enc koi8-u.enc
iso2022-kr.enc iso8859-16.enc iso8859-5.enc jis0201.enc ksc5601.enc
iso8859-10.enc iso8859-1.enc iso8859-6.enc jis0208.enc

sugerencias

El siguiente comando copiaría los archivos que coinciden con el primer criterio (asumiendo que el
directorio de trabajo actual es el directorio de inicio de Bob).

510
Examen de archivos

Conceptos clave

• El comando file muestra el tipo de archivo


• El comando cat muestra el contenido de un archivo
• Los comandos more y less "hojean" através de un archivo, una pantalla completa a la vez.
• Los comandos head y tail presentan las primeras o las últimas líneas de un archivo.
• En el entorno gráfico X se puede utilizar nautilus para examinar archivos de texto.

Discussion

Ver archivos

Linux ofrece varios comandos para examinar archivos y su contenido. Esta lección aborda algunas
de las herramientas más utilizadas.

El comando file

El contenido de cualquier archivo dado puede ser ASCII (texto plano, HTML, scripts de shell,
código fuente del programa, etc.) o binario (un ejecutable compilado, un archivo, comprimido,
audio, etc.).

Los comandos analizados en este capítulo son sólo para uso en archivos ASCII, el intentar usarlos
con archivos binarios puede generar problemas un poco molestos (como pantallas llenas de
caracteres extraños) o hasta problemas mayores (bloqueando la terminal). Esto se debe a que los
archivos binarios pueden contener códigos binarios arbitrarios y algunos de estos códigos tienen
un significado especial cuando se (mal )interpretan como texto ASCII. Por lo tanto, es una buena
idea revisar el tipo de archivo de cualquier archivo que usted no reconozca utilizando file antes de
intentar ver el archivo con otra de las herramientas que se muestran aquí.

file [OPCIONES] [ARCHIVO...]

Prueba FILE(s) para determinar el tipo de archivo y muestra los resultados en la salida estándar.

Ejemplo de uso con archivos ASCII:

[nero@station nero]$ file index.html novel.ps mailer


index.html: HTML document text
novel.ps: PostScript document text conforming at level 3.0
mailer: perl script text executable

Ejemplo de uso con archivos binarios:

511
[nero@station nero]$ file logo.jpeg symphony.mp3 archive.tgz
logo.png: PNG image data, 387 x 69, 8-bit grayscale, non-
interlaced
symphony.mp3: MP3, 128 bits, 44.1 kHz, JStereo
archive.tgz: gzip compressed data, deflated, last modified: Thu
Mar 20 21:27:27 2003, os: Unix

El comando cat

Este comando se introdujo por primera vez en el capítulo 3 de este cuaderno. Aquí le mostramos
algunas de sus opciones.

cat [OPCIONES] [ARCHIVO...]

Concatena FILE(s) en la salida estándar.

Opción Efecto
-A Muestra todos los caracteres incluyendo los caracteres de control y los de no impresión.
-s " Apiña" múltiples líneas adyacentes en blanco en una sóla línea en blanco
-n Numera las líneas de la salida

El comando cat, cuando se utiliza para ver archivos, simplemente muestra todo el contenido de
una sola vez. Los archivos largos pasan por la pantalla de manera muy rápida haciendo que cat
sea el comando más apropiado para aquellos archivos con menos de una pantalla de texto.

Los paginadores more y less

Tanto more como less están diseñados para ver archivos de texto en la pantalla. Su uso es muy
similar aunque el comando less es un poco más moderno y tiene unas pocas características extras
tales como el responder de manera correcta a [PgArriba], [PgAbajo] y a las flechas de navegación.
Después de todo,less es more.

Es bien importante familiarizarse con el comando less, ya que otras herramientas (como man) lo
utilizan en segundo plano para brindar funciones de paginador.

more [OPCIONES] [ARCHIVO...]

Muestra el/los archivo(s)FILE(s) en la salida estándar y una pantalla a la vez bajo el control del
teclado.

Opción Acción
-c Limpia la pantalla y redibuja en vez de desplazarse
-s "Apiña" múltiples líneas adyacentes en blanco en una sóla línea en blanco

less [OPCIONES] [ARCHIVO...]

Muestra el/los archivo(s)FILE(s) en la salida estándar y una pantalla a la vez bajo el control del
teclado.

512
Opción Acción
-c Limpia la pantalla y redibuja en vez de desplazarse
-r Muestra los caracteres de control básico
-s "Apiña" múltiples líneas adyacentes en blanco en una sóla línea en blanco

Table 1. Comandos de navegación less (more)

Comando more Acción


?
>espacio> Si adelanta una pantalla entera
[PgDn] No adelanta una pantalla entera
b Si devuelve una pantalla entera
[PgUp] No devuelve una pantalla entera
[DnArrow] No adelanta una línea
[Flechaarriba] No se devuelve una línea
/text Si va hacia adelante para buscar texto
?texto No va hacia atrás para buscar texto
n Si repite la última búsqueda
N No repite la última búsqueda pero en dirección contraria
q Si quit
h Si ayuda (introduce muchos comandos nuevos)

Una de las características del paginador less es que depende de un concepto estándar de Unix
llamado tuberías. Aunque las tuberías se discuten más adelante esta característica de less es
bastante útil y sencilla de utilizar así que amerita presentarla ahora. Una tubería actúa como un
redireccionamiento en donde la salida de un comando es redireccionado a un lugar distinto de la
terminal. Con la redirección (usando >) la salida se redirecciona a un archivo específico. Cuando se
utiliza una tubería la salida de un comando es redireccionada como entrada de otro comando. La
shell bash usa el caracter | (suele encontrarse encima de la tecla RETURN) para construir
tuberías.

Al ejecutar un comando que produce bastante salida, ésta se puede poner en una tubería
usandoless. En vez de ser botada a una terminal, la salida se puede navegar como si fuese un
archivo, subiendo y bajando de página y haciendo búsquedas. Cuando termine salga de less y la
salida desaparecerá.

El usuario elvis está utilizando el comando ps aux para ver una tabla con todos los procesos que
están ejecutándose en la máquina. Como espera que la salida sea más bien larga, decide
entonces poner una tubería del comando al navegador less.

[elvis@station elvis]$ ps aux


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1392 92 ? S 17:27 0:04 init [
root 2 0.0 0.0 0 0 ? SW 17:27 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW 17:27 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN 17:27 0:00 [ksoftirqd_CPU0]
root 9 0.0 0.0 0 0 ? SW 17:27 0:00 [bdflush]
...
[elvis@station elvis]$ ps aux | less

513
Ahora él puede utilizar la mismas secuencia que utiliza al navegar un archivo (o las páginas man)
para hojear las salidas de los comandos ps:ESPACIO para avanzar, b para retroceder,
/textRETORNO para buscar el texto text, y q para salir.

El comando head

Algunas veces todo lo que se necesita al examinar un archivo es ver las primeras líneas del
archivo. El comando head nos permite hacer esto.

head [OPCIONES] [ARCHIVO...]

Escribe las primeras 10 líneas de cada ARCHIVO a la salida estándar.

Opción Efecto
-num, -n Imprime las primeras num líneas (por defecto es 10).
num
-q Suprime encabezados que dan nombres de archivo

En el siguiente ejemplo elvis examinará las primeras 10 líneas y luego las primeras 5 líneas del
archivo /etc/group.

[elvis@station elvis]$ head /etc/group


root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:
[elvis@station elvis]$ head -n 5 /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
Si se le da más de un nombre de archivo como argumento head presentará unas primeras pocas
líneas de cada archivo individualmente separado por un encabezado que muestra el nombre de
archivo. En el siguiente ejemplo, elvis lista las primeras pocas líneas de los scripts de servicios de
Red Hat que se encuentran en el directorio /etc/rc.d/init.d.

514
[elvis@station elvis]$ head -5 /etc/rc.d/init.d/*
==> /etc/rc.d/init.d/aep1000 <==
#!/bin/sh
#
# Tags
# chkconfig: - 30 70
# description: load and unload AEP1000/AEP2000 coprocessor driver

==> /etc/rc.d/init.d/anacron <==


#!/bin/sh
# Startup script for anacron
#
# chkconfig: 2345 95 05
# description: Run cron jobs that were left out due to downtime

==> /etc/rc.d/init.d/apmd <==


#!/bin/sh
#
# chkconfig: 2345 26 74
# description: apmd is used for monitoring battery status and logging it
via \
# syslog(8). It can also be used for shutting down the machine
when \

==> /etc/rc.d/init.d/atd <==


#!/bin/bash
#
# /etc/rc.d/init.d/atd
#
# Starts the at daemon

...

Así como con el paginador less de arriba, la salida de comandos largos se puede truncar al
establecer una tuería en el comando head.

[student@station student]$ ps aux | head -5


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 2500 416 ? S 10:51 0:03 init [5]
root 2 0.0 0.0 0 0 ? SW 10:51 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW 10:51 0:00 [kapmd]
root 4 0.0 0.0 0 0 ? SWN 10:51 0:00
[ksoftirqd/0]
[student@station student]$

El comando tail

tail [OPCIONES] [ARCHIVO...]

Para complementar head, el comando tail muestra las últimas 10 líneas de cada FILE a la salida
estándar.

515
Opción Efecto
-num, -n Muestra las últimas num líneas (por defecto es 10).
num
-q Suprime encabezados que dan nombres de archivo
-f Mantiene el archivo abierto y escribe las nuevas líneas como añadidas

En el siguiente ejemplo, elvis escribe las últimas 10 líneas y después las ultimas 5 del archivo /etc/
group.

[elvis@station elvis]$ tail /etc/group


named:x:25:
gdm:x:42:
postgres:x:26:
apache:x:48:
postdrop:x:90:
postfix:x:89:
squid:x:23:
webalizer:x:67:
ldap:x:55:
elvis:x:500:
[elvis@station elvis]$ tail -n 5 /etc/group
postfix:x:89:
squid:x:23:
webalizer:x:67:
ldap:x:55:
elvis:x:500:

El comando tail tiene otra opción bastante útil: la opción -f (follow). Con esta opción tail mostrará
las últimas líneas del archivo y luego "espera" y continua presentando cualquier nueva línea al ser
añadida al archivo. Frecuentemente, se utiliza para monitorear archivos de registro en tiempo real.
Una vez inicie con esta opción, el intérprete de comandos no retorna. En su lugar, tail -f se
mantiene activa y continuará presentando las nuevas líneas hasta que se presione CTRL-C.

A title

Ejemplos

Identificación de documentos con file

Al explorar la configuración del sistema de impresión cups, prince se encontró con los siguientes
archivos en el directorio /usr/share/cups/banners.

[prince@station banners]$ ls /usr/share/cups/banners/


classified confidential secret standard topsecret unclassified

Como no está seguro de qué tipo de archivos son, trata entonces de identificarlos con el comando
file.

516
[prince@station banners]$ cd /usr/share/cups/banners/
[prince@station banners]$ file *
classified: PostScript document text conforming at level 3.0
confidential: PostScript document text conforming at level 3.0
secret: PostScript document text conforming at level 3.0
standard: PostScript document text conforming at level 3.0
topsecret: PostScript document text conforming at level 3.0
unclassified: PostScript document text conforming at level 3.0

El comando file revela que éstos son documentos PostScript enviados a la impresora como
pancartas.

Determinar el tipo correcto de archivo con file

El usuario elvis acaba de descargar algunas imágenes del álbum de fotos del sitio web de su amigo
y las guardó en un directorio llamado pics.

[elvis@station images]$ ls pics/


dscn0936.png dscn0942.png dscn0953.jpg
dscn0938.png dscn0952.png dscn0959.jpg

Observa las extensiones de cuatro de los archivos y parecen estar en formato PNG, mientras que
dos de ellas parecen tener formato JPEG. Al parecerle extraño, confirma el tipo de archivos
ejecutando el comando file.

[elvis@station images]$ file pics/*


pics/dscn0936.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
pics/dscn0938.png: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced
pics/dscn0942.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
pics/dscn0952.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
pics/dscn0953.jpg: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced
pics/dscn0959.jpg: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced

Los últimos dos archivos están en formato PNG como los otros cuatro. Aparentemente, los dos
últimos fueron nombrados con una extensión equivocada.

Hojear archivos con head

La usuaria blondie recientemente aprendió que todos los archivos del directorio /etc/profile.d
terminados en .sh se encuentran incluidos en su configuración de shell bash cada vez que inicia
sesión. Interesada en saber lo que contienen los archivos decide hojear las primeras líneas de
cada archivo con el siguiente comando.

517
[blondie@station blondie]$ head /etc/profile.d/*.sh

==> /etc/profile.d/glib2.sh <==


## This caused GLib2 applications to convert filenames from
## locale encoding to UTF-8. If the locale encoding is already
## UTF-8 then it makes no difference.
export G_BROKEN_FILENAMES=1
==> /etc/profile.d/gnome-ssh-askpass.sh <==
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
export SSH_ASKPASS

==> /etc/profile.d/jdk.sh <==


export PATH=/usr/local/j2sdk1.3.1/bin:$PATH

==> /etc/profile.d/lang.sh <==


# /etc/profile.d/lang.sh - set i18n stuff

sourced=0
for langfile in /etc/sysconfig/i18n $HOME/.i18n ; do
[ -f $langfile ] && . $langfile && sourced=1
done

if [ -n "$GDM_LANG" ]; then
sourced=1
LANG="$GDM_LANG"
...
Combinación de archivos múltiples en un sólo archivo con head

La usuaria madonna está aprendiendo sobre PAM, los módulos de autenticación conectables de
Linux. Acaba de descubrir el directorio /usr/share/doc/pam-0.75/txts, el cual contiene un gran
número de archivos README.

[madonna@station madonna]$ cd /usr/share/doc/pam-0.75/txts/


[madonna@station txts]$ ls
pam_appl.txt README.pam_ftp README.pam_shells
pam_modules.txt README.pam_limits README.pam_stack
pam.txt README.pam_listfile README.pam_stress
README README.pam_localuser README.pam_tally
README.pam_access README.pam_mail README.pam_time
README.pam_chroot README.pam_nologin README.pam_timestamp
README.pam_console README.pam_permit README.pam_unix
README.pam_cracklib README.pam_pwdb README.pam_userdb
README.pam_deny README.pam_rhosts README.pam_warn
README.pam_env README.pam_rootok README.pam_wheel
README.pam_filter README.pam_securetty README.pam_xauth

En vez de examinar cada archivo individualmente ella quisiera combinarlos en un sólo archivo para
poderlo navegar fácilmente. Sabe que puede utilizar el comando cat y redireccionar la salida al
archivo, pero ya no sabría los nombres de archivos asociados con cada uno de estos archivos. En
su lugar, decide utilizar el comando head, dándole un número absurdo de líneas a seleccionar. De
esa manera, podrá navegar el contenido de los archivos con un aviso identificador otorgando el
nombre de archivo.

518
[madonna@station txts]$ head -99999 README* > /tmp/pam_READMEs.txt
[madonna@station txts]$ less /tmp/pam_READMEs.txt
==> README <==
$Id: 010_text.dbk,v 1.1.1.1 2003/08/11 13:18:31 bowe Exp $

This is a directory for text versions of the pam documentation

==> README.pam_access <==


# Description of its configuration file
#
# (The default config file is "/etc/security/access.conf". This
# default can be overridden with a module config argument
...

Monitoría de archivos múltiples con tail

En Red Hat Enterprise Linux, los eventos del sistema se registran en archivos de texto que se
encuentran en el directorio /var/log tales como /var/log/messages (para eventos del sistema en
general) y /var/log/secure (para aquellos eventos que incluyen información importante). Cuando los
eventos ocurren se añaden nuevas líneas a estos archivos en tiempo real.

Suponga que un administrador de sistemas quisiera observar ambos archivos de registro y ver la
nueva información tan pronto como llega. Ella utiliza el comando tail -f para seguir el final de
ambos archivos. El comando tail inmediatamente presenta las últimas 10 líneas de ambos
archivos, decoradas por el nombre de archivo.

519
[root@station root]# cd /var/log
[root@station log]# tail -f messages secure

==> messages <==


Jun 25 11:20:59 station kernel: 11: @cf13e4c0 length 800000de status 800100de
Jun 25 11:20:59 station kernel: 12: @cf13e500 length 800000de status 000100de
Jun 25 11:20:59 station kernel: 13: @cf13e540 length 80000042 status 00010042
Jun 25 11:20:59 station kernel: 14: @cf13e580 length 800005ea status 000105ea
Jun 25 11:20:59 station kernel: 15: @cf13e5c0 length 8000031e status 0001031e
Jun 25 11:22:06 station su(pam_unix)[2229]: session closed for user madonna
Jun 25 11:22:10 station su(pam_unix)[2352]: session opened for user root by elvis(uid=2291)
Jun 25 11:23:06 station su(pam_unix)[2399]: session opened for user root by elvis(uid=2291)
Jun 25 11:23:55 station su(pam_unix)[2399]: session closed for user root
Jun 25 11:24:00 station su(pam_unix)[2441]: session opened for user elvis by elvis(uid=2291)

==> secure <==


Jun 24 15:32:15 station sshd[11535]: Accepted publickey for root from 127.0.0.1
port 36253 ssh2
Jun 24 15:32:15 station sshd[11545]: Accepted publickey for root from 127.0.0.1
port 36254 ssh2
Jun 24 15:32:16 station sshd[11555]: Accepted publickey for root from 127.0.0.1
port 36256 ssh2
Jun 24 17:00:22 station sshd[819]: Received signal 15; terminating.
Jun 24 17:29:05 localhost sshd[792]: Server listening on 0.0.0.0 port 22.
Jun 24 17:30:49 localhost xinetd[803]: START: sgi_fam pid=1322 from=<no address>Jun 24
19:24:47 localhost xinetd[803]: START: sgi_fam pid=3175 from=<no address>Jun 25 08:43:54
localhost sshd[792]: Received signal 15; terminating.
Jun 25 10:06:28 station sshd[834]: Server listening on 0.0.0.0 port 22.
Jun 25 10:09:01 station xinetd[845]: START: sgi_fam pid=1134 from=<no address>

En este punto, el comando tail sigue ejecutándose, pero la salida hace una pausa hasta que ocurre
un nuevo evento en el sistema, el cual se registra en uno de los archivos. Después el comando tail
muestra las nuevas lineas añadidas decoradas con el nombre de archivo del archivo pertinente.

==> messages <==


Jun 25 11:24:54 station su(pam_unix)[2481]: session opened for user root by elvis (uid=501)
Jun 25 11:25:02 station su(pam_unix)[2481]: session closed for user root

Ejercicios en línea

Navegar archivos de texto Lab Exercise Objetivo: Examinar archivos usando varias utilidades
para navegar. Tiempo estimado: 15 minutos.

Especificaciones

En este ejercicio necesitará tres terminales (ya sean consolas virtuales o terminales dentro del
entorno gráfico X) cada una utilizando su cuenta primaria.

1. En la primera terminal, cat el contenido del archivo /etc/services incluyendo la opción


correcta para numerar todas las líneas. Despues de ver el resultado, repita el comando
(con la misma opción) redireccionando la salida al archivo services.cat.txt en su directorio
de inicio.

520
2. Mientras esté en la primera terminal haga un listado recursivo de todos los archivos con el
comando ls -R / y atrape la salida (utilizando una tubería) con el paginador less. Use los
comandos básicos del paginador tales como ESPACIO y b para navegar la salida. Explore
otros comandos del paginador utilizando el comando h para abrir una ventana de ayuda.

Cuando haya terminado, NO salga del paginador less, vaya a una nueva terminal para
realizar el siguiente paso.

3. En la segunda terminal, use el comando head para ver las primeras 5 líneas de todos los
archivos en el directorio /etc/sysconfig cuyo nombre empieza por system- al archivo
confheaders.txt en su directorio de inicio. Utilice la opción apropiada para suprimir los
encabezados con los nombres de archivos que head imprime por defecto.
4. Al seguir en la segunda terminal, ejecute el comando vmstat 1. Este comando traza las
estadísticas de la memoria y la CPU de su máquina generando una línea una vez por
segundo. Cuando haya visto lo suficiente, utilice la secuencia CTRL-C para matar el
comando.

Ejecute el comando de nuevo, esta vez redireccionando la salida al archivo vmstat.out en


su directorio de inicio como se muestra a continuación.

[elvis@station elvis]$ vmstat 1 > vmstat.out

5. NO pare este comando, déjelo ejecutando. Vaya a una nueva terminal para realizar el
siguiente paso.
6. En una tercera terminal siga el creciente archivo vmstat.out con el comando tail -f. NO
pare el comando tail hasta no haber confirmado el siguiente ejercicio.

Deliverables A title Question 1

1. Un archivo en su directorio de inicio llamado services.cat.txt, el cual contiene el contenido


del archivo /etc/services con líneas numeradas producidas por el comando cat.
2. Un paginador less ejecutando, el cual se encuentra utilizando una tubería para navegar la
salida del comando ls -R /.
3. El archivo confheaders.txt en su directorio de inicio, el cual contiene las primeras cinco
líneas de cada archivo en /etc/sysconfig comenzando por redhat-, como lo produjo el
comando head, suprimiendo los nombres de archivos (con la opción u opciones
apropiadas de la línea de comandos).

Limpieza

Después de completar este ejercicio salga del paginador less con el comando q y termine los
comandos vmstat y tail con la secuencia de controlCTRL-C.

521
Modificación de archivos

Conceptos clave

• Un editor de textos no es un procesador de palabras.


• Linux se envía con muchos editores de texto
• nano es un editor de texto de la línea de comandos comúnmente usado.
• gedit es un editor de texto gráfico comúnmente usado.

Discussion

Editor de texto vs. Procesador de palabras

Una de las maneras en que Linux alcanza su alto nivel de flexibilidad es por medio de la robustez
de su configuración. Usualmente la información sobre la configuración se encuentra almacenada
en archivos de texto ASCII. Con frecuencia la administración de sistemas involucra la actualización
o corrección de estos archivos de configuración. La herramienta para lograr esto es un editor de
texto.

Un editor de texto no es lo mismo que un procesador de palabras. Además de las palabras de un


documento, el procesador de palabras permite al usuario especificar tipos de letra, configuraciones
del tabulador, márgenes, justificaciones y muchas otras características diseñadas para modificar la
manera en que un documento se ve en el papel. Los documentos generados por procesadores de
palabras contienen códigos binarios que especifican la configuración de estas características
adicionales. Un archivo de texto plano tal como un archivo de configuración no contiene tales
códigos y no está diseñado para imprimirlo en papel. Un editor de texto está diseñado sólo para
modificar el contenido del texto de un archivo ASCII plano y no contiene ningún código binario.

Un procesador de palabras sería una opción apropiada para escribir una carta, un memo, un
boletín, un folleto o cualquier documento en donde la presentación visual sea controlada por el
software de edición.

Un editor de texto es la opción apropiada para crear o modificar archivos de configuración, código
fuentes de programas, documentación del sistema o cualquier documento (así como documentos
HTML) en donde la presentación visual es controlada por el software (tal como un navegador de
web) y no por el software de edición. Debido a que este curso se enfoca en la administración de
sistemas Linux, los editores de texto serán nuestra herramienta en la mayoría de los casos.

Editores de texto en Linux

Linux viene junto con un juego completo de editores de texto, cada uno con sus fortalezas y
debilidades. Linux también incluye procesadores de palabra para la creación de documentos como
parte de productos tales como OpenOffice.

Como todos los editores de texto trabajan en archivos de texto sencillos, puede escoger el que
quiera sin problemas de compatibilidad entre los productos. Normalmente se escoge una opción
con base en la disponibilidad, facilidad de uso, familiaridad y características especiales. Por
ejemplo, algunos editores facilitan la generación de código de programas formateados de manera
correcta haciendo que la programación sea mucho más fácil y rápida. Este capítulo presenta dos
editores fáciles de utilizar nano y gedit. El editor de texto más popular en los sistemas Linux es vi

522
y también es el más robusto y el más complicado. La complejidad de este editor hace difícil
abordarlo en un curso introductorio.

nano

nano es un editor de texto simple que presenta una pantalla completa. Los comandos se presentan
al final de la pantalla y se proporciona ayuda de acuerdo con el contexto. Al escribir los caracteres
estos se insertan de manera inmediata en el texto.

Uso:

nano [OPCIONES] [ARCHIVO]

Abre el ARCHIVO en modo de edición.

Como se mencionó anteriormente el comando nano se presenta al final de la pantalla durante la


sesión de edición, lo cual hace muy fácil recordar los comandos de edición. Los comandos
primarios de nano se encuentran resumidos abajo. Allí hallará que el símbolo circunflejo (^),
seguido de una letra se utiliza para representar combinaciones de Ctrl-tecla, así que ^K representa
la combinación de CTRL-K.

Table 1. Los comandos de nano

Comando Función
^G Ayuda - abre una pequeña ventana de ayuda
^X Salir - sale (y opcionalmente guarda el archivo)
^O Escribir - guarda el archivo
^J Justificar
^R Leer el archivo - e insertar en la posición del cursor
^W Dónde está - búsqueda de texto
^Y Página anterior -retrocede una página
^V Próxima página - adelanta una página
^K Cortar texto - corta una línea a la vez
^U Deshace el corte de texto - inserta el último bloque de texto cortado
^C Posición del cursor- identifica el número de línea y de columna
^T Corrector ortográfico - empieza a corregir la ortografía

Table 2. Opciones especiales de nano

Opción Función
-w desactiva el ajuste de texto
-v "ver" el archivo en modo de sólo-lectura

Los archivos de configuración pueden sufrir daños debido a cortes de línea indebidos, así que con
frecuencia se inicianano con la opción-w para editar estos archivos.

gedit

gedit es un editor gráfico de texto disponible para el entorno de X-window. Se puede acceder a él
entrando gedit en el intérprete de comandos de una terminal o seleccionando Accesorios -> Editor
de texto del menú de GNOME. Proporciona una interfaz familiar de documentos para crear y
modificar archivos de texto e iconos de barras de herramientas para acceder a características tales

523
como búsqueda y remplazo, cortar-copiar -pegar, e imprimir. Esta ventana cuenta con pestañas
que permiten abrir más de un documento a la vez. También soporta una interfaz estándar para
interactuar con el sistema de archivos.

Figure 1. El editor gráfico de textos gedit

Ejercicios en línea

Editores de texto Lab Exercise Objetivo: Editores de texto Estimated Time: 10 mins.

Especificaciones

El archivo /etc/services es un ejemplo de un archivo de texto de configuración ASCII de Linux. En


este laboratorio tendrá que hacer dos copias de este archivo y modificar uno utilizando el editor de
texto nano y modificar el otro utilizando el editor de textos gráfico gedit. Si su sistema no tiene
instalado el servidor X, utilice el editor nano para ambos archivos.

El editor nano

1. En su directorio de inicio cree una copia del archivo /etc/services llamado services.nano
2. Abra el archivo services.nano utilizando el editor de textos nano.
3. Al usar las secuencias de control especificadas al final de la pantalla, busque y borre todas
las ocurrencias del caracter +. Mantenga los espacios de las columnas y guarde su archivo
como services.noplus.
4. Continuando en la misma sesión de edición mueva su cursor a la línea 140. La
combinación CTRL-C le informará el número de línea actual (observe que CTRL-C, el
comando que usualmente termina un proceso, ha sido sobrescrito por el editor nano y
tiene un nuevo comportamiento). Borre esa línea y la siguiente. Guarde su archivo como
services.nonext.
5. Cierre el editor nano.

524
El editor gedit

1. En su directorio de inicio cree una copia del archivo /etc/services llamado services.gedit
2. Abra el archivo services.gedit utilizando el editor de texto gedit.
3. Mueva su cursor a la línea número 100 (el explorar un poco el menú de gedit le puede
simplificar esta tarea). Borre toda la línea y las dos siguientes. Guarde su archivo como
services.notsmux.
4. Remplace toda ocurrencia de la letra tcp con udp. Realice la búsqueda y remplace
teniendo en cuenta mayúsculas y minúsculas (por ejemplo, no remplace TCP). Guarde su
archivo como services.notcp.
5. Cierre el editor gedit.

Deliverables A title Question 1

Debe crear todos los archivos en su directorio de inicio.

1. Un archivo llamado services.noplus, el cual es un duplicado del archivo /etc/services con


los caracteres + borrados.
2. Un archivo llamado services.nonext, el cual además de la modificación anterior ha
suprimido las líneas número 140 y 141.
3. Un archivo services.notsmux, el cual es el duplicado del archivo /etc/servicessin las líneas
100, 101 y 102 suprimidas.

525
Supplements
Escritura avanzada de shell

Conceptos clave

• Linux utiliza el mecanismo de scripts, en donde los archivos de scripts de texto pueden ser
ejecutados por un intérprete especificado en la línea inicial.
• Dentro de un script bash, los argumentos provistos al invocar un script están disponibles
como parámetros posicionales (por ejemplo, las variables $1, $2, ...).
• El comando incorporado read se puede utilizar para leer la entrada desde la "entrada
estándar" del teclado.
• La shell utiliza una sintaxis if ... then ... [else ...] fi para implementar ramas condicionales.
• El comando test suele utilizarse como comando condicional en ramas if ... then.
• La shell bash utiliza una sintaxis for ... in ... do ... done para implementar bucles.

Discussion

Escritura de shell

En capítulos anteriores a este cuaderno discutimos la creación de scripts simples de shell. Estos
scripts hacían algo más que ejecutar una serie de comandos, opcionalmente aceptando la salida
del usuario para definir variables.

Sin embargo, los scripts de shell son capaces de mucho más. Este capítulo agregará algunas
herramientas valiosas, permitiéndole a sus scripts tomar decisiones si/entonces/otro, en inglés
if/then/else, y retroalimentar una serie de acciones de modo indefinido.

Ramas: if ... then ... [else ...] fi

Sintaxis Bash para ramas

Al programar, las ramas le permiten a los programas escoger entre una o dos (o más) rutas
alternas de ejecución. La shell bash, al igual que la mayoría de los lenguajes de programación,
utiliza la palabra si, en inglés if, para significar una rama. Más formalmente, bash utiliza la siguiente
sintaxis.

if condición
then

comando(s)
...
fi

526
if condición
then

comando(s)
...
else

comando(s)
...
fi

Los comandos en estas estrofas se ejecutan si la condición tiene "éxito".

Los comandos en la estrofa se ejecutan si la condición "fracasa".

Al utilizar esta sintaxis, los retornos de carro son importantes (por ejemplo, el if y then deben
presentarse en líneas separadas), pero las sangrías no lo son.

¿Qué espera bash como condición? A diferencia de la mayoría de los lenguajes de programación,
bash no tiene sintaxis interna para hacer comparaciones (¿tales como $ A == apple, o $B >25). En
su lugar, bash se concentra en la razón de su diseño inicial: la ejecución de comandos. Cualquier
comando se puede utilizar para la condición. La shell bash ejecutará el comando y examinará su
valor de retorno. Si el comando tiene "éxito"(devuelve un valor de retorno de 0), la primera estrofa
de comandos se ejecutará. Si el comando fracasa (devuelve un valor de retorno no igual a cero), la
segunda estrofa de comandos se ejecutará (si existe).

La siguiente modificación para el script de elvis shut sirve de ejemplo.

[elvis@station elvis]$ ls
example.sh shut
[elvis@station elvis]$ cat shut
#!/bin/bash
# the first argument should be the name of the file to shut.

if ls $1
then
chmod 600 $1
else
echo "The file $1 does not exist."
fi
[elvis@station elvis]$ ./shut example.sh
example.sh
[elvis@station elvis]$ ./shut foo
ls: foo: No such file or directory
The file foo does not exist.

En el primer caso, el comando ls tiene "éxito" (porque el archivo example.sh existe, el valor de
retorno del comando ls es 0). Como resultado, la primera estrofa de la cláusula if ... then ... else ...
fi se ejecuta. En el segundo caso, el archivo foo no existe, por lo tanto la segunda estrofa (otro) de
la cláusula se ejecutó.

527
El comando test

El ejemplo anterior es bastante raro. El comando ls se ha forzado a realizar una labor para la cual
no está diseñado: probar si existe un archivo. Aunque puede hacer esto, los mensajes que imprime
distraen la atención. Si el archivo especificado existe, su nombre se imprime en la pantalla. Si el
archivo no existe, entonces un mensaje de error se imprimirá en pantalla. Si solo hubiera un
comando que comprobara la existencia del archivo y retornara el código de retorno apropiado, sin
emitir otros mensajes...

Lo hay. El comando se llama test. El comando test fue diseñado específicamente para este
propósito: para ser un comando condicional en frases bashif ... then. Más específicamente, el
comando test está diseñado para comparar cadenas de texto, números enteros y atributos de
archivo. Nunca genera salida, en cambio, se comunica mediante su valor de retorno. El comando
test retorna 0 si la expresión que evalúa es verdadera y un valor de no cero si no lo es.

La mayoría de argumentos de test se parecen a las opciones de la línea de comandos. Por


ejemplo, -e examina si existe un archivo. El guión anterior podría mejorarse remplazando ls con
test -e.

[elvis@station elvis]$ cat shut


#!/bin/bash
# the first argument should be the name of the file to shut.

if test -e $1
then
chmod 600 $1
else
echo "The file $1 does not exist."
fi
[elvis@station elvis]$ ./shut example.sh
[elvis@station elvis]$ ./shut foo
The file foo does not exist.

Observe que el comando test examina la existencia de un archivo, pero no genera mensajes para
distraer la atención del usuario.

El siguiente cuadro lista algunas de las opciones más comunes para examinar los atributos de los
archivos.

Table 1. Expresiones de test para examinar atributos de archivos

Expresión Condición
-d ARCHIVO El ARCHIVO existe y es un directorio.
-e ARCHIVO El ARCHIVO existe
-f ARCHIVO El ARCHIVO existe y es un archivo regular.
-r ARCHIVO El ARCHIVO existe y es leíble.
-w ARCHIVO El ARCHIVO existe y es escribible.
-x ARCHIVO El ARCHIVO existe y es ejecutable.
FILE1 -nt El FILE1 en más reciente que ARCHIVO2.
ARCHIVO2

Table 2. Expresiones de test para comparar cadenas de texto

528
Expresión Condición
[-n] CADENA DE la longitud de CADENA DE TEXTO es mayor que cero.
TEXTO
-z CADENA DE TEXTO la longitud de CADENA DE TEXTO es cero.
CADENA1 = CADENA2 CADENA1 y CADENA2 son iguales.
CADENA1 != CADENA2 CADENA1 y CADENA2 no son iguales.

Por último, el siguiente cuadro lista las expresiones que permiten al comando test utilizar una
lógica compuesta.

Table 3. Expresiones lógicas para el comando test

Expresión Condición
EXPRESIÓN1 -a Tanto EXPRESIÓN1 como EXPRESIÓN2 son verdaderas.
EXPRESIÓN2
EXPRESIÓN1 -o EXPRESIÓN1 o EXPRESIÓN2 es cierta.
EXPRESIÓN2
! EXPRESIÓN EXPRESIÓN es falsa.

Estos cuadros ofrecen al estudiante una serie de expresiones útiles. Para obtener una lista
completa, consulte la página de manual test(1).

Expresión alterna para test: [ expresión ]

Como el comando test es tan utilizado en scripts bash se ha desarrollado una sintaxis más corta.
Las siguientes dos expresiones son equivalentes.

test expresión

[ expresión ]

A manera de ejemplo, el script de elvis shut se puede reescribir así:

[elvis@station elvis]$ cat shut


#!/bin/bash
# the first argument should be the name of the file to shut.

if [ -e $1 ]
then
chmod 600 $1
else
echo "The file $1 does not exist."
fi

Observe que el comando test se ha remplazado con la sintaxis alterna [ ... ].

529
Al utilizar la sintaxis alterna, se debe tener cuidado de incluir un espacio después de abrir el
paréntesis y antes de cerrarlo.[1] Por ejemplo, las siguientes dos construcciones del comando test
están erradas.

[-e foo.sh ]
[ -e foo.sh]

La siguiente construcción está realmente errada.

[-e foo.sh]

Bucles: for ... in ... do ... done

Sintaxis bash para bucles

Los bucles son quizás la estructura de programación más útil para automatizar trabajos
convencionales. Los bucles permiten la repetición de una serie de comandos, usualmente con
leves variaciones en cada iteración. Estas variaciones se suelen ejecutar mediante una variable
conocida como un iterator. Para cada iteración del bucle, la variable toma un valor diferente. Por
ejemplo, elvis pudo utilizar el siguiente guión para afirmar su afecto por su colección de mascotas
domésticas.

[elvis@station elvis]$ cat nice


#!/bin/bash

for PET in kitty doggy gerbil newt


do
echo "nice $PET."
done
[elvis@station elvis]$ ./nice
nice kitty.
nice doggy.
nice gerbil.
nice newt.

En este script, la variable de shell PET se utiliza como iterador. Con cada iteración del bucle, la
variable adquiere un valor diferente.

Más formalmente los bucles for ... in ... do ... done en bash utilizan la siguiente sintaxis.

for iterador in lista


do
comando(s)
...
done

530
Para cada repetición del bucle, la variable iterator evaluará las palabras individuales en la
expresión lista

Para un ejemplo más práctico, revisitaremos el guión de elvis shut. El usuario elvis desearía
modificar su guión, con el fin de poder especificar archivos múltiples en la línea de comandos. Para
implementar este cambio, esencialmente toma su guión anterior y lo delimita dentro de un bucle for
... in .. do ... done. En lugar de utilizar el primer parámetro posicional ($1) directamente, elvis utiliza
un iterador a través de todos los argumentos provistos en la línea de comandos.

[elvis@station elvis]$ cat shut


#!/bin/bash
# the first argument should be the name of the file to shut.

for FILE in $*
do
if [ -e $FILE ]
then
chmod 600 $FILE
else
echo "The file $FILE does not exist."
fi
done

A continuación, elvis utiliza el guión para modificar los permisos en los archivos example.sh y nice.

[elvis@station elvis]$ ls -l
total 12
-rwxr-xr-x 1 elvis elvis 212 Sep 3 10:56 example.sh
-rwxr-xr-x 1 elvis elvis 77 Sep 4 12:16 nice
-rwxrwxr-x 1 elvis elvis 188 Sep 4 12:31 shut
[elvis@station elvis]$ ./shut example.sh biz nice baz
The file biz does not exist.
The file baz does not exist.
[elvis@station elvis]$ ls -l
total 12
-rw------- 1 elvis elvis 212 Sep 3 10:56 example.sh
-rw------- 1 elvis elvis 77 Sep 4 12:16 nice
-rwxrwxr-x 1 elvis elvis 188 Sep 4 12:31 shut

Observe el uso de la variable $* para generar la lista. El siguiente cuadro sugiere otros trucos del
oficio.

Table 1. Técnicas comunes para generar listas iterativas

Cuando utilice... ...$i itera a través de ...


for i in $* los argumentos de línea de comando del script
for i in /etc/*.conf el del archivo coincidente con el comodín /etc/*.conf
for i in $(command) las palabras devueltas por el comando command.

531
Ejemplos

Un script para "empacar" directorios

El usuario elvis se da cuenta que a menudo está "tarring up" (archivando) directorios que no está
utilizando. Decide crear un guión llamado pack, el cual le ayudará a archivar directorios más
rápidamente.

El script pack espera que uno o más directorios sean listados como argumentos. Para cada
directorio, el script creará un archivo llamado como el directorio con la extensión .tgz agregada.
Sólo si la creación del archivo tiene éxito, el script eliminará el directorio original.

Como elvis considera detenidamente los directorios que los usuarios pueden especificar, se da
cuenta que los directorios . y .. pueden causar problemas (¿por qué?), entonces les agrega una
exclusión.

[elvis@station elvis]$ cat pack


#!/bin/bash

for DIR in $*; do

if [ -d $DIR ]
then

if [ "$DIR" == "." -o "$DIR" == ".." ]


then
echo "skipping directory $DIR"
else

tar cvzf $DIR.tgz $DIR && rm -fr $DIR


fi
else
echo "skipping non directory $DIR"
fi
done
El guión recorre todos los argumentos de línea de comandos provistos.

El guión confirma que el argumento existe y que se refiere a un directorio.

El guión aquí comprueba que el usuario no tiene el directorio . o .. especificado. En la


práctica, hay aún algunos nombres de directorios que pueden causar problemas. ¿Puede
usted pensar en alguno?
Por último, aquí hay una línea que trabaja duro. Observe que el directorio original se elimina
sólo si el comando tar tiene éxito.

Él ensaya su script en estos dos directorios de prueba.

532
[elvis@station elvis]$ mkdir test{1,2}
[elvis@station elvis]$ touch test{1,2}/{one,two,three,four}
[elvis@station elvis]$ ls -R
.:
pack test1 test2

./test1:
four one three two

./test2:
four one three two
[elvis@station elvis]$ ./pack test1 test2
test1/
test1/one
test1/two
test1/three
test1/four
test2/
test2/one
test2/two
test2/three
test2/four
[elvis@station elvis]$ ls -R
.:
pack test1.tgz test2.tgz
Los directorios de prueba se han "empacado".

Ejercicios en línea Lab Exercise Objetivo: Utilizar scripts shell para automatizar la rotación de
imágenes.Estimated Time: 30 mins.

Especificaciones

Crear un script llamado rotate_cw que sirva para rotar imágenes 90 grados. Para realizar la
rotación, debería utilizar el comando convert (analice la página de manual convert(1) y preste
mucha atención a la opción rotate). A continuación presentamos un ejemplo de uso del comando
convert para rotar una imagen.

[elvis@station elvis]$ cp /usr/share/pixmaps/redhat-main-menu.png .


[elvis@station elvis]$ convert -rotate 90 redhat-main-menu.png
/tmp/redhat-main-
menu.png
El archivo /tmp/redhat-main-menu.png es la misma imagen de redhat-main-menu.png rotada 90
grados.

El script debe esperar como argumentos múltiples nombres de archivo de las imágenes que van a
ser rotadas. Debe asumir que los nombres de archivo no contienen componentes de directorio (por
ejemplo, se referirán a archivos en el directorio actual). El guión debe generar un nuevo archivo de
la imagen rotada y si la nueva imagen se genera correctamente, remplace la imagen original con la
imagen rotada (dando la apariencia de rotar imágenes "en su lugar".

Abandone el guión en su directorio de inicio y asegúrese que tiene permisos ejecutables.

Deliverables A title Question 1

533
Un script bash ejecutable llamado ~/rotate_cw, el cual rotará imágenes en el directorio local
cuyos nombres de archivo (sin componentes de directorio) pasan como argumentos.
content_view let_

534
Codificación de caracteres e internacionalización

Conceptos clave

• When storing text, computers transform characters into a numeric representation. This
process is referred to as encoding the text.
• In order to accommodate the demands of a variety of languages, several different encoding
techniques have been developed. These techniques are represented by a variety of
character sets.
• La técnica más sofisticada de codificación se conoce como el Conjunto Universal de
Caracteres (UCS)
• La técnica de codificación en Linux de Red Hat Enterprise se conoce como UTF-8, la cual
permite la flexibilidad de Unicode y a su vez retiene la compatibilidad de ASCII.
• La variable de entorno LANG se utiliza para especificar un lenguaje preferido del usuario y
la codificación de caracter.

Archivo

Codificación de texto

Perhaps the most common type of data which computers are asked to store is text. As computers
have developed, a variety of techniques for encoding text have been developed, from the simple in
concept (which could encode only the Latin alphabet used in Western languages) to complicated
but powerful techniques that attempt to encode all forms of human written communication, even
attempting to include historical languages such as Egyptian hieroglyphics. The following sections
discuss many of the encoding techniques commonly used in Red Hat Enterprise Linux.

Internacionalización (i18n)

As this Workbook continues to discuss many tools and techniques for searching, sorting, and
manipulating text, the topic of internationalization cannot be avoided. In the open source
community, internationalization is often abbreviated as i18n, a shorthand for saying "i-n with 18
letters in between". Applications which have been internationalized take into account different
languages. In the Linux (and Unix) community, most applications look for the LANG environment
variable to determine which language to use.

At the simplest, this implies that programs will emit messages in the user's native language.

[elvis@station elvis]$ echo $LANG


en_US.UTF-8
[elvis@station elvis]$ chmod 666 /etc/passwd
chmod: changing permissions of `/etc/passwd': Operation not permitted
[elvis@station elvis]$ export LANG=de_DE.utf8
[elvis@station elvis]$ chmod 666 /etc/passwd
chmod: Beim Setzen der Zugriffsrechte fr /etc/passwd: Die Operation ist
nicht erlaubt

More subtly, the choice of a particular language has implications for sorting orders, numeric
formats, text encoding, and other issues.

535
El Administrador de paquetes RPM

Conceptos clave

• El comando rpm se utiliza para agregar o quitar programas desde su sistema.


• Usted debe tener privilegios de root para agregar y quitar programas con rpm.
• Cualquiera puede solicitar paquetes instalados o archivos de paquetes.

Discussion

RPM: El administrador de paquetes de Red Hat

El administrador de paquete de Red Hat probablemente es el elemento que mejor define la


distribución de Red Hat Enterprise Linux. El administrador de paquete ofrece a los desarrolladores
una forma de construir y distribuir programas, a los administradores una forma de instalar y
mantener programas y a todos los usuarios una forma de solicitar información y verificar la
integridad de programas instalados.

La necesidad de administración de paquetes

Antes de que la administración de paquetes se convirtiera en un concepto técnico, los programas


se distribuyeron principalmente como "tarballs" (por ejemplo, archivos comprimidos tar) y sólo en
forma de origen. Cualquiera que esté utilizando un producto de código abierto necesitará
desempacar el tarball, compilar los ejecutables (esperando que sus sistema tenga las bibliotecas
correctas para soportarlo), e instalar el producto en su sistema, a menudo con componentes en
directorios múltiples (tales como /etc, /var/lib, /usr/bin/ y /usr/lib).

Por lo general, los guiones distribuídos con código abierto realizan cada uno de estos pasos más
fácilmente, pero incluso ellos no tratan dos problemas fundamentales. El primero es el problema de
dependencia. A menudo, los productos de fuente abierta reutilizan código distribuido en forma de
una biblioteca. Si la biblioteca apropiada no está instalada aún en el sistema, la aplicación que
depende de ésta no servirá. El segundo problema fundamental es el mantenimiento. ¿Qué sucede
cuando, después de seis meses lanzan una nueva versión del producto o alguien decide no querer
más un producto en particular? Se necesitaría rastrear y quitar o remplazar los archivos
individuales del producto.

RPM está diseñado para ayudar a resolver esos dos problemas fundamentales.

Los componentes RPM

Cuando la gente habla de RPM se refiere a tres componentes colectivamente: la base de datos
RPM, el ejecutable rpm y los archivos de paquete.

La base de datos RPM

La base de datos RPM es el centro del producto, proporciona la respuesta a los dos problemas
antes mencionados. Cada vez que el programa es instalado por RPM, se crean las entradas de
base de datos que representan cada archivo instalado. Debido a la base de datos, los archivos se
pueden quitar fácilmente desde el sistema más tarde.

536
Además, la base de datos mantiene una lista de dependencias requerida y provista por varios
paquetes. Al instalar una aplicación que requiere una biblioteca, por ejemplo, la biblioteca se puede
listar como dependencia específica y la base de datos puede responder de modo inequívoco por la
presencia (o ausencia) de la biblioteca.

La base de datos reside en el directorio /var/lib/rpm, pero aparte de saber que existe, los usuarios
estándar (o incluso el administrador) poco necesitarán acceder al directorio directamente.

El ejecutable rpm

Los usuarios interactúan con la base de datos RPM a través del comando rpm. El ejecutable es
utilizado por administradores para instalar, modernizar o quitar paquetes de programas y por el
usuario para contestar preguntas acerca de los paquetes instalados o verificar su integridad.
Examinaremos las solicitudes de RPM en detalle más adelante.

Archivos de paquete

Los archivos de paquete son el medio por el cual se distribuyen los programas. Los archivos de
paquete suelen nombrarse mediante la siguiente convención.

nombre-versión-publicación.archivo.rpm

Por ejemplo, la primera publicación del archivo de paquete para versión 4.0.7 de la aplicación zsh
de código abierto compilado para la arquitectura Intel x86 (y compatible) se llamaría
convencionalmente zsh-4.0.7-1.i386.rpm.

Los archivos de paquete son esencialmente archivos tar (aunque más de cerca parecen archivos
cpio menos familiares) combinados con la información de encabezado, la cual nombra versiones y
dependencias de estados para el paquete. Cuando la gente se refiere a la distribución de Red Hat,
generalmente se refiere a la colección de archivos de paquete RPM que componen el programa
instalado en una máquina.

Realizar peticiones a la base de datos RPM

Cuando se invoca con -q como su primera opción, el comando rpm realizará peticiones a la base
de datos RPM (o algunas veces archivos de paquete RPM directamente).

Formulación de peticiones RPM

Cuando se presenta por primera vez a rpm, la sintaxis asociada con peticiones puede ser un poco
abrumadora. Ayuda a pensar que cada petición consta de dos preguntas: (1)¿Qué paquetes estoy
solicitando? (2)¿Qué pregunta estoy haciendo? Cada una de las opciones relacionadas con
peticiones del comando rpm entra en una de estas dos categorías.

Table 1. Opciones para realizar peticiones RPM con el fin de especificar paquetes

Opción Especificaciones
-a todos los paquetes instalados
paquete- el paquete nombre
nombre
-f filename el paquete propietario del archivo filename

537
-p paquete- solicitud del archivo de paquete paquete-archivo-nombre directamente. Esta
archivo- opción es fundamentalmente diferente, pues todas las otras opciones realizan
nombre una petición a la base de datos RPM de paquetes instalados.

Table 2. Opciones de peticiones RPM para especificar información

Opción Especificaciones
(por defecto) nombre del paquete y versión
-i encabezado de información del paquete
-l lista de archivos pertenecientes al paquete
--queryformat lista información especificada en cadena de texto de formato str
str

Al escoger una opción desde el primer cuadro y cero o más opciones desde el segundo cuadro, los
usuarios pueden formular preguntas específicas para la base de datos RPM.

Ejemplos de peticiones

Peticiones generales

Por ejemplo, la opción -a realiza una solicitud en todos los paquetes instalados. Si no se hace otra
pregunta, por defecto rpm retornará el nombre del paquete. Así rpm -qa retornará una lista de
todos los paquetes instalados.

[prince@station prince]$ rpm -qa


basesystem-8.0-2
expat-1.95.5-2
libacl-2.2.3-1
popt-1.8-0.69
rootfiles-7.2-6
cpio-2.5-3
gzip-1.3.3-9
...

Si se especifica un nombre de paquete, el rpm solicitará sólo aquel paquete. ¿Qué información
retorna? De nuevo, por defecto, retornará el nombre del paquete.

[prince@station prince]$ rpm -q bash


bash-2.05b-20.1

Aunque quizás no es la más informativa de las solicitudes, prince al menos recibe la confirmación
de la instalación del paquete, y un número de versión. Por lo general, cuando se solicita el nombre
del paquete se pide más información. Por ejemplo, al agregar -i se generará un encabezado de
información.

538
[prince@station prince]$ rpm -qi bash
Name : bash Relocations: /usr
Version : 2.05b Vendor: Red Hat, Inc.
Release : 20.1 Build Date: Wed 09 Apr 2003 09:02:36 AM EDT
Install Date: Tue 08 Jul 2003 09:29:33 AM EDT Build Host:
stripples.devel.redhat.com
Group : System Environment/Shells Source RPM: bash-2.05b-20.1.src.rpm
Size : 1619204 License: GPL
Signature : DSA/SHA1, Mon 09 Jun 2003 06:45:19 PM EDT, Key ID 219180cddb42a60e
Packager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
Summary : The GNU Bourne Again shell (bash).
Description :
The GNU project Bourne Again shell (bash) is a shell or command
language interpreter that is compatible with the Bourne shell
(sh). Bash incorporates useful features from the Korn shell (ksh) and
the C shell (csh) and most sh scripts can be run by bash without
modification. Bash is the default shell for Red Hat Linux.

O añadiendo un -l se generará una lista de todos los archivos instalados.

[prince@station prince]$ rpm -ql bash


/bin/bash
/bin/bash2
/bin/sh
/etc/skel/.bash_logout
/etc/skel/.bash_profile
/etc/skel/.bashrc
/usr/bin/bashbug
/usr/lib/bash
/usr/share/doc/bash-2.05b
/usr/share/doc/bash-2.05b/CHANGES
...

Si se incluyen ambos en rpm -qil bash se generarían los dos.

Investigación de un paquete desconocido

¿Qué sucede si usted ha encontrado un archivo en el sistema de archivos y quiere conocer a qué
paquete de archivo pertenece? rpm -qf ...

[prince@station etc]$ rpm -qf /etc/aep.conf


hwcrypto-1.0-14

¿Quiere saber más acerca del paquete? Agregue un -i.

539
[prince@station etc]$ rpm -qf /etc/aep.conf -i
Name : hwcrypto Relocations: (not relocateable)
Version : 1.0 Vendor: Red Hat, Inc.
Release : 14 Build Date: Tue 04 Feb 2003 06:20:37 AM EST
Install Date: Tue 01 Apr 2003 11:27:43 AM EST Build Host:
sylvester.devel.redhat.com
Group : System Environment/Base Source RPM: hwcrypto-1.0-14.src.rpm
Size : 711506 License: GPL
Signature : DSA/SHA1, Mon 24 Feb 2003 01:25:46 AM EST, Key ID
219180cddb42a60ePackager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
Summary : Hardware cryptographic accelerator support.
Description :
This package contains the shared libraries used to interface with
hardware cryptographic accelerators under Linux.

¿Existe documentación en el sistema que pueda dar mayor información acerca de esto? Agregue -l
para listar los archivos relacionados con /etc/aep.conf.

[prince@station etc]$ rpm -qf /etc/aep.conf -l


/etc/aep
/etc/aep.conf
/etc/aep/aeptarg.bin
/etc/aeplog.conf
...
/usr/sbin/aepversion
/usr/share/doc/hwcrypto-1.0
/usr/share/doc/hwcrypto-1.0/hwcrypto.txt
/usr/share/doc/hwcrypto-1.0/readme.snmp
/usr/share/snmp/mibs/cnStatTrap.mib

En este caso, no mucho, pero quizás /usr/share/doc/hwcyrpto.txt ayudará un poco. Muchos


paquetes incluyen páginas de man que se pueden leer o navegar. Al menos usted puede ubicar
algunos archivos de configuración que quiera hojear para averiguar un poco más.

Investigación de un archivo de paquete desconocido

¿Qué sucede si usted se encuentra un archivo de paquete que aún no ha sido instalado en su
sistema? El comando rpm permite que los archivos de paquete sean solicitados con la opción -p.

540
[prince@station RPMS]$ rpm -qil -p xsri-2.1.0-5.i386.rpm
Name : xsri Relocations: (not relocateable)
Version : 2.1.0 Vendor: Red Hat, Inc.
Release : 5 Build Date: Sat 25 Jan 2003 03:37:15 AM EST
Install Date: (not installed) Build Host: porky.devel.redhat.com
Group : Amusements/Graphics Source RPM: xsri-2.1.0-5.src.rpm
Size : 27190 License: GPL
Signature : DSA/SHA1, Mon 24 Feb 2003 12:40:17 AM EST, Key ID 219180cddb42a60ePackager
: Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
Summary : A program for displaying images on the background for X.
Description :
The xsri program allows the display of text, patterns, and images in
the root window, so users can customize the XDM style login screen
and/or the normal X background.

Install xsri if you would like to change the look of your X login
screen and/or X background. It is also used to display the default
background (Red Hat logo).
/usr/bin/xsri
/usr/share/doc/xsri-2.1.0
/usr/share/doc/xsri-2.1.0/README

Como se mencionó en el cuadro anterior, este es fundamentalmente un tipo diferente de solicitud.


El archivo de paquete, el cual podría o no ser instalado, está entregando la información no la base
de datos RPM.

Formatear información específica

¿Qué sucedería si usted quisiera generar una lista de los 10 paquetes más grandes instalados en
su sistema? Con el rpm -qai se vería el encabezado de información para cada paquete, el cual se
podría buscar con grep sólo para los tamaños, pero entonces necesitaría nombres. Podría agregar
nombres, pero luego el nombre y el tamaño estarían en líneas separadas. Usted capta la idea.

Afortunadamente, el comando rpm permite a los usuarios componer preguntas específicas al


especificar una cadena de formato de solicitud. La cadena está compuesta por un texto ASCII, pero
los símbolos de la forma %{fieldname} serán remplazados por el campo de información relevante.
¿Qué se puede utilizar como nombres archivados? Para los principiantes, cualquier campo hallado
en un encabezado de información de paquete, pero hay más. El comando rpm --querytags
retornará una lista completa (e intimidatoria) de los campos disponibles.

Para la tarea específica a la mano, prince realiza la siguiente solicitud, (observe que necesita
especificar explícitamente una nueva línea con \n).

[prince@station RPMS]$ rpm -qa --queryformat "%{size} %{name}\n"


0 basesystem
156498 expat
19248 libacl
111647 popt
1966 rootfiles
67679 cpio
162449 gzip
...

541
Justo la información que prince necesitaba. Con una sintaxis de %anchura{nombre de campo} se
puede especificar una anchura de campo opcional. Utilizando esto para limpiar su salida, y
entubándose a sort y a head, prince genera con facilidad una lista de los 10 paquetes más
grandes en su sistema.

[prince@station RPMS]$ rpm -qa --queryformat "%10{size} %{name}\n" |


sort -rn |
head
170890527 kernel-source
131431309 openoffice-i18n
100436356 openoffice-libs
84371104 gnucash
80018678 openoffice
75838208 rpmdb-redhat
55166532 Omni
54674111 tetex-doc
41939971 glibc-common
36762653 xorg

Ejercicios en línea Lab Exercise Objetivo: Familiarizarse con peticiones RPM

Tiempo estimado: 15 minutos.

Especificaciones

1. Cree el archivo ~/bash_files que contenga una lista de todos los archivos pertenecientes al
paquete bash listando un archivo por línea mediante referencias absolutas.
2. Cree el archivo ~/sshd_man, que liste los tres archivos que contengan las páginas de
manual asociadas con el paquete openssh-server, un archivo por línea mediante
referencias absolutas.
3. En el archivo incluya la palabra que mejor complete la siguiente oración. La biblioteca
/lib/libcap.so.1.* se utiliza para obtener y establecer POSIX.1e __________. (No se
preocupe si no entiende del todo la respuesta).
4. Cree el archivo ~/license_counts que presenta el número de ocurrencias de paquetes que
tienen licencia bajo una licencia determinada para las 5 licencias más utilizadas,
clasificadas en orden numérico descendente. Si se realiza correctamente, su archivo
debería estar formateado como el siguiente. (No se preocupe si las cuentas reales o
nombres de licencia son diferentes. También, usted podría notar lógicamente licencias
similares, tales como LGPL/GPL y GPL/LGPL. No intente combinarlas en una sola
entrada).

[prince@station prince]$ cat license_counts


355 GPL
147 LGPL
53 BSD
47 distributable
18 xorg

content_view let_
Deliverables A title Question 1

542
1. El archivo ~/bash_files, que contiene una lista de todos los archivos pertenecientes al
paquete bash, un archivo por línea, mediante referencias absolutas.
2. El archivo ~/sshd_man que contiene una lista de los tres archivos que proporcionan
páginas de manual para el paquete openssh-server, uno por línea, mediante referencias
absolutas.
3. El archivo ~/whatis_libcap que contiene la respuesta de una palabra para lo que la
biblioteca obtiene y establece.
4. El archivo ~/license_counts que presenta varias licencias bajo las cuales se distribuyen
los paquetes, seguido por el número de paquetes a los cuales se aplica la licencia,
clasificados en orden numérico descendente.

543
Users and Groups

Usuarios de Linux y el archivo /etc/passwd

Conceptos clave

• A un nivel inferior los usuarios son representados por un número entero llamado Id del
usuario (uid).
• Cada proceso que se desarrolla en el sistema se ejecuta como un uid dado
• Cada archivo en el sistema de archivos es propiedad de un uid
• El archivo /etc/passwdasigna los uids a las cuentas de usuario.
• Las cuentas de usuarios asignan los uids al nombre del usuario, contraseña, Id de Grupo
(s), directorio de inicio y shell de inicio.
• La contraseña se puede cambiar con el comando passwd .

Discussion

Los usuarios de Linux y el archivo /etc/passwd.

Cuando se utiliza un sistema Linux, usted primero se identifica al entrar con un nombre particular
de usuario nombre de usuario. Su nombre de usuario lo representa a usted. Está asociado con las
cosas que usted hace: cada proceso que se ejecuta en el sistema tiene un nombre de usuario
asociado. Está asociado con las cosas que usted grabe: cada archivo en el sistema está rotulado
como propiedad de un usuario particular. Está asociado con las cosas que usted utiliza: la cantidad
de espacio en el disco que utiliza o la cantidad de tiempo del procesador que usa, pueden ser
rastreados por el nombre de usuario.

Cada usuario en el sistema no sólo tiene un nombre de usuario único, sino también un userid, a
menudo abreviado como uid. Linux rastrea los userids como un número entero de 32bits, es decir
que puede haber más de 2^32 o cerca de 4 mil millones de usuarios. Mientras que a la gente le
gusta pensar en términos de palabras (nombres de usuarios), al Kernel de Linux se le facilita
pensar en términos de números (uids). Cuando el kernel mantiene el rastro de quién es el dueño
del proceso o del archivo, éste recuerda el uid en lugar del nombre del usuario. Sólamente cuando
algún comando produce salida para que la gente lea, el uid se convierte en el nombre de usuario.

El sistema mantiene una base de datos que asigna los nombres de usuarios a los userids. Esta
base de datos se almacena en el archivo de configuración /etc/passwd . Linux, al igual que Unix,
tiene una afortunada tradición: incluso los archivos principales de configuración en el sistema se
mantienen en un texto leíble por humanos y se pueden modificar con un editor de textos. Los
usuarios y administradores pueden usar herramientas sencillas para manejar texto, tales como los
paginadores para examinar las bases de datos. La mayoría de los usuarios en el sistema tiene
permisos para leer, pero no para modificar este archivo. A continuación se verán unas lineas de un
archivo típico/etc/passwd.

544
[elvis@station elvis]$ tail /etc/passwd
apache:x:48:48:Apache:/var/www:/bin/bash
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
webalizer:x:67:67:Webalizer:/var/www/html/usage:/sbin/nologin
elvis:x:501:501::/home/elvis:/bin/bash
prince:x:502:502::/home/prince:/bin/bash
madonna:x:504:504::/home/madonna:/bin/bash
blondie:x:505:505::/home/blondie:/bin/bash
sleepy:x:507:507::/home/sleepy:/bin/bash
grumpy:x:509:509::/home/grumpy:/bin/bash
doc:x:510:510::/home/doc:/bin/bash

El archivo /etc/passwd es una configuración de archivo con base en líneas, en donde cada línea
define un usuario en el sistema. Las líneas están divididas internamente en siete campos y cada
campo está separado por una coma. La siguiente tabla explica el uso de cada uno de estos
campos.

Nombre de Num Propósito


campo
Nombre de 1 El nombre de usuario se utiliza para dar un nombre leíble al usuario.
usuario
Contraseña 2 En los sistemas Unix más antiguos este campo contiene la contraseña del
usuario encriptada. Por defecto, Red Hat Enterprise Linux no hace uso de
este campo por razones de seguridad.
Id del usuario 3 El número entero que el kernel de Linux utiliza para identificar al usuario.
(uid)
Groupid 4 El número entero que el kernel de Linux utiliza para identificar al grupo
Primario (gid) primario del usuario. Las membresías del grupo se estudiarán en la
siguiente sección.
GECOS 5 Este campo con ese nombre tan raro ya no sirve su propósito original, el
cual era importante para el entorno de desarrollo original de Unix. En estos
días, el campo se utiliza para almacenar texto simple que ayuda a
identificar al usuario, generalmente un nombre completo, pero algunas
veces también incluye el número telefónico o la dirección.
Directorio de 6 Cuando un usuario inicia sesión, su shell de inicio la utilizará como su
inicio directorio actual de trabajo. Este es uno de los pocos directorios en los que
los usuarios estándar pueden escribir y generalmente son de uso privado
para el usuario.
Shell de 7 La shell de inicio de sesión es la shell predeterminada para los usuarios al
inicio de iniciar la sesión. En Red Hat Enterprise Linux es generalmente /bin/bash.
sesión

Los usuarios rara vez modifican este archivo directamente pero presentaremos varios comandos
que le permitirán al usuario cambiar ciertos campos. Si alguna vez necesita refrescar su memoria;
los campos están documentados en la página man passwd(5).

Las contraseñas y el archivo /etc/shadow.

Como se mencionó anteriormente la contraseña encriptada del usuario se solía almacenar en el


segundo campo del archivo /etc/passwd. Debido a que el archivo /etc/passwd no solo contiene
contraseñas, sino mucha más información, es necesario que todos puedan leerlo. Sin embargo,
con el moderno poder de la informática, el exponer la forma encriptada de su contraseña es
peligroso. Sin mucho esfuerzo, las máquinas modernas pueden tratar de adivinar su contraseña

545
encriptando todas las combinaciones de cada letra hasta encontrar la combinación exacta. Esto se
conoce como un ataque de "fuerza bruta".

En cambio los sistemas de Linux y Unix almacenan las contraseñas utilizando una nueva técnica
llamada "Shadow Passwords", donde las contraseñas de los usuarios se almacenan en un archivo
especializado /etc/shadow. Debido a que el archivo contiene sólo información relacionada con las
contraseñas, sus permisos no permiten ver su contenido. Para mayores detalles vaya a la página
man shadow(5) para obtener mayores detalles.

Los usuarios pueden cambiar su contraseña con un simple comando llamado passwd. Si usted no
es el usuario de root, el comando passwd no aceptará argumentos ni opciones. Su uso individual
permite al usuario cambiar su propia contraseña:

[madonna@station madonna]$ passwd


Changing password for user madonna.
Changing password for madonna
(current) UNIX password:
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

Observe que los usuarios necesitan suministrar su contraseña antes de poder cambiarla. Esto evita
que alguien tome aprovecho de una terminal abandonada por sólo unos segundos.

¡Recuerde su contraseña!

Si cambia su contraseña de Linux, ¡asegúrese de recordarla! Su contraseña nunca se


almacenará en el sistema en texto comprensible, incluso su administrador de sistemas no
puede conocer su contraseña. Si usted la olvida, alguien con privilegios de root le puede
crear una nueva.
Selección de una contraseña "segura"

Al escoger una nueva contraseña, con frecuencia los usuarios son amonestados con un
mensaje de BAD PASSWORD. Tradicionalmente, las contraseñas son susceptibles a un tipo
de ataque conocido como un ataque de "diccionarios", en donde un atacante encripta un
diccionario completo (tal como /usr/share/dict/words) y compara la salida encriptada con el
contenido del archivo/etc/shadow.

Para ayudar a evitar ataques de diccionarios, el comando passwd impedirá que los usuarios
utilicen contraseñas demasiado sencillas o fáciles de encontrar en un diccionario.

Hay tres tipos de usuarios: normal, root y sistema

Los usuarios de Linux suelen agruparse en tres clases.

Usuarios normales

Los usuarios normales representan gente real que utiliza el sistema, estos usuarios
normales generalmente tienen un /bin/bash como shell de inicio de sesión y un directorio
de inicio dentro del directorio /home. Por lo general, los usuarios normales pueden crear
archivos únicamente dentro de sus directorios de inicio y directorios temporales en todo el

546
sistema, tales como /tmp y /var/tmp.En Red Hat Enterprise Linux, los usuarios normales
tienen uids mayores a 500.

El usuario root

El uid 0 está reservado para root, algunas veces llamado el superusuario. El root es el rey
del sistema: puede modificar o remover cualquier archivo; ejecutar cualquier comando;
matar cualquier proceso. El usuario root está encargado de añadir y mantener otros
usuarios, configurar el hardware y agregar el software del sistema. Aunque puede crear
archivos en cualquier parte del sistema, generalmente utiliza su directorio de inicio /root.

Usuarios del sistema

La mayoría de los sistemas de Linux reservan un rango de valor bajo de uids para actuar
como usuarios del sistema. Los usuarios del sistema no representan gente, sino
componentes del sistema. Por ejemplo, los procesos que manejan el correo electrónico
usualmente operan como el nombre de usuario correo. Los procesos que ejecutan el
servidor de red Apache operan como el usuario apache. Los usuarios del sistema por lo
general no tienen una shell de inicio de sesión porque no representan gente real.
Asimismo, los directorios de inicio de los usuarios del sistema rara vez residen en /home,
sino que por lo general son directorios de sistema que pertenecen a la aplicación relevante.
Por ejemplo, el usuario Apache, tiene un directorio de inicio /var/www. En Red Hat
Enterprise Linux, los usuarios del sistema tienen uids que van de 1 a 499.

Table 1. Ids de usuarios de Red Hat Enterprise Linux

Rango de uid Tipo de usuario


0 el usuario root
1-499 usuarios del sistema
500+ usuarios normales

Ejemplos

Examen de los userids de procesos

El usuario elvis quiere averiguar que otra gente está utilizando el sistema Linux y lo que están
haciendo. Lista todos los procesos que están ejecutándose en la máquina actualmente.

547
[elvis@station elvis]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1380 76 ? S 03:33 0:04 init [
root 2 0.0 0.0 0 0 ? SW 03:33 0:00 [keventd]
root 3 0.0 0.0 0 0 ? SW 03:33 0:00 [kapmd]
...
root 872 0.0 0.1 5932 440 ? S 03:34 0:00
[sendmail]
smmsp 881 0.0 0.1 5732 312 ? S 03:34 0:00
[sendmail]
root 891 0.0 0.0 1420 56 ? S 03:34 0:00 gpm -t
ps/2 -m /d
root 900 0.0 0.0 1572 128 ? S 03:34 0:00 crond
xfs 973 0.0 0.0 4812 236 ? S 03:34 0:00 [xfs]
root 992 0.0 0.0 3412 4 ? S 03:34 0:00 rhnsd
--interval
root 999 0.0 0.0 1356 4 tty1 S 03:34 0:00
/sbin/mingetty tt
...
prince 1066 0.0 1.4 18428 3704 ? S 03:37 0:00 /usr/bin/
gnome-se
prince 1116 0.0 0.4 6136 1084 ? S 03:37 0:00
/usr/libexec/bono
prince 1118 0.0 0.6 17380 1716 ? S 03:37 0:00 gnome-
settings-da
prince 1123 0.0 0.1 2688 388 ? S 03:37 0:00 [fam]
prince 1128 0.0 0.4 3816 1032 ? S 03:37 0:02
xscreensaver -nos
prince 1135 0.0 2.1 20220 5440 ? S 03:37 0:06 gnome-
panel --sm-
prince 1137 0.0 3.9 86176 10048 ? S 03:37 0:04 nautilus
--no-def
prince 1145 0.1 3.0 26132 7900 ? S 03:37 0:13 /usr/bin/
python /
root 1146 0.0 0.0 1412 156 ? S 03:37 0:00
[pam_timestamp_c]
prince 1160 0.1 3.4 23208 8844 ? S 03:38 0:11 /usr/bin/
gnome-te
prince 1161 0.0 0.1 1852 284 ? S 03:38 0:00 [gnome-
pty-helpe]
prince 1162 0.0 0.1 4368 340 pts/0 S 03:38 0:00 bash
prince 1210 0.0 0.3 4372 964 pts/1 S 03:39 0:01 bash
prince 2262 0.4 8.0 99276 20476 pts/0 S 03:42 0:36 /usr/bin/
galeon-b
prince 2266 0.0 0.5 5652 1480 ? S 03:42 0:00 oafd
--ac-activat
prince 2818 0.0 0.3 4368 864 pts/2 S 04:17 0:00 bash
prince 3673 0.1 0.5 4356 1444 pts/4 S 05:46 0:00 bash
root 3699 0.0 0.3 4112 952 pts/4 S 05:46 0:00 [su]
elvis 3702 0.0 0.5 4312 1416 pts/4 S 05:46 0:00 -bash
elvis 3736 1.1 4.0 24572 10316 pts/4 S 05:46 0:00 evolution
elvis 3739 0.4 0.8 5664 2260 ? S 05:46 0:00 oafd
--ac-activat
elvis 3742 0.5 2.3 22548 6100 ? S 05:46 0:00 wombat --
oaf-acti
elvis 3746 0.3 1.6 11296 4288 ? S 05:46 0:00 bonobo-
moniker-xm
elvis 3753 1.0 3.4 57400 8916 ? S 05:46 0:00
evolution-mail --
elvis 3755 0.0 0.5 3260 1440 ? S 05:46 0:00 /usr/bin/
gconfd-1
elvis 3762 0.6 2.5 23052 6628 ? S 05:46 0:00
evolution-address
elvis 3766 0.5 2.5 23516 6560 ? S 05:46 0:00
evolution-calenda
elvis 3771 0.5 2.2 21336 5860 ? S 05:46 0:00
evolution-alarm-n
elvis 3773 0.6 2.3 21740 6104 ? S 05:46 548
0:00
evolution-executi
Algunas de las líneas en esta lista bastante larga fueron editadas y remplazadas por "...".

La primera columna de la lista muestra el nombre de usuario que está operando un proceso.
Además de prince, madonna y elvis, - elvis asume que son nombres de usuarios asociados con
gente real, elvis observa que muchos de los procesos en el sistema están ejecutando como el
usuario de root y también como usuarios smmsp y xfs.

Examen de los propietarios de archivo por nombre de usuario y userid.

La usuaria blondie está examinando el directorio /home y observa que cada directorio de inicio de
usuario le pertenece al nombre de usuario apropiado. Luego utiliza el comando ls -ln para listar el
directorio de propietarios "numéricamente"o por userid en lugar de por nombre de usuario. Preste
mucha atención a la tercera columna en la siguiente lista, la cual muestra un propietario de archivo.

[blondie@station blondie]$ ls -l /home/


total 48
drwx------ 4 blondie blondie 4096 May 14 06:35 blondie
drwx------ 4 doc doc 4096 May 14 06:32 doc
drwx------ 4 elvis elvis 4096 May 14 06:31 elvis
drwx------ 4 grumpy grumpy 4096 May 14 06:32 grumpy
drwx------ 4 madonna madonna 4096 May 14 06:31 madonna
drwx------ 4 prince prince 4096 May 14 06:31 prince
drwx------ 4 sleepy sleepy 4096 May 14 06:32 sleepy
[blondie@station blondie]$ ls -ln /home/
total 48
drwx------ 4 505 505 4096 May 14 06:35 blondie
drwx------ 4 510 510 4096 May 14 06:32 doc
drwx------ 4 501 501 4096 May 14 06:31 elvis
drwx------ 4 509 509 4096 May 14 06:32 grumpy
drwx------ 4 504 504 4096 May 14 06:31 madonna
drwx------ 4 502 502 4096 May 14 06:31 prince
drwx------ 4 507 507 4096 May 14 06:32 sleepy

En la lista ls -l, los propietarios de archivo son vistos por nombre de usuario. En la lista ls -ln, los
propietarios de archivo aparecen por userid.

Cambio de un nombre de usuario como root

El administrador de la máquina, actuando como root, desea editar el archivo /etc/passwd. Primero,
root tomará un ls -l de los archivos en el directorio /home. Luego, root cambiará el nombre del
usuario sleepy en la base de datos de usuarios y por último, mirará otra vez la salida del comando
ls -l.

549
[root@station root]# ls -l /home/
total 48
drwx------ 4 blondie blondie 4096 May 14 06:40 blondie
drwx------ 4 doc doc 4096 May 14 06:32 doc
drwx------ 4 elvis elvis 4096 May 14 06:31 elvis
drwx------ 4 grumpy grumpy 4096 May 14 06:32 grumpy
drwx------ 4 madonna madonna 4096 May 14 06:31 madonna
drwx------ 4 prince prince 4096 May 14 06:31 prince
drwx------ 4 sleepy sleepy 4096 May 14 06:32 sleepy
[root@station root]# nano /etc/passwd

(root edits the /etc/passwd file, so that the line ...

sleepy:x:507:507::/home/sleepy:/bin/bash

... now reads ...

sleepier:x:507:507::/home/sleepy:/bin/bash

... )

[root@station root]# ls -l /home/


total 48
drwx------ 4 blondie blondie 4096 May 14 06:40 blondie
drwx------ 4 doc doc 4096 May 14 06:32 doc
drwx------ 4 elvis elvis 4096 May 14 06:31 elvis
drwx------ 4 grumpy grumpy 4096 May 14 06:32 grumpy
drwx------ 4 madonna madonna 4096 May 14 06:31 madonna
drwx------ 4 prince prince 4096 May 14 06:31 prince
drwx------ 4 sleepier sleepy 4096 May 14 06:32 sleepy

En el primer caso el usuario propietario del directorio de inicio de sleepy /home/sleepy aparece
en la lista como sleepy.
En el segundo caso, el usuario propietario del directorio de inicio de sleepy aparecerá en la
lista como sleepier.

¿Qué se puede aprender de este ejemplo? root no cambió nada en /home/sleepy, sólo la base de
datos de usuarios. Sin embargo, tan pronto como el archivo modificado /etc/passwd se grabó, el
comando ls -l comenzó a reportar la nueva información. Esto sugiere lo siguiente:

1. El kernel de Linux no almacena el nombre de usuario del que posee el archivo, sino el
número entero del userid, (del ejemplo anterior, ¿cuál userid es propietario del directorio
/home/sleepy ?).
2. Cada vez que ejecuta el comando ls, debe buscar los trazados del nombre de
usuario/userid en el archivo /etc/passwd para anexar los nombres de usuario a los
propietarios de userid provistos por el kernel.

Ejercicios en línea Determinación de información del usuario Lab Exercise Objetivo:Determinar


los parámetros relacionados con el usuario tales como userid y shell de inicio. Estimated Time: 10
mins.

Especificaciones

550
Al examinar el primer, tercer y último campo (séptimo) del archivo /etc/passwd, determine el userid
y la shell de inicio para su nombre de usuario, el usuario root, y el usuario nobody (sí, hay un
usuario de sistema con el nombre de usuario"nobody"). Cree archivos sencillos en su directorio de
inicio llamado my.uid,my.shell, root.uid, root.shell, nobody.uid, y nobody.shell que contengan sólo la
información apropiada en una sola línea.

Por ejemplo, si el shell de inicio de sesión del usuario nobody fuera /bin/bash, el siguiente comando
crearía fácilmente el archivo apropiado.

[student@station student]$ echo /bin/bash > nobody.shell


[student@station student]$ cat nobody.shell
/bin/bash

Deliverables A title Question 1

Al terminar, los siguientes seis archivos deberían estar en su directorio de inicio, el cual contiene
content_view let_
sólo la siguiente información:

filename Contenido
my.uid Su número entero de userid de cuenta
my.shell Su shell de inicio
root.uid El número entero de userid de root
root.shell La shell de inicio del usuario root
nobody.uid El userid entero del usuario nobody
nobody.shell La shell de inicio del usuario nobody

551
Los grupos Linux y el archivo/etc/group.

Conceptos clave

• Básicamente, un grupo es solo un group id (gid) de un número entero


• Cada proceso que se ejecuta en el sistema opera bajo una colección de grupos (gids).
• El archivo /etc/groupasigna gids a nombres y a membresías de grupo.
• Cada archivo en el sistema de archivos pertenece a un solo gid.
• Los usuarios tienen un solo grupo primario definido en el archivo /etc/passwd.
• Los usuarios pueden ser miembros de múltiples grupos secundarios definidos en el archivo
/etc/groups.

Discussion

Grupos de Linux

La lección anterior presentó el hecho de que cada proceso se ejecuta bajo el contexto de un
usuario dado. Además, los usuarios, los procesos que estos operan y los archivos que poseen,
pertenecen a la colección de grupos-. Las membresías de grupo le permiten a los administradores
de sistemas manejar eficientemente las colecciones de los usuarios que tienen objetivos similares.

Cada usuario es miembro de un grupo primario. Además, los usuarios pueden ser miembros de
cero o más grupos secundarios. Las implicaciones de los grupos primarios o secundarios se
presentan a continuación.

El archivo /etc/group.

Para el kernel de Linux, un grupo es nombrado usando un id de grupo (GID) de 32 bits, (note la
similitud con que el kernel referencia los usuarios). El archivo /etc/groupasocia nombres de grupo
con GIDs (para humanos) y define los usuarios que pertenecen a cada grupo. El archivo /etc/group,
juega un papel similar para los grupos así como el archivo /etc/passwd lo es para los usuarios,
tiene una estructura similar, y un nombre más razonable. Es un archivo de configuración con base
en líneas, cada línea consta de campos separados por una coma así como se demuestra a
continuación.

wrestle:x:201:ventura,hogan,elvis
physics:x:202:einstein,maxwell,elvis
emperors:x:203:nero,julius,elvis
governor:x:204:ventura,pataki
music:x:205:elvis,blondie,prince,madonna
dwarfs:x:206:sleepy,grumpy,doc
elvis:x:501:
prince:x:502:
madonna:x:504:
blondie:x:505:

552
Los cuatro campos proporcionan la siguiente información:

Nombre de campo Num Propósito


Groupname 1 El nombre de grupo se utiliza para dar al grupo un nombre legible.
Contraseña de 2 Los grupos pueden contar con una contraseña de grupo aunque esto
grupo sucede raras veces.
Grupo ID (GID) 3 El número entero de grupo id.
Miembros de 4 Una lista de nombres de usuarios separados por comas que define
grupo los miembros del grupo.

¿Por qué grupos?

Las membresías de grupo se utilizan muy a menudo para determinar quién tiene acceso a qué en
el sistema de archivo. Los dwarfs que se encuentran en el siguiente ejemplo del archivo /etc/group
doc, grumpy, y sleepy, podrían estar trabajando en mis prospectos y no querrán que otros usuarios
tengan acceso a su información. Los archivos que están utilizando (y los directorios en los que
están almacenándolos) pueden organizarse de tal manera que cada miembro del grupo dwarfs
tenga acceso a ellos, pero otros usuarios no.

El hecho de que cada archivo en el sistema pertenezca a un usuario ya se ha mencionado


anteriormente. Cada archivo en el sistema también pertenece a un grupo, al cual se alude como
"grupo propietario". En la siguiente lista de archivos ls -len el directorio /var/prospects, la tercera
columna lista al usuario propietario de los archivos y la cuarta columna el grupo propietario.

[doc@station prospects]# ls -l /var/prospects/


total 12
-rw-rw---- 1 doc dwarfs 143 May 15 07:38 doc.txt
-rw-rw---- 1 grumpy dwarfs 29 May 15 07:38 grumpy.txt
-rw-rw---- 1 sleepy dwarfs 2027 May 15 07:38 sleepy.txt

Mientras que los usuarios individuales poseen sus propios archivos, cada archivo tiene al grupo
dwarfs como su propietario de grupo o en otras palabras, cada archivo es "propiedad" del grupo
dwarfs. La primera columma especifica los permisos que tienen el usuario propietario y los
miembros del grupo dueños del archivo. ¿Pueden leerlo? ¿Pueden modificarlo? ¿Cómo interpretar
y manejar estos permisos es el tema del próximo cuaderno. Por ahora, tenga en cuenta quecada
archivo en el sistema de archivos tiene un usuario propietario y un grupo propietario.

Grupos primarios y secundarios

Debido a que cada archivo debe tener un grupo propietario, debe haber un grupo por defecto
asociado con cada usuario. Este grupo por defecto se convierte en el propietario del grupo de los
archivos recién creados. Este grupo se conoce como el grupo primariodel usuario. Un grupo de
usuario primario se define en el cuarto campo de una entrada de usuario /etc/passwd.

Aparte del grupo primario, los usuarios pueden optar también por pertenecer a otros grupos. Estos
grupos se llaman grupos secundariosy están definidos (por coincidencia) en el cuarto campo del
archivo /etc/group file.

Considere los siguientes extractos de los archivos /etc/passwd file y /etc/group.

553
[elvis@station elvis]$ tail /etc/passwd
grumpy:x:509:509::/home/grumpy:/bin/bash
doc:x:510:510::/home/doc:/bin/bash
student:x:2299:2299::/home/student:/bin/bash
ventura:x:511:511::/home/ventura:/bin/bash
hogan:x:512 :512 ::/home/hogan:/bin/bash
pataki:x:513:513::/home/pataki:/bin/bash
einstein:x:514:514::/home/einstein:/bin/bash
maxwell:x:515:515::/home/maxwell:/bin/bash
nero:x:516:516::/home/nero:/bin/bash
julius:x:517:517::/home/julius:/bin/bash
[elvis@station elvis]$ cat /etc/group
...
wrestle:x:201:ventura,hogan ,elvis
physics:x:202:einstein,maxwell,elvis
emperors:x:203:nero,julius,elvis
governor:x:204:ventura,pataki
...
hogan:x:512:
pataki:x:513:
einstein:x:514:
maxwell:x:515:
nero:x:516:
julius:x:517:

En la toma de pantalla anterior se han omitido algunas líneas y se han reemplazado con "...".

En el tercer campo encontramos que el usuario hogan tiene un userid de 512.

En el cuarto campo encontramos que el usuario hogan tiene un id de grupo primario de 512,
(observe que el id del grupo primario hogan es el mismo que su id de usuario. Esto no tiene
que ser el caso, pero lo es a menudo debido a la forma en que se adicionan los usuarios en
Red Hat Enterprise Linux).
Aunque sabemos que el grupo primario de hogan es 512 desde el archivo /etc/passwd, no
podemos conocer el nombre del grupo hasta examinar el archivo/etc/group. Aquí encontramos
que el nombre de grupo del grupo 512 es hogan. En Red Hat Enterprise Linux,el grupo
primario de un usuario casi siempre tiene el mismo nombre del nombre de usuario.
Aquí encontramos que hogan también es miembro del grupo wrestlers. El grupo wrestlers es
un grupo secundario.

En resumen, se puede decir lo siguiente acerca de los grupos primarios y secundarios.

• Un groupid primario se define en el cuarto campo del archivo/etc/passwd. Luego, el


nombre del usuario del grupo primario se asocia con el groupid en el archivo /etc/group.
• Los usuarios de grupos secundarios se definen al adicionar el nombre de usuario al cuarto
campo de las líneas apropiadas en el archivo/etc/group.

¿Cómo puedo cambiar mis membresías de grupo?

554
Los usuarios estándar no tienen permiso para editar el archivo /etc/passwd ni el archivo /etc/group
y por lo tanto, no pueden cambiar las membresías de grupo. Únicamente el usuario administrativo
root, puede cambiar las membresías de grupo.

Si usted no tiene acceso a la máquina como root, las asociaciones de grupo se pueden modificar
utilizando los comandos usermod ygroupmod o la utilidad gráfica system-config-users. El uso
de estos comandos se verá en otro curso.

Ejemplos

¿Quiénes son miembros de ese grupo?

En la siguiente lista del directorio /var/spool, prince observa que el grupo "sys" es propietario del
directorio /var/spool/cups.

[prince@station prince]$ ls -l /var/spool/


total 64
...
drwx------ 2 root root 4096 Feb 19 08:39 cron
drwx------ 3 lp sys 8192 May 21 12:36 cups
drwxr-xr-x 23 root root 4096 Jan 24 18:52 lpd
drwxrwxr-x 2 root mail 4096 May 21 10:55 mail
...

El usuario prince ahora se está preguntando cuál de los usuarios del sistema es miembro de los
grupos sys. Con el fin de averiguarlo, examina el archivo /etc/group.

[prince@station prince]$ head /etc/group


root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:

Al examinar la cuarta línea, prince determina que los usuarios root, bin y adm son los miembros
actuales del grupo sys.

¿A qué grupos pertenece el usuario ?

El usuario prince desea averiguar a qué grupos pertenece el usuario root. Debido al formato del
archivo /etc/group, no puede determinar la respuesta al examinar una sola línea. Decide, entonces,
buscar la palabra "root" en el archivo.

555
[prince@station prince]$ cat /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
...
Después de una inspección tediosa de la salida, prince decide que root pertenece a los siguientes
grupos: root, bin, daemon, sys, adm, disk y wheel y piensa para sí que "debe haber una forma más
fácil", (esperemos que prince lea la siguiente lección).

Ejercicios en línea Determinación de membresías de grupo Lab Exercise Objetivo: determinar las
membresías de grupos localmente definidos.Estimated Time: 10 mins.

Especificaciones

Crea un archivo en su directorio de inicio llamado physics.txt, el cual contiene una lista de los
miembros del grupo physics, separados por espacios.

Por ejemplo, si elvis, blondie, y prince fueran los miembros de un grupo physics, el siguiente
comando crearía fácilmente dicho archivo.

[student@station student]$ echo "blondie elvis prince" > physics.txt


[student@station student]$ cat physics.txt
blondie elvis prince
Deliverables A title Question 1

Un archivo ~/physics.txt que contenga una lista del grupo physics, separado por espacios.

Determinación de los grupos a los que un usuario está suscritos (la forma difícil) Lab Exercise
Objetivo:Determinar los grupos a los cuales pertenece un usuario definido localmente. Estimated
Time: 10 mins.

Especificaciones

Crea un archivo en su directorio de inicio llamado elvisgrp.txt, el cual contiene una lista de los
grupos a los que el usuario elvis pertenece.

Por ejemplo, si elvis perteneció a los grupos sys, music, y elvis, entonces el siguiente comando
crearía fácilmente dicho archivo.

[student@station student]$ echo "elvis music sys" > elvisgrp.txt


[student@station student]$ cat elvisgrp.txt
elvis music sys
Deliverables A title Question 1

556
El archivo ~/elvisgrp.txtque contiene una lista de los grupos a los que el usuario elvis pertenece.

557
Revisar la información del usuario

Conceptos clave

• El comandoid muestra la información del grupo y del usuario.


• El comando whoamiinforma el nombre del usuario actual.
• Los comandos who, users, y w informan sobre usuarios con sesiones activas.
• El comando finger reporta la última vez que los usuarios entraron al sistema y otra
información adicional.

Discussion

Identificacion de usuarios: el comando id.

La lección anterior presentó los conceptos de grupos y la manera cómo los archivos /etc/passwdy /
etc/groupdefinen las membresías de grupo. Debido a que la determinación de las membresías de
grupos desde estos archivos no se hace directamente, los usuarios suelen utilizar el comando id
para determinar la información sobre un usuario.

id [[-g] | [-G] | [-u]] [-n] [NOMBRE DE USUARIO]

Escribe información para el NOMBRE DE USUARIOo el usuario actual.

Opción Efecto
-g,--grupo Escribe únicamente el id de grupo
'G,--grupos Escribe todos los ids de grupo
-u, --user Escribe sólo el identificador de usuario efectivo
-n, --name Imprime el nombre del usuario o del grupo en lugar del número.

Si se llama sin argumentos, el comando id entrega un resumen de membresías de grupo para el


usuario que lo ejecuta. Si está provisto del nombre de usuario, el comando id entrega información
del grupo para ese usuario específico.

[elvis@station elvis]$ id
uid=501(elvis) gid=501(elvis) groups=501(elvis),203(emperors),205(music)
[elvis@station elvis]$ id blondie
uid=505(blondie) gid=505(blondie) groups=505(blondie),205(music)

Por defecto, el comando presenta el identificador de usuario, el grupo primario y todos los grupos
(primario y secundario) a los cuales pertenece el usuario, tanto por nombre de grupo como por id
de grupo.

La salida del comando id puede calificarse con las opciones, como se resume en la tabla anterior.
Por ejemplo, si un usuario solo quizo saber el id del grupo primario de un usuario, el comando
podría ser invocado con la opción -g. Si el usuario quizo conocer el nombre del grupo en lugar del
número, la opción -n también podría especificarse. De la misma manera, la opción -G reportará
todos los grupos , no sólo el grupo primario. Estas líneas de comando son muy útiles cuando el
comando id se utilizado en scripts.

558
[elvis@station elvis]$ id -g blondie
505
[elvis@station elvis]$ id -gn blondie
blondie
[elvis@station elvis]$ id -Gn blondie
blondie music

El comando whoami .

El comando whoami simplemente entrega el nombre del usuario actual.

whoami

Escribe el nombre del usuario actual.

En Red Hat Enterprise Linux, muy pocas veces hay la necesidad de usar el comando whoami,
porque el intérprete de comandos por defecto bash presenta de inmediato el nombre de usuario
del usuario actual. El intérprete de comandos es configurable, sin embargo, en otros sistemas de
Linux y Unix o en otros entornos (tales como shells de rescate), la identidad del usuario podría no
ser tan obvia. También el comando whoami puede estar insertado en un script, el cual podría tener
un comportamiento diferente dependiendo de quién lo está ejecutando.

¿Quién tiene una sesión abierta? Los comandos users, wy who.

Si un usuario quisiera saber quién más está usando una máquina Linux o Unix en particular. Red
Hat Enterprise Linux, provee tres comandos que reportan los usuarios actuales, cada uno con un
nivel diferente de detalle. El más sencillo de estos es el comando users.

users

Hace una lista sencilla de quienes están conectados al sistema.

Puede que el usuario elvis quiera saber quién más está conectado a la máquina.

[elvis@station elvis]$ users


blondie elvis elvis elvis elvis elvis prince root

El comando reporta que blondie, elvis, prince y root están actualmente conectados a la máquina.
¿Por qué elvis aparece en la lista cinco veces? Unix tradicionalmente asocia toda la actividad
desde una sola terminal con lo que técnicamente se llama "sesión". Al utilizar el entorno gráfico X,
cada ventana de una terminal abierta se considera una terminal distinta y por lo tanto, una sesión
diferente. El usuario elvis probablemente está usando terminales múltiples dentro de X windows.

w [[-h] | [-s] | [-f]] [NOMBRE DE USUARIO]

559
Escribe información detallada de quien está actualmente conectado o para el usuario USERNAME,
si es dado.

Opción Efecto
-h salta la cabecera
-s una lista corta
-f no muestra el campo "FROM".

Al igual que el comando users, el comando w lista los usuarios que están conectados en el
sistema, pero provee mucha más información detallada como lo demuestra el usuario elvis:

[elvis@station elvis]$ w
12:58:58 up 1 day, 3:32, 8 users, load average: 0.01, 0.04, 0.04
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty2 - 12:45pm 13:19 0.05s 0.05s -bash
prince tty1 - 12:45pm 13:01 4.63s 4.60s top
elvis rain.rdu station.redhat.c 9:44am 0.00s 5:42 1.58s /usr/bin/gnome
elvis pts/0 station.redhat.c 9:59am 1:05m 5.33s 3.05s mutt
elvis pts/2 station.redhat.c 11:24am 1.00s 0.99s 57.08s /usr/bin/gnome
elvis pts/4 station.redhat.c 11:10am 1:05m 0.20s 0.20s bash
elvis pts/5 station.redhat.c 11:29am 12:37 15.90s 0.16s ssh root
blondie pts/6 station.redhat.c 12:46pm 12:37 0.05s 0.05s -bash

La línea superior da la información resumida: el tiempo actual, el tiempo en días, horas y minutos
que la máquina ha estado funcionando sin interrupciones, el número de usuarios y el promedio
actual de carga (como un promedio de 1.5 y 15 minutos) para la máquina. El comando luego
presenta una tabla con la siguiente información.

Columna Información
USER El nombre de usuario del usuario que está conectado.
TTY La terminal desde donde el usuario está conectado, (la interpretación de las terminales
se discute en el cuaderno 1).
FROM Si el usuario está conectado a la red, el nombre del anfitrión desde donde el usuario
está conectado.
LOGIN@ La hora en que el usuario inició la sesión.
IDLE El tiempo que ha transcurrido desde la última interacción en la terminal.
JCPU La cantidad de tiempo CPU consumido por todos los procesos que están ejecutándose
en el momento asociados con la sesión de la terminal.
PCPU La cantidad de tiempo de CPU consumido por sólo el proceso actual, como se le llama
en el campo "WHAT".
WHAT El proceso del usuario, ejecutándose actualmente.

El último de estos tres comandos similares, who,también provee información detallada acerca de
quién está conectado en el momento. Si se llama sin argumentos, se comporta de una manera
similar al comando w. El comando who también está diseñado para reportar eventos del sistema
tal como el nivel de ejecución actual, ajustes al sistema del reloj y procesos generados por el
proceso /sbin/init. Mucha de esta información va más allá del alcance de este curso.

Revisión de usuarios: el comando finger.

Uso del comando finger.

560
El comando fingerse puede utilizar para "chequear" al usuario, no sólo para ver si está conectado,
sino también si ha leído su correo y la hora en que inició la sesión, entre otras cosas.

finger [[-s] | [-l] | [-p]] [USUARIO...] [USER@HOST ...]

Escribe la información sumaria acerca del usuario específico, incluyendo si ha entrado al sistema,
si ha revisado su correo o hace una lista de todos los usuarios en el sistema si no se proporciona
ninguno.

Opción Efecto
-s Salida en formato sumario
-l Salida en formato largo
-p No muestre la información ".plan", ".project", etc.

A manera de ejemplo, el usuario elvis usa el comando finger para ver quién está en el sistema.

[elvis@station elvis]$ finger


Login Name Tty Idle Login Time Office Office Phone
madonna *:0 May 26 06:40
madonna pts/0 28 May 26 06:40 (:0.0)
madonna pts/1 20 May 26 06:41 (:0.0)
madonna pts/2 May 26 06:50 (:0.0)
madonna pts/3 3 May 26 07:04 (:0.0)
elvis tty1 May 26 07:09
prince tty2 May 26 07:10

Sin argumentos el comando finger actúa de manera muy parecida al comando who, dando
información sumaria incluyendo la de la terminal del usuario (Tty), la hora de inicio y el tiempo de
inactividad.

Ahora elvis nota que su amiga blondie no está conectada y decide buscar más información acerca
de ella.

[elvis@station elvis]$ finger blondie


Login: blondie Name: (null)
Directory: /home/blondie Shell: /bin/bash
Never logged in.
No mail.
No Plan.

En este caso el comando finger entrega información sumaria sobre la usuaria blondie, incluyendo
el hecho de que ella nunca ha estado en el sistema y que no tiene correo en espera.

Personalización de la salida del comando finger.

Cuando elvis decide chequear al usuario prince, el comando finger proporciona mucha más
información.

561
[elvis@station elvis]$ finger prince
Login: prince Name: (null)
Directory: /home/prince Shell: /bin/bash
On since Mon May 26 07:10 (EDT) on tty2 10 minutes 30 seconds idle
New mail received Mon May 26 07:17 2003 (EDT)
Unread since Wed May 14 06:31 2003 (EDT)
Plan:

12:00 - 1:00 lunch


1:00 - 3:00 in class
3:30 - 4:30 ultimate frisbee

Debido a que prince está conectado en el momento, el comando finger entrega al usuario, la
terminal, la hora de acceso al sistema y el tiempo de inactividad.
El comando finger reporta la úĺtima hora en que el usuario recibió correo y la última vez que lo
leyó, (observe que no sólo funciona si la máquina está configurada para recibir correo-e
directamente, sino que utiliza una cuenta POP provista de un proveedor del servicio de
Internet).
El usuario prince ha creado un archivo ~/.plan que el comando finger reporta.

Un usuario puede personalizar la información que otra persona ve cuando está en finger, creando
archivos ocultos en su directorio de inicio. El comando finger conoce los siguientes archivos.

Nombre de Propósito
archivo
.plan Aparece en pantalla con el comando finger bajo el título "Plan:".
.project Aparece en pantalla con el comando finger bajo el título "Project:".
.pgpkey Aparece en la pantalla gracias al comando finger bajo el título "PGP Key:". Sirve
para que el usuario publique una parte de la clave pública de una clave
pública/privada que se utiliza en la encripción de la clave pública.

Permiso de acceso a su directorio de inicio

Por defecto en Red Hat Enterprise Linux, el directorio de inicio de un usuario no tiene acceso a los
otros directorios de inicio que se encuentran en el sistema . Para que el comando finger encuentre
estos archivos, un usuario debe habilitar los permisos de ejecución en su directorio de inicio
usando un comando similar al siguiente:

[prince@station prince]$ chmod o+x ~


Este tema se tratará a profundidad en el Cuaderno 4.

Utilización del comando finger en la red.

El comando finger también puede reportar la actividad de un usuario en máquinas remotas. El


usuario elvis desea ver lo que va a hacer el usuario pataki en la máquina nimbus.example.com.

Para que este comando


[elvis@station funcione,
elvis]$ la máquina
finger remota nimbus.example.com debe optar por utilizar
pataki@nimbus.example.com
Login: pataki Name: (null)
Directory: /home/pataki Shell: /bin/bash
Never logged in.
New mail received Mon May 26 07:41 2003 (EDT)
Unread since Wed May 14 15:34 2003 (EDT)
Plan:
Balance the budget.

562
Ejemplos

Utilización del comando idpara determinar las membresías de grupo.

La usuaria blondie ha enviado un correo electronico a su administrador pidiendo unirse al grupo de


music. Al entrar el siguiente día, quiere saber si el administrador lo hizo. Para averiguarlo, blondie
ejecuta el comando id.

[blondie@station blondie]$ id
uid=505(blondie) gid=505(blondie) groups=505(blondie),205(music)

blondie ve que ha sido agregada al grupo music.

Ponerse al corriente con elvis.

La usuaria blondie quiere ponerse al corriente con el usuario elvis. Ella averigua si elvis está
conectado al sistema utilizando el comando w.

[blondie@station blondie]$ w
08:05:50 up 1:28, 7 users, load average: 0.00, 0.15, 0.34
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
prince tty2 - 9:10am 55:48 0.05s 0.05s -bash
elvis tty1 - 9:09am 55:52 0.01s 0.01s -bash
blondie :0 - 8:40am ? 0.00s 0.83s /usr/bin/gnome-
blondie pts/0 :0.0 8:40am 8:27 10.23s 0.10s bash
blondie pts/1 :0.0 8:41am 2:03 0.54s 0.54s bash
blondie pts/2 :0.0 8:50am 0.00s 0.56s 8.06s /usr/bin/gnome-
blondie pts/3 :0.0 9:04am 59:28 0.20s 8.06s /usr/bin/gnome-

Blondie observa que elvis está conectado pero tiene un tiempo inactivo de cerca de una hora. Al
tratar de decidir si elvis está realmente sentado frente a la terminal, utiliza el comandofinger.

[blondie@station blondie]$ finger elvis


Login: elvis Name: (null)
Directory: /home/elvis Shell: /bin/bash
On since Mon May 26 07:09 (EDT) on tty1 1 hour 6 minutes idle
New mail received Mon May 26 06:53 2003 (EDT)
Unread since Wed May 14 06:31 2003 (EDT)
Plan:

9:30 - 10:30 Team meeting


12:30 - 1:30 Lunch

Al ver que elvis ha puesto en la lista una reunión a las 9;30, blondie asume que elvis no está en la
terminal, pero que quedó conectado.

Personalización de la información de finger.

563
El usuario prince desea personalizar lo que los usuarios ven si ellos ejecutan finger. El sabe que
primero necesita permitir el acceso a su directorio de inicio.

[prince@station prince]$ chmod o+x ~

Luego, prince genera un archivo .plan.

[prince@station prince]$ nano ~/.plan

...( dentro del editor nano, prince crea el siguiente archivo )...

Convertirse en la primera persona en instalar Red Hat Enterprise Linux


en la luna.

...( y guarda el archivo como ~/.plan) ...

[prince@station prince]$ cat ~/.plan


Convertirse en la primera persona en instalar Red Hat Enterprise Linux
en la luna.

Por último, prince rutinariamente firma su correo-e con la clave privada GPG. Le gustaría que el
comando finger reportara su clave pública para que la gente pudiera verificar su firma.

[prince@station prince]$ gpg --export -a prince > ~/.pgpkey

Para confirmar su configuración, él decide ejecutar el comando finger para sí mismo.

[prince@station prince]$ finger prince


Login: prince Name: (null)
Directory: /home/prince Shell: /bin/bash
On since Mon May 26 07:10 (EDT) on tty2
New mail received Mon May 26 07:17 2003 (EDT)
Unread since Wed May 14 06:31 2003 (EDT)
PGP key:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.1 (GNU/Linux)

mQGiBD7SCMcRBADqfVCpDz/h4ky/K0y2aJoJXaBMRn1KG5fro8PRXa/mH8/ToR9h
n3PdJGCV4glJnMfG2II6+HTm5kgTbg+ACZyvP9JBDGqMpbA2kCQk2RjEEArkL8d4
...
R1ujp1rJ8gCfUtM9p6A5yx5FpPQrsCtKRuurixo=
=315x
-----END PGP PUBLIC KEY BLOCK-----
Plan:
Become the first person to install Red Hat Enterprise Linux on the moon.

Observe que se han borrado varias líneas y se remplazaron con "...".

Contactar el servidor de finger, finger.kernel.org

564
Algunas veces, los sitios de Internet reconfigurarán su servicio finger de esta manera que en vez
de listar a todos los usuarios conectados en ese momento, el servicio presente una pequeña
cantidad de información. (por lo general cambiante). La usuaria Madonna utiliza el comando finger
para preguntarle a finger.kernel.org por las últimas versiones del kernel de Linux.

[madonna@station madonna]$ finger @finger.kernel.org


The latest stable version of the Linux kernel is: 2.4.20
The latest prepatch for the stable Linux kernel tree is: 2.4.21-rc3
The latest beta version of the Linux kernel is: 2.5.69
The latest snapshot for the beta Linux kernel tree is: 2.5.69-bk19
The latest 2.2 version of the Linux kernel is: 2.2.25
The latest 2.0 version of the Linux kernel is: 2.0.39
The latest prepatch for the 2.0 Linux kernel tree is: 2.0.40-rc6
The latest -ac patch to the stable Linux kernels is: 2.4.21-rc2-
ac3
The latest -ac patch to the beta Linux kernels is: 2.5.69-ac1
The latest -dj patch to the beta Linux kernels is: 2.5.69-dj1

Ejercicios en línea

Listado de grupos con el comando id. Lab Exercise Objetivo: Listar las membresías de grupo con
el comando id.Tiempo estimado: 5 minutos.

Especificaciones

Redireccione la salida del comando idpara crear un archivo en su directorio de inicio llamado
mygroups.txt. Utilice el comando apropiado para cambiar la línea de comando, de tal manera que
sus grupos suscritos (primarios y secundarios) aparezcan en una sola línea, separados por un solo
espacio.

Por ejemplo, si los ejercicios se han completado correctamente, el archivo debería tener un formato
similar al siguiente.

[student@station student]$ cat mygroups.txt


student wrestle physics

Deliverables A title Question 1

Un archivo ~/mygroups.txtque contenga sus grupos suscritos, separados por un espacio en una
sola línea.

Creación de un .plan para el comandofinger. Lab Exercise Objetivo: Crear una respuesta
personalizada para el comando finger.Estimated Time: 10 mins.

Especificaciones

Utilización de un editor de texto o una redirección sencilla del comando echo para crear un archivo
.plan, de tal manera que cuando los usuarios utilicen el comando finger, puedan ver los contenidos
de su plan. Utilice una de sus cuentas alternas para confirmar su configuración.

565
Para que este ejercicio funcione, usted debe permitir que otros usuarios tengan acceso a su
directorio de inicio utilizando el comando chmod o+x ~.

Deliverables A title Question 1

1. Permisos en su directorio de inicio autorizando a otros usuarios la entrada a archivos


dentro de éste.
2. Un archivo llamado ~/.planen su directorio de inicio con contenido que se puede ver con el
comando finger.

Possible Solution

El siguiente comando da una posible solución a este ejercicio.

[student@station student]$ chmod o+x ~


[student@station student]$ echo "Complete exercise two successfully" > ~/.plan
[student@station student]$ cat ~/.plan
Ejercicio 2 completo a satisfacción

Al entrar en la consola virtual con una de sus cuentas alternas, debería poder ver su plan como
salida del comandofinger.

[student_a@station student_a]$ finger student


Login: student Name: (null)
Directory: /home/student Shell: /bin/bash
Never logged in.
No mail.
Plan:
Complete exercise two successfully

Limpieza

Al final de este ejercicio, usted puede cerrar su directorio de inicio restaurando los permisos
originales con chmod o-x ~ (¿Qué ven los otros usuarios en respuesta al comando fingeren este
caso?).

Cambio de identidad

Conceptos clave

• El comando su le permite a un usuario cambiar el id del usuario.


• El comando su, usualmente se llamado con un guión, así como en su -para especificar
que, en efecto, el usuario debería iniciar la sesión como el nuevo usuario.
• El comando newgrp, también llamado sg, permite al usuario cambiar el id degrupo
primario.

Discussion

Cambio de identidad

566
A menudo en Linux, a un usuario le gustaría convertirse temporalmente en otro usuario. Puede que
necesite cambiar los permisos a un archivo del cual no es dueño o puede que un amigo quiera
utilizar su terminal por un momento. El comando que le permite temporalmente cambiar su id de
usuario se llama su.

su [[-] | [-c] | [-m, -p] | [-s, --shell=SHELL]] [USER [ARG]]

Cambie el userid al USUARIO específicado o a root si ahora el USUARIO se especifica.

Opción Efecto
- haga de la shell una shell de inicio.
-c ejecute el comando específico y regrese
-m,-p Preserve el entorno actual
-s, --shell=SHELL Utilice SHELL como la nueva shell de usuario

Convertirse temporalmente en otro usuario puede ser tan simple como "su" a ese usuario.

[elvis@station elvis]$ su prince


Password:
[prince@station elvis]$

Observe los obvios problemas de seguridad. Las propiedades y permisos de usuarios no tendrían
sentido si los usuarios pudieran usar su cuando quisieran. Para convertirse en el usuario prince,
era necesario que elvis conociera la contraseña de prince.

Al utilizar el comando su, la nueva shell se convierte en la shell de prince y los procesos iniciados
desde la shell le pertenecen a prince. Sin embargo, la shell se llama una shell de no-inicio, prince
no se registró totalmente- el intérprete de comandos indica que él aún está en el directorio de inicio
de elvis. Aunque la shell y todo lo que ésta inicie, pertenece a prince gran parte del entorno de la
shell fue heredado de elvis.

Para iniciar la sesión como usuario nuevo puede llamar al comando su con un - (un guión simple).
Este especifica que la shell del nuevo usuario debe ser una shell de inicio.

[elvis@station elvis]$ su - prince


Password:
[prince@station prince]$

En este caso prince ha ingresado efectivamente, para que el nuevo directorio de trabajo actual de
la shell sea el directorio de inicio de prince, y el entorno de prince se haya inicializado desde su
propia configuración.

La diferencia entre una shell de inicio y una de no-inicio y el uso de las variables de entorno, se
verá con más detalle en otro cuaderno. Por ahora, sólo tenga en cuenta que para llegar a ser
completamente un nuevo usuario, el comando su debería llevar un - y un nombre de usuario.

Convertirse en root

567
Usualmente,un usuario debe ser root para configurar(o arreglar) una máquina Linux. Para
convertirse de un usuario normal a un usuario root, el usuario debe conocer la contraseña de root y
usar el comando "su". Si el comando su se utiliza sin argumentos, éste asume que el usuario está
tratando de convertirse en root.

[elvis@station elvis]$ su -
Password:
[root@station root]#

Debido a que el comando su se llamó con un -, la nueva shell de root comienza en el directorio de
inicio. También observe el cambio sutil en el intérprete de comandos bash. Cuando la shell está se
ejecuta como root, el intérprete de comandos usa "#" en lugar de "$".

El "superusuario"

En Linux y Unix, la cuenta de root se conoce algunas veces como el "superusuario". Este
término probablemente surgió de un malentendido del significado de las letras del comando
su, las cuales se utilizan para convertirse en root. En lugar de superusuario, las letras
significan switch userid - cambio de userid.

Cambio de grupo primario con el comando newgrp (o sg).

En las lecciones anteriores hablamos del papel del grupo primario. Para repasar, cada usuario
tiene un grupo primario como se define en el archivo/etc/passwd y los archivos recién creados son
grupos pertenecientes a un usuario del grupo primario. Algunas veces, puede que los usuarios
quieran convertir uno de sus grupos secundarios en primario para que los archivos recién creados,
sean propiedad de ese grupo. El comando newgrp, equivalente al comando llamado sg hace
justamente esto.

newgrp [[GROUP]]

Genera una nueva shell con GROUP como su grupo primario. Si GROUP no se especifica, utilice
el grupo primario por defecto.

En la siguiente secuencia de comandos, prince creará un nuevo archivo, luego utilizará el comando
newgrppara generar una nueva shell con un grupo primario de music. En la nueva shell, prince
creará otro archivo, el cual pertenecerá al grupo music, prince luego abandonará la nueva shell.

568
[prince@station prince]$ id
uid=502(prince) gid=502(prince) groups=502(prince),205(music)
[prince@station prince]$ date > foo
[prince@station prince]$ ls -l
total 4
-rw-rw-r-- 1 prince prince 29 May 26 12:26 foo
[prince@station prince]$ newgrp music
[prince@station prince]$ id

uid=502(prince) gid=205(music) groups=502(prince),205(music)


[prince@station prince]$ date > biz
[prince@station prince]$ ls -l
total 8

-rw-r--r-- 1 prince music 29 May 26 12:26 biz


-rw-rw-r-- 1 prince prince 29 May 26 12:26 foo
[prince@station prince]$ exit

Observe que después de ejecutar el comandonewgrp, el comando id está reportando al grupo


primario de prince como "music".
El archivo biz, creado cuando el grupo primario de prince era music, es propiedad del grupo
music.

Ejemplos

Comando su y las sesiones.

Desde la primera consola virtual(tty1), el usuario elvis utiliza el comando su para convertirse en el
usuario prince, observando quién está en la máquina tanto antes como después de usar el
comando su.

[elvis@station elvis]$ w
12:44:38 up 3:44, 1 user, load average: 0.02, 0.07, 0.07
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
elvis tty1 - 12:44pm 0.00s 0.08s 0.02s w
[elvis@station elvis]$ su - prince
Password:
[prince@station prince]$ w
12:44:56 up 3:44, 1 user, load average: 0.02, 0.06, 0.07
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
elvis tty1 - 12:44pm 0.00s 0.13s 0.14s login -- elvis

Para sorpresa del usuario, no hay prueba de que prince haya estado en el sistema. Un listado de
todos los procesos asociados con la primera consola virtual ayuda a ilustrar el porqué.

569
[prince@station prince]$ ps aux | grep tty1
elvis 6115 0.0 0.5 4316 1392 tty1 S 12:44 0:00 -bash
root 6156 0.0 0.3 4112 960 tty1 S 12:44 0:00 su -
prince
prince 6157 0.0 0.5 4316 1404 tty1 S 12:44 0:00 -bash
prince 6207 0.0 0.2 2648 696 tty1 R 12:49 0:00 ps aux
prince 6208 0.0 0.2 3576 644 tty1 S 12:49 0:00 grep tty1

Cuando elvis ejecuta el comando su, el comando su opera como root (esto se conoce como un
suid ejecutable, el cual se tratará con mayor detalle más adelante). Como el comando su, estaba
operando como root, entonces puede iniciar una nueva shell como el usuario prince. La shell
original, como elvis, aún existe y como es el primer proceso que se debe iniciar en la terminaltty1,
aún es propietario de la sesión asociada con esa terminal. El comando w, el cual lista las sesiones,
no sabe de la shell del usuario prince.

Ejercicios en línea

Utilización del comando newgrppara cambiar grupos primarios. Lab Exercise Objetivo: Uso del
comando newgrp para cambiar los grupos primarios y crear un grupo de archivos de propiedad de
un nuevo grupo. Estimated Time: 10 mins.

Especificaciones

Use el comando idpara confirmar que su cuenta es miembro del grupo secundario music.

[student@station student]$ id
uid=2299(student) gid=2299(student)
groups=2299(student),201(wrestle),205(music)

En su directorio de inicio, cree un archivo llamado music.txt, el cual es de propiedad de grupo


music y otro archivowrestle.txt, el cual es de propiedad de grupo wrestle. Para poder hacer esto,
cambie a su grupo primario con el comandonewgrp. El contenido de los archivos en realidad no
tiene importancia.

Si el ejercicio se ha completado correctamente, un listado largo (ls -l) de su directorio de inicio


debería dar una salida similar a lo siguiente:

[student@station student]$ ls -l
total 8
-rw-r--r-- 1 student music 29 May 27 08:57 music.txt
-rw-r--r-- 1 student wrestle 29 May 27 08:57 wrestle.txt

Deliverables A title Question 1

1. Un archivo titulado ~/music.txt perteneciente al grupo music.

570
2. Un archivo titulado ~/wrestle.txtperteneciente al grupo wrestle.

Possible Solution

La siguiente secuencia de comandos brinda una solución posible para crear el archivomusic.txt.

571

Você também pode gostar