
%***********************************************************************
%
%       Spanish Translation by:  Oscar Porcar Borras,
%                                <al000129@llevant.uji.es>
%
%       Revised (cballard)       Jun 19, 1997
%
%***********************************************************************
\chapter{Trabajando con \unix}\label{shell2-chapter}

\begin{fortune}
\begin{verse}
  A UNIX saleslady, Lenore,\\
  Enjoys work, but she likes the beach more.\\
  \hspace{0.5in}She found a good way\\
  \hspace{0.5in}To combine work and play:\\
  She sells C shells by the seashore.
\end{verse}
\end{fortune}
\glossary{C shell}\glossary{Bourne shell}
\glossary{fichero}\glossary{entrada}\glossary{salida}


\unix\ es un potente sistema para aquellos que saben cómo dominar su
poder.  En este capítulo, intentaré describir varias maneras de usar
el shell de \unix, \cmdnm{bash}\ttindex{bash}, más eficientemente.

\section{Comodines}\bindex{shell!comodines}
\index{shell!globbing|ver{shell, comodines}}
\index{comodines|ver{shell, comodines}}

En el capítulo anterior, se enseñaron los comandos para mantener
ficheros \cmdnm{cp}, \cmdnm{mv}, y \cmdnm{rm}.  A veces, se querrá
tratar con más de un fichero a la vez---en realidad, con muchos a la
vez.  Por ejemplo, se quiere copiar todos los ficheros que empiecen
por \file{data} en un directorio llamado \file{\tie/backup}.  Se
podría hacer esto ejecutando muchos comandos \cmdnm{cp}, o escribiendo
cada fichero en una línea de comando.  Estos dos métodos llevan mucho
tiempo, incluso, se tienen muchas posibilidades de cometer errores.

Una buena manera de hacer este trabajo es teclear:
\begin{screen}\begin{verbatim}
/home/larry/report$ ls -F
1993-1          1994-1          data1           data5
1993-2          data-new        data2
/home/larry/report$ mkdir ~/backup
/home/larry/report$ cp data* ~/backup
/home/larry/report$ ls -F ~/backup
data-new        data1           data2           data5
/home/larry/report$
\end{verbatim}\end{screen}% $

Como se puede observar, el asterisco indica a \cmdnm{cp} que tome
todos los ficheros que empiecen por \file{data} y los copie a
\file{\tie/backup}.  ¿Qué cree que \cmdln{cp d*w \tie/backup} puede
haber hecho?

\subsection{¿Qué ocurre {\em realmente\/}?}

Buena pregunta. De hecho, hay un par de carácteres especiales
interceptados por el shell, \cmdnm{bash}\ttindex{bash}. El carácter
\cmdln{*}, un asterisco, dice ``cambia esta palabra con todos los
ficheros que se ajusten a esta especificación''. Así, el comando
\cmdln{cp data* \tie/backup}, como el de arriba, cambia a \cmdln{cp
  data-new data1 data2 data5 \tie/backup} antes de ejecutarse.

Para ilustrar esto, introduciré un comando nuevo,
\cmdnm{echo}\impttindex {echo}. \cmdnm{echo} es un comando
extremadamente simple; repite, o muestra, cualquier parámetro. De este
modo:

\begin{screen}\begin{verbatim}
/home/larry$ echo Hola!
Hola!
/home/larry$ echo Como se encuentra?
Como se encuentra?
/home/larry$ cd report
/home/larry/report$ ls -F
1993-1          1994-1          data1           data5
1993-2          data-new        data2
/home/larry/report$ echo 199*
1993-1 1993-2 1994-1
/home/larry/report$ echo *4*
1994-1
/home/larry/report$ echo *2*
1993-2 data2
/home/larry/report$
\end{verbatim}
\end{screen}

Como se puede ver, el shell expande el comodín y pasa todos los
ficheros al programa que se va a ejecutar. Esto plantea una pregunta
interesante: ¿qué ocurre si {\em no\/} hay ficheros que se ajusten a
la especificación del comodín? Pruebe \cmdln{echo /rc/fr*og} y
\cmdnm{bash}\ttindex{bash} pasará literalmente la especificación del
comodín al programa.

Otros shells, como \cmdnm{tcsh}\ttindex{tcsh}, en vez de pasar el
comodín literalmente, contestarán {\tt No match.} Aquí está el mismo
comando ejecutado bajo \cmdnm{tcsh}:

\begin{screen}\begin{verbatim}
mousehouse>echo /rc/fr*og
echo: No match.
mousehouse>
\end{verbatim}\end{screen}
    
La última pregunta que podría hacerse es, ¿qué pasa si quisiera
mostrar \file{data*}, en vez de la lista de nombres?  Bien, tanto en
\cmdnm{bash} como en \cmdnm{tcsh}, sólo se debe incluir la cadena
entre comillas:

\begin{minipage}{2.6in}\begin{screen}
\begin{verbatim}
/home/larry/report$ echo "data*"
data*
/home/larry/report$
\end{verbatim}\end{screen}\end{minipage}\ {\large Ó bien}\ 
\begin{minipage}{2.6in}\begin{screen}
\begin{verbatim}
mousehouse>echo "data*"
data*
mousehouse>
\end{verbatim}\end{screen}\end{minipage}


\subsection{El signo de interrogación}

Además del asterisco, el shell también interpreta un signo de
interrogación como un carácter especial.  Un signo de interrogación
coincidirá con un carácter, y sólo uno. Por ejemplo, \cmdln{ls
  /etc/??}  mostrará todos los ficheros de dos letras en el directorio
\file{/etc}.

\eindex{shell!comodines}

\section{Ganar tiempo con \cmdnm{bash}}
\index{editando la línea de comandos|ver{shell, editando}}

\subsection{Editando la línea de comandos}\bindex{shell!editando}

A veces, escribe un comando largo a \cmdnm{bash}\ttindex{bash} y,
antes de pulsar \ret, se da cuenta de que ha cometido un error al
escribirlo.  Se puede simplemente borrar todo y volver a teclear
correctamente, pero ¡es demasiado esfuerzo!  En cambio, se pueden
usar las flechas para moverse, borrar el/los carácter/es incorrecto/s,
y escribir la información correctamente.

Hay muchas teclas especiales que ayudan a editar la línea de comandos,
muchas de ellas similares a los comandos usados en GNU~Emacs\index{GNU
  Emacs}.  Por ejemplo, \key{C-t} intercambia dos carácteres
adyacentes\footnote{\key{C-t} significa mantener pulsada la tecla
  marcada como ``Ctrl'', y apretar la tecla ``t''. Luego soltar
  ambas.}.  Se pueden encontrar muchos de los comandos en el capítulo
sobre~Emacs, Capítulo~\ref{emacs-chapter}.

\eindex{shell!editando}

\subsection{Completamiento de comandos y nombres de 
fichero}\bindex{shell!completamiento}

Otra peculiaridad de \cmdnm{bash}\ttindex{bash} es la ejecución
automática de las líneas de comando.  Por ejemplo, veamos el siguiente
ejemplo de un comando \cmdnm{cp} típico:

\begin{screen}\begin{verbatim}
/home/larry$ ls -F
esto-es-un-fichero-largo
/home/larry$ cp esto-es-un-fichero-largo corto
/home/larry$ ls -F
corto              esto-es-un-fichero-largo
/home/larry$ 
\end{verbatim}\end{screen}
    
Es una gran molestia tener que teclear cada letra de
\file{esto-es-un-fichero-largo} cada vez que se quiere acceder a él,
sucede lo mismo si queremos crear \file{esto-es-un-fichero-largo}
copiando en él \file{/etc/passwd}\footnote{\cmdln{cp /etc/passwd
    esto-es-un-fichero-largo}}.  Ahora, aprenderemos a escribir el
anterior comando \cmdnm{cp} más rápidamente y con menos posibilidad de
error.

En vez de teclear el nombre del fichero entero, se escribe \cmdln{cp
  es}, se pulsa y suelta la tecla \key{Tab}.  Por arte de magia, el
resto del nombre del fichero aparece en la línea de comandos, y se
puede escribir \file{corto}.  Desgraciadamente,
\cmdnm{bash}\ttindex{bash} no pude leer los pensamientos, por lo que
se debe teclear \file{corto}.

Cuando se pulsa \key{Tab}, \cmdnm{bash} mira lo que hay escrito y
busca un fichero que empiece como eso.  Por ejemplo, si tecleo
\file{/usr/bin/ema} y luego pulso \key{Tab}, \cmdnm{bash} encontrará
\file{/usr/bin/emacs} ya que es el único fichero que empieza por
\file{/usr/bin/ema} en mi sistema.  En cambio, si tecleo
\file{/usr/bin/ld} y pulso \key{Tab}, \cmdnm{bash} me avisará.  Eso es
porque tres ficheros, \file{/usr/bin/ld}, \file{/usr/bin/ldd}, y
\file{/usr/bin/ld86} empiezan por \file{/usr/bin/ld} en mi sistema.

Si se intenta un completamiento y \cmdnm{bash} avisa, se puede pulsar
inmediatamente \key{Tab} otra vez para conseguir una lista de todos
los ficheros que coincidan con el patrón.  De este modo, si no se está
seguro del nombre exacto del fichero, podemos teclear los primeros
carácteres del nombre y buscarlo en una lista más pequeña de ficheros.
 
\eindex{shell!completamiento}
 

\section{La entrada estándar y La salida estándar}

% it might be nice to get some illustrations around here, with
% pointers showing where all the output is going

Intentemos abordar un problema simple: conseguir un listado del
directorio \file{/usr/bin}.  Si hacemos \cmdln{ls /usr/bin}, algunos
de los nombres de los ficheros saldrán por arriba de la pantalla.
¿Como se pueden ver todos los ficheros?

\subsection{Algunos conceptos de \unix}

El sistema operativo \unix\ facilita mucho a los programas el uso del
terminal.  Cuando un programa escribe algo en la pantalla, está usando
algo llamado \concept{salida estándar}.  Salida estándar, en inglés
standard output o {\tt stdout}, es la manera que tiene el programa de
escribirle cosas al usuario.  El nombre por el que se indica un
programa es \concept{entrada estándar} ({\tt stdin}).  Es posible que
un programa se comunique con el usuario sin usar la entrada o salida
estándar, pero la mayoría de los comandos que se tratan en este libro
usan {\tt stdin} y {\tt stdout}.

Por ejemplo, el comando \cmdnm{ls}\ttindex{ls} imprime una lista de
los directorios en la salida estándar, que está normalmente
``conectada'' al terminal.  Un comando interactivo, como el shell,
\cmdnm{bash}\ttindex{bash}, lee los comandos de la entrada estándar.

Un programa también puede escribir en el \concept{error estándar}, ya
que es muy fácil hacer que la salida estándar apunte a cualquier lugar
aparte del terminal.  El error estándar ({\tt stderr}) está casi
siempre conectado al terminal para que alguna persona pueda leer el
mensaje.

En esta sección, examinaremos tres modos de enredarse con la entrada y
salida estándar: redireccionar la salida, redireccionar la entrada, y
las tuberías.

\subsection{Redireccionar la salida}\bindex{Redireccionar la salida}

Un aspecto muy importante de \unix\ es la posibilidad de {\bf
  redireccionar} la salida.  Esto permite que, en vez de ver los
resultados de un comando, los salvemos en un fichero o los enviemos
directamente a una impresora.  Por ejemplo, para redireccionar la
salida del comando \cmdln{ls /usr/bin}, se coloca un signo\tie``{\tt
  >}'' al final de la línea, y se indica el fichero donde dejar la
salida:

\begin{screen}\begin{verbatim}
/home/larry$ ls
/home/larry$ ls -F /usr/bin > listado
/home/larry$ ls
listado
/home/larry$
\end{verbatim}\end{screen}

Como se puede ver, en vez de escribir los nombres de todos los
ficheros, el comando crea un fichero totalmente nuevo en el directorio
actual.  Echemos un vistazo a este fichero usando el comando
\cmdnm{cat}.  Si se recuerda, \cmdnm{cat} era un comando bastante
inútil que copiaba lo que se escribía (entrada estándar) al terminal
(salida estándar).  \cmdnm{cat} también imprime un fichero en la
salida estándar si se indica el fichero como parámetro:

\begin{screen}\begin{verbatim}
/home/larry$ cat listado
..
/home/larry$
\end{verbatim}\end{screen}
    
La salida exacta del comando \cmdln{ls /usr/bin} aparece en el
contenido de \file{listado}.  Por ahora todo bien, sin embargo no
resuelve el problema original.\footnote{Para lectores impacientes, el
  comando que se debe usar es \cmdnm{more}.  Sin embargo, hay que
  hablar un poco sobre algo más antes de llegar ahí.}

A pesar de todo, \cmdnm{cat} hace algunas cosas interesantes cuando se
redirecciona su salida.  ¿Qué hace el comando \cmdln{cat listado >
  fichero}?  Normalmente, el \cmdln{> fichero} dice ``coge toda la
salida del comando y ponla en \file{fichero}''.  La salida del comando
\cmdln{cat listado} es el fichero \file{listado}.  Así hemos inventado
un nuevo (y no tan eficiente) m\'{etodo} de copiar ficheros.

¿Qué ocurre con el comando \cmdln{cat > zorro}? \cmdnm{cat} lee cada
l\'{i}nea escrita en el terminal (entrada estándar) y la imprime de
vuelta (salida estándar) hasta que lee \key{Ctrl-d}.  En este caso, la
salida estándar se ha redireccionado al fichero \file{zorro}.  Ahora
\cmdnm{cat} sirve como un editor rudimentario:

\begin{quote}{\tt 
/home/larry\$ cat > zorro\\
El rapido zorro marron salta sobre el descuidado perro.\\
{\em pulsa Ctrl-d}
}\end{quote}

Ahora se ha creado el fichero \file{zorro} que contiene la frase ``El
rapido zorro marron salta sobre el descuidado perro''.  Un último uso
del versátil comando \cmdnm{cat} es con{\bf cat}enar ficheros.
\cmdnm{cat} imprimirá cada fichero dado como parámetro, uno despues de
otro.  El comando \cmdln{cat listado zorro} imprimirá el listado del
directorio \file{/usr/bin}, y luego la tonta frase.  Así, el comando
\cmdln{cat listado zorro > listyzorro} creará un nuevo fichero
conteniendo los contenidos de \file{listado} y \file{zorro}.

\eindex{Redireccionar la Salida}

\subsection{Redireccionar la entrada}\bindex{Redireccionar la Entrada}

Así como cuando se redirecciona la salida estándar\index{salida
  estándar}, es posible redireccionar la entrada\index{estándar
  input}.  En lugar de que un programa lea su entrada desde el
teclado, la leerá desde un fichero.  Como redireccionar la entrada
está relacionado con redireccionar la salida, parece natural
que\tie``{\tt <}'' sea el carácter para redireccionar la entrada.
Éste también se usa después del comando que se desee ejecutar.

Esto es generalmente útil si se tiene un fichero de datos y un comando
que espera sus datos desde la entrada estándar.  Muchos comandos
permiten especificar un fichero sobre el cual operar, así que en las
actividades diarias el\tie``{\tt <}'' no se usa tanto como otras
técnicas.

\eindex{Redireccionar la entrada}

\subsection{Las tuberías}\bindex{tuberías}

Muchos comandos \unix\ producen gran cantidad de información.  Por
ejemplo, es normal que un comando como \cmdln{ls /usr/bin} produzca
más salida que la que se puede ver en pantalla.  Para que se pueda ver
toda la información de un comando como \cmdln{ls /usr/bin}, es
necesario usar otro comando \unix\, llamado
\cmdnm{more}\ttindex{more}\footnote{Se llama
  \cmdnm{more}\ttindex{more} porque ese es el indicador que
  originalmente mostraba: ``{\tt --more--}''.  En varias versiones de
  \linux\ el comando \cmdnm{more} es identico a un comando más
  avanzado que hace todo lo que \cmdnm{more} puede hacer y más aún.
  Como demostración de que los programadores de ordenadores son malos
  cómicos, llamaron a este nuevo
  programa\tie``\cmdnm{less}''\ttindex{less}.}.  \cmdnm{more} parará
cada vez que la pantalla se llene de información.  Por ejemplo,
\cmdln{more < /etc/rc} mostrará el fichero \file{/etc/rc} como lo
haría \cmdln{cat /etc/rc}, excepto que \cmdnm{more} permite leerlo.
\cmdnm{more} también admite el comando \cmdln{more /etc/rc}, y esa es
la forma normal de invocarlo.

Sin embargo, eso no ayuda al problema de que \cmdln{ls /usr/bin}
muestre más información de la que se pueda ver.  \cmdln{more < ls
  /usr/bin} no funciona--- ¡la redirección de entrada sólo funciona
con ficheros, no comandos!  Se {\em podría\/} hacer esto:

\begin{screen}\begin{verbatim}
/home/larry$ ls /usr/bin > temp-ls
/home/larry$ more temp-ls
..
/home/larry$ rm temp-ls
\end{verbatim}\end{screen}% $

Pero, \unix\ propone una forma más limpia de hacerlo.  Se puede usar
el comando \cmdln{ls /usr/bin | more}.  El carácter \cmdln{|} es una
{\bf tubería}.  Como una tubería de agua, una tubería \unix\ controla
el flujo.  En vez de agua, se controla el flujo de información.

Los {\bf filtros}\index{filtros} son programas muy útiles para usarse
en conjunción con las tuberías.  Un filtro es un programa que lee la
entrada estándar, la cambia de alguna manera, y la saca por la salida
estándar. \cmdnm{more} es un filtro---lee los datos que coge de la
entrada estándar y los muestra por la salida estándar pantalla a
pantalla, permitiendo leer el fichero.  \cmdnm{more} no es un gran
filtro porque su salida no se puede enviar a otro programa.

Otros filtros incluyen los programas \cmdnm{cat}\ttindex{cat},
\cmdnm{sort}\ttindex {sort}, \cmdnm{head}\ttindex{head}, y
\cmdnm{tail}\ttindex{tail}.  Por ejemplo, si se quiere leer sólo las
primeras diez l\'{i}neas de la salida de \cmdnm{ls}, se puede usar
\cmdln{ls /usr/bin | head}.

\eindex{tuberías}

\section{Multitarea}\label{section-multitasking}

\subsection{Usando el control de trabajos}
\index{control de trabajos|see{shell, control de trabajos}} 

{\bf Control de trabajos}\index{shell!control de trabajos} se refiere
a la habilidad de poner procesos (esencialmente, otra palabra para
programas) en \concept{background} (segundo plano) y ponerlos de
vuelta en \concept{foreground} (primer plano). Esto es como decir, que
se quiere ser capaz de ejecutar algo mientras se hacen otras cosas,
pero que estén ahí otra vez cuando se les quiera decir algo o
pararlos.  En Unix, la principal herramienta para el control de
procesos es el shell---seguirá la pista de los procesos por usted, si
se aprende como hablar su lenguaje.

Las dos palabras más importantes en ese lenguaje son
\cmdnm{fg}\ttindex{fg}, para primer plano, y \cmdnm{bg}\ttindex{bg},
para segundo plano.  Para entender como funcionan, use el comando
\ttindex{yes} \cmdnm{yes} en el indicador del sistema.

\begin{screen}\begin{verbatim}
/home/larry$ yes
\end{verbatim}
\end{screen}% $

Esto produce el maravilloso efecto de desplazar una larga columna de
{\tt y}es por la parte izquierda de la pantalla, tan rápido que no se
pueden seguir\footnote{Hay buenas razones para que este extraño
  comando exista.  Ciertos comandos esperan una confirmación ---un
  ``si'' ([y]es en inglés) a una pregunta.  El comando \cmdnm{yes}
  permite al programador automatizar la respuesta a esas preguntas.}.
Para pararlo, se podría pulsar \key{Ctrl-c} y matarlo, pero esta vez
Ud. oprimirá~\key{Ctrl-z}.  Parece haberse detenido, pero habrá un
mensaje antes del indicador de sistema, más o menos parecido a este:

\begin{screen}\begin{verbatim}
[1]+   Stopped                  yes
\end{verbatim}
\end{screen}

Significa que el trabajo \cmdnm{yes} se ha \concept{suspendido} en el
segundo plano.  Se puede hacer que siga ejecutándose tecleando
\ttindex{fg}\index{foreground} \cmdnm{fg} en el indicador de sistema,
que lo pondrá en primer plano otra vez.  Si se desea, se pueden hacer
otras cosas antes, mientras está suspendido.  Pruebe unos cuantos
\cmdnm{ls} o algo antes de ponerlo en primer plano nuevamente.

Una vez que ha vuelto al primer plano, las {\tt y}es empezarán a salir
otra vez, tan rápido como antes.  No hay que preocuparse de que si
mientras ha estado suspendido ha ``almacenado'' más {\tt y}es para
enviarlas a la pantalla: cuando un trabajo se suspende, el programa
entero no se ejecuta hasta que se lo vuelva de vuelta a la vida.
(Ahora pulse \key{Ctrl-c} para matarlo de veras).

Pongamos aparte el mensaje que obtuvimos del shell:

\begin{screen}\begin{verbatim}
[1]+   Stopped                yes
\end{verbatim}\end{screen}

El número entre corchetes es el \index{shell!número de trabajo} {\bf
  número de trabajo} de este proceso, y se usará cuando se necesite
referenciarlo específicamente.  (Naturalmente, desde el momento que
tengamos en ejecución múltiples trabajos, se necesita un modo de
acceder a cada uno).  El \cmdln{+} siguiente indica que ése es el
``trabajo actual'' --- esto es, el proceso más reciente que se ha
movido del primer plano al segundo.  Si se tecleara \cmdln{fg}, se
pondría el trabajo con el \cmdln{+} en primer plano otra vez.  (Más
sobre esto después, cuando se discuta la ejecución de múltiples
trabajos a la vez).  La palabra {\tt Stopped} significa que el trabajo
está ``parado''.  El trabajo no está muerto, pero actualmente no se
ejecuta.  \linux\ lo ha guardado en un estado especial de suspendido,
listo para saltar a la acción cuando alguien lo solicite.  Finalmente,
el {\tt yes} es el nombre del trabajo que se ha detenido.

Antes de seguir adelante, matemos este trabajo y lo arrancamos otra
vez de forma diferente.  El comando se llama \ttindex{kill}
\cmdnm{kill} y se usa del siguiente modo:

\begin{screen}\begin{verbatim}
/home/larry$ kill %1
[1]+  Stopped                 yes
/home/larry$
\end{verbatim}\end{screen}
\index{trabajos|see{shell, trabajos}}

Ese mensaje sobre el proceso que indica ``parado'' otra vez induce a
error.  Para saber si aún está vivo (eso es, tanto en ejecución como
congelado en un estado suspendido), teclee \index{shell!trabajos}
\cmdln{jobs}:

\begin{screen}\begin{verbatim}
/home/larry$ jobs
[1]+  Terminated                 yes
/home/larry$
\end{verbatim}\end{screen}
        
Ahora ya lo sabe: ¡el trabajo ha \index{terminación} terminado!  (Es
posible que el comando \cmdnm{jobs} no muestre nada, lo que
simplemente significa que no hay trabajos ejecutándose en segundo
plano.  Si se acaba de matar un trabajo, y al teclear \cmdnm{jobs} no
muestra nada, se tiene la seguridad de que el comando \cmdnm{kill} se
ha ejecutado correctamente.  Normalmente indicará que el trabajo ha
``terminado''.)

Ahora, ejecute \cmdnm{yes} de nuevo, de esta forma:

\begin{screen}\begin{verbatim}
/home/larry$ yes > /dev/null
\end{verbatim}\end{screen}% $
    
Si lee la sección sobre la redirección de entrada y salida, sabrá que
se está enviando la salida de \cmdnm{yes} a un fichero especial
llamado \file{/dev/null}.  \file{/dev/null} es un agujero negro que
come cualquier salida que se le envíe (se puede imaginar ese torrente
de {\tt y}es saliendo por detrás del ordenador y perforando un agujero
en la pared, si eso le hace feliz).

Despues de teclear esto, no se recuperará el indicador de sistema,
pero tampoco saldrá esa columna de {\tt y}es.  Sin embargo la salida
se está enviando a \file{/dev/null}, el trabajo aún se ejecuta en
primer plano.  Como siempre, se puede suspender pulsando \key{Ctrl-z}.
Hágalo ahora para volver al indicador del sistema.

\begin{screen}\begin{verbatim}
/home/larry$ yes > /dev/null
["yes" se ejecuta, y solamente se ha pulsado Ctrl-z]
[1]+  Stopped                 yes >/dev/null 

/home/larry$ 
\end{verbatim}
\end{screen}

Hmm\ldots ¿hay alguna forma de ponerlo en ejecución en segundo plano,
mientras deja el indicador del sistema para trabajar de forma
interactiva?  El comando para hacer eso es
\ttindex{bg}\index{background}\cmdnm{bg}:

\begin{screen}\begin{verbatim}
/home/larry$ bg
[1]+ yes >/dev/null  &
/home/larry$ 
\end{verbatim}
\end{screen}

Ahora, deberá tener confianza en mí sobre esto: después de teclear
\cmdnm{bg}, el trabajo \cmdln{yes > /dev/null} habrá continuado con su
ejecución otra vez, pero esta vez en segundo plano.  De hecho, si hace
alguna cosa en el prompt, como \cmdnm{ls} u otros, se dará cuenta que
su máquina se ha ralentizado un poco (¡generar y descargar
continuamente una cadena preparada de ``yes'' lleva algo de tiempo, al
fin y al cabo!)  Aparte de esto, no hay ningún otro efecto.  Se puede
hacer lo que se desee en el indicador del sistema, y \cmdnm{yes}
continuará felizmente enviando su salida al agujero negro.

Ahora hay dos formas diferentes de matarlo: con el comando
\cmdnm{kill} que ya se explicó, o poniendo el trabajo en primer plano
de nuevo e interrumpirlo con una interrupción, \key{Ctrl-c}.  Probemos
la segunda forma, sólo para entender la relación entre \cmdnm{fg} y
\cmdnm{bg} un poco mejor;

\begin{screen}\begin{verbatim}
/home/larry$ fg
yes >/dev/null 

[ahora esta en primer plano.  Imagine que pulso Ctrl-c para terminarlo]

/home/larry$
\end{verbatim}\end{screen}

Bueno, se acabó.  Ahora, ejecute unos cuantos trabajos
simultáneamente, como estos:

% lg: rephrase the above paragraph, maybe. It's a little awkward and
% lg: too much a meta-paragraph: a paragraph about the document
% kff: done, (good point).

\begin{screen}\begin{verbatim}
/home/larry$ yes  > /dev/null &
[1] 1024
/home/larry$ yes | sort > /dev/null &
[2] 1026
/home/larry$ yes | uniq > /dev/null 
[y aqui, pulse Ctrl-z para suspenderlo, por favor]

[3]+  Stopped                 yes | uniq >/dev/null
/home/larry$
\end{verbatim}\end{screen}
    
La primera cosa que le debe llamar la atención de estos comandos es la
terminación \cmdln{\&} al final de los dos primeros.  \index{\&} Poner
un \cmdln{\&} después del comando indica al shell que los ejecute en
segundo plano desde el principio.  (Es una forma de evitarse tener que
ejecutar el programa, pulsar \key{Ctrl-z}, y luego teclear
\cmdln{bg}.)  Así, estos dos comandos han empezado a ejecutarse en
segundo plano.  El tercero está suspendido e inactivo en este momento.
Se puede dar cuenta de que la máquina se ha vuelto más lenta, ya que
los que se están ejecutando requieren un poco de tiempo de CPU.

Cada uno indica su número de trabajo.  Los dos primeros también
muestran sus \concept{números de identificación de proceso}, o PID,
\index{PID} despues del número de trabajo.  Los PIDs normalmente no
son algo que se necesite conocer, pero a veces viene bien.

Matemos el segundo, ya que creo que está ralentizando su máquina.  Se
puede teclear \cmdln{kill \%2}, pero eso sería demasiado fácil.  Por
el contrario, haga esto:

\begin{screen}\begin{verbatim}
/home/larry$ fg %2
yes | sort >/dev/null
[pulse Ctrl-c para matarlo]

/home/larry$
\end{verbatim}\end{screen}
    
Como esto demuestra, \cmdnm{fg} toma parámetros empezando con
\cmdln{\%}.  De hecho, se podría teclear sólo esto:

\begin{screen}\begin{verbatim}
/home/larry$ %2
yes | sort >/dev/null
[pulse Ctrl-c para matarlo]

/home/larry$
\end{verbatim}\end{screen}
    
Esto funciona por que el shell automáticamente interpreta un número de
trabajo como una petición para poner ese trabajo en primer plano.  Se
puede indicar los números de trabajo con otros números precedidos por
un \index{\%} ``{\tt \%}''.  Ahora teclee \cmdln{jobs} para ver cuáles
trabajos quedan en ejecución:

\begin{screen}\begin{verbatim}
/home/larry$ jobs
[1]-  Running                 yes >/dev/null  &
[3]+  Stopped                 yes | uniq >/dev/null
/home/larry$
\end{verbatim}
\end{screen}
        
El \cmdln{-} indica que ese trabajo número 1 es segundo en la lista
para ser puesto en el primer plano, si sólo se teclea \cmdln{fg} sin
dar parámetros.  El \cmdln{+} indica que el trabajo especificado es el
primero en la lista---un \cmdln{fg} sin parámetros pondrá al trabajo
número 3 en el primer plano.  Sin embargo, se puede acceder a él
llamándolo, si se desea, mediante:

\begin{screen}\begin{verbatim}
/home/larry$ fg %1
yes >/dev/null 
[ahora pulse Ctrl-z para suspenderlo]

[1]+  Stopped                 yes >/dev/null
/home/larry$
\end{verbatim}
\end{screen}

Al cambiar al trabajo número 1 y luego suspenderlo han cambiado las
proridades de todos los trabajos de usuario.  Esto se puede ver con el
comando \cmdnm{jobs}:

\begin{screen}\begin{verbatim}
/home/larry$ jobs
[1]+  Stopped                 yes >/dev/null
[3]-  Stopped                 yes | uniq >/dev/null
/home/larry$
\end{verbatim}
\end{screen}
        
Ahora los dos están parados (porque los dos se han suspendido con
\key{Ctrl-z}), y el número 1 es el siguiente en la lista a entrar en
el primer plano por defecto.  Esto es así porque se le puso en el
primer plano manualmente, y luego fue suspendido.  El \cmdln{+}
siempre se refiere al trabajo más reciente que ha sido suspendido del
primer plano.  Se puede continuar con su ejecución otra vez:

\begin{screen}\begin{verbatim}
/home/larry$ bg
[1]+ yes >/dev/null  &
/home/larry$ jobs
[1]-  Running                 yes >/dev/null  
[3]+  Stopped                 yes | uniq >/dev/null
/home/larry$
\end{verbatim}
\end{screen}% $
        
Fíjese que ahora está en ejecución, y el otro trabajo se ha movido en
la lista y tiene el \cmdln{+}.  Ahora matémoslos para que el sistema
no esté permanentemente ralentizado por procesos que no hacen nada.

\begin{screen}\begin{verbatim}
/home/larry$ kill %1 %3
[3]   Terminated              yes | uniq >/dev/null 
/home/larry$ jobs
[1]+  Terminated              yes >/dev/null 
/home/larry$
\end{verbatim}
\end{screen}% $

Aparecerán varios mensajes sobre la terminación de los trabajos---nada
muere tranquilamente, al parecer.  La figura~\ref{job-control} de la
página~\pageref{job-control} muestra un breve resumen de lo que se
debe saber acerca del control de trabajos.

\begin{figure}[tb]
  \index{shell!control de trabajos!resumen}
\begin{dispitems}
\item [\cmdnm{fg} {\sl \%n\nro trabajo}] Este es un comando del shell
  que devuelve un trabajo al primer plano.  Para saber cuál es éste
  por defecto, se teclea \cmdln{jobs} y se busca el que tiene
  el\tie{\tt +}.\\ Parámetros: número de trabajo opcional.  El trabajo
  por defecto se identifica con el\tie{\tt +}.
  
\item [{\tt \&}] Cuando se añade un\tie{\tt \&} al final de la línea
  de comandos, indica al comando que se ejecute en segundo plano
  automáticamente.  Este trabajo está entonces sujeto a todos los
  métodos usuales para el control de trabajos aquí detallados.
  
\item [\cmdnm{bg} {\sl \%n\nro trabajo}] Este es un comando del shell
  que manda a un trabajo suspendido ejecutarse en segundo plano.  Para
  saber cual es éste por defecto, se teclea \cmdln{jobs} y se busca el
  que tiene el\tie{\tt +}.\\ Parámetros: número de trabajo opcional.
  El trabajo por defecto se identifica con el\tie{\tt +}.
  
\item [\cmdnm{kill} {\sl \%n\nro trabajo} {\sl PID}] Este es un
  comando del shell que obliga a un trabajo en segundo plano, ya sea
  suspendido o en ejecución, a terminar.  Se debe siempre especificar
  el número de trabajo o PID, y si se están usando
  números de trabajo, no hay que olvidar poner el\tie{\tt \%}.\\
  Parámetros: El número de trabajo (a continuación del\tie{\tt \%}) o
  el PID (no es necesario el\tie{\tt \%}).  Se puede especificar más
  de un proceso o trabajo en una línea.
  
\item [\cmdnm{jobs}] Este comando del shell lista información sobre
  los trabajos que están en ese momento en ejecución o suspendidos.  A
  veces también dice cuáles son los que acaban de salir o han
  terminado.
  
\item [\key{Ctrl-c}] Este es el carácter genérico de interrupción.
  Normalmente, si se pulsa mientras un programa se está ejecutando en
  primer plano, matará al programa (puede que haya que hacerlo varias
  veces).  Sin embargo, no todos los programas responderán a este
  método de terminación.
  
\item [\key{Ctrl-z}] Esta combinación de teclas normalmente suspende
  un programa, puede que algunos programas lo ignoren.  Una vez
  suspendido, el trabajo se puede reiniciar en el segundo plano o se
  puede matar.

\end{dispitems}
\caption{Resumen de comandos y teclas usados para el control de
  trabajos.}
\label{job-control}
\end{figure}

\subsection{Teoría del control de trabajos}
\index{shell!control de trabajos!conceptos}

Es importante entender que el control de procesos lo hace el shell.
No hay ningún programa en el sistema llamado \cmdnm{fg}; por eso,
\cmdnm{fg}, \cmdnm{bg},\tie{\tt \&}, \cmdnm{jobs}, y \cmdnm{kill} son
internos al shell\footnote{N. del T.: En el original pone
  "shell-builtins", eso es que se compilan dentro del shell.}. (A
veces \cmdnm{kill} es un programa independiente; en el shell
\cmdnm{bash} usado por \linux\ pertenece al shell).  Esto es una forma
lógica de hacerlo: ya que cada usuario quiere su propio espacio de
control de trabajos, y cada usuario ya tiene su propio shell, es
% lg: why the quotes?
% kff: good question :-)... computer techies tend
% to use the word "space" in a way unfamiliar to many people, but I
% think readers can grok it from context, now that you bring it up, so
% I have killed the quotes.
más fácil que el shell siga la pista de los trabajos usuario.  Por
otro lado, cada número de trabajo de usuario sólo tiene significado
para ese usuario: mi trabajo número [1] y su trabajo número [1] son
probablemente dos procesos totalmente diferentes.  De hecho, si se
está conectado más de una vez, cada uno de los shells tendrá datos
únicos sobre el control de trabajos, as\'{i} como también un usuario
puede tener dos trabajos diferentes con el mismo número ejecutándose
en dos shells diferentes.

La manera segura de referenciarlos es usar el número {\bf
  ID}entificador de Proceso ({\tt PID}).  Estos números abarcan todo
el sistema --- cada proceso tiene su propio (y único) número.  Dos
usuarios diferentes pueden referenciar un proceso por su {\tt PID} y
saber que están hablando sobre el mismo proceso (¡asumiendo que están
conectados en la misma máquina!)

Echémosle un vistazo a un comando más para entender que son los {\tt
  PID}s.  El comando \cmdnm{ps} lista todos los procesos en ejecución,
incluyendo el shell.  Pruébelo.  Tiene también unas cuantas opciones,
de las cuales las más importantes (para mucha gente) son \cmdln{a},
\cmdln{u}, y \cmdln{x}.  La opción \cmdln{a} lista los procesos
pertenecientes a algún usuario, no sólo los suyos propios.  La
\cmdln{x} lista los procesos que no tienen un terminal asociado a
ellos\footnote{Esto sólo tiene sentido para ciertos programas que no
  tienen que hablar con el usuario a través del teclado.}.
Finalmente, la \cmdln{u} da información adicional sobre los procesos
que es frecuentemente útil.

Para hacerse una idea de lo que realmente está haciendo el sistema, se
ponen todos juntos: \cmdln{ps -aux}.  Se pueden ver los procesos que
usan más memoria mirando la columna {\tt \%MEM}, y más CPU mirando a
la columna {\tt \%CPU}.  (La columna {\tt TIME} lista la cantidad {\em
  total\/} de tiempo de CPU usado.)\glossary{tiempo de CPU}

Otra nota rápida sobre los PIDs.  \cmdnm{kill}, aparte de tomar
opciones de la forma {\sl \%n\nro trabajo}, toma opciones de los PIDs
en crudo.  Esto es, si pone un \cmdln{yes > /dev/null} en segundo
plano, se ejecuta \cmdln{ps}, y se busca el \cmdnm{yes}.  Luego se
teclea \cmdln{kill PID}\footnote{En general, es más fácil matar el
  número del trabajo en vez de usar PIDs.}.

Si empieza a programar en C con su sistema Linux, pronto aprenderá que
el control de trabajos del shell es sólo una versión interactiva de
las llamadas a las funciones \cmdnm{fork} y \cmdnm{execl}.  Esto es
demasiado complejo para explicarlo aquí, pero sería útil recordarlo
después cuando se esté programando y se quieran ejecutar múltiples
procesos desde un simple programa.

\section{Consolas virtuales: como estar en varios lugares a la vez}

Linux soporta \index{vitual consoles} \index{VC|ver{virtual consoles}}
{\bf consolas virtuales}.  Son una manera de hacer que su simple
máquina aparezca como múltiples terminales, todos conectados al mismo
núcleo \linux.  Por fortuna, usar las consolas virtuales es una de las
cosas más simples en \linux: hay ``hot keys''\footnote{N.T.: No he
  creido apropiado traducir este término, ya que muchos usuarios saben
  a lo que se refiere.  De todas formas para el que no lo sepa, esto
  es, una simple combinación de teclas que hace un cierto trabajo.}
para cambiar entre las consolas rápidamente.  Para probarlo, hay que
conectarse al sistema, pulsar la tecla \key{Alt} izquierda, y pulsar
\key{F2} (esto es, la tecla de función número 2)\footnote{Hay que
  asegurarse de que esto se hace desde consolas en modo texto: si se
  está ejecutando X~Window u otra aplicación gráfica, probablemente no
  funcionará, sin embargo corre el rumor de que pronto se podrá
  cambiar entre las consolas virtuales en X~Window de Linux.}
\footnote{N. del T.: De hecho al momento de la traducción, la
  combinación es \key{Ctrl-Alt-{\sl tecla-de-función}}.}.
% I think it does now. -M ****

Se encontrará con otro indicador para conectarse.  No se alarme: ahora
está en la consola virtual (VC) número 2.  Conéctese y haga algunas
cosas --- unos cuantos \cmdnm{ls} o lo que sea --- para confirmar que
es un shell real.  Ahora puede volver a la VC número 1, pulsando el
\key{Alt} izquierdo y \key{F1}.  O se puede mover a una {\em tercera}
VC, de la forma obvia (\key{Alt-F3}).

Generalmente los sistemas Linux vienen con cuatro VC activadas por
defecto.  Esto se puede incrementar a ocho; estos temas se cubrirán en
\ldpsa.  Ello implica editar uno o dos ficheros en el directorio {\tt
  /etc}.  Sin embargo, cuatro deben ser suficientes para la mayoría de
las personas.
% lg: just is more direct and better for both I&GS and UG
% yup, shouldn't take up space here with this stuff, you're right.

% Umm, the virtual consoles are enabled, there just aren't any
% shells running in them - you can start programs with stdin from
% other VCs and/or stdout to other VCs. -M ****

Una vez las haya usado, las VC probablemente se convertirán en una
herramienta indispensable para tener varias cosas ejecutándose a la
vez.  Por ejemplo, yo normalmente ejecuto Emacs en la VC 1 (y hago la
mayor parte de mi trabajo ahí), mientras tengo un programa de
comunicaciones en la VC 3 (así puede coger o dejar ficheros via modem
mientras trabajo, o ejecutar programas en máquinas remotas), y
mantengo un shell en la VC 2 sólo en caso de que tenga que ejecutar
algo sin involucrar a la VC 1.

% Local Variables: 
% mode: latex
% TeX-master: "guide"
% End: 
