SlideShare una empresa de Scribd logo
1 de 62
Descargar para leer sin conexión
La shell bash
1
Capítulo 1 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 "!".
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.
La shell bash
2
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 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.
[madonna@station madonna]$ nano .bashrc
... (madonna appends a single line containing the command "cal") ...
[madonna@station madonna]$ cat .bashrc
La shell bash
3
# .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.
[blondie@station blondie]$ history
1 ls -l /home/
2 ls -ln /home/
3 exit
4 exit
5 id
...
167 mv rhyme stuff/
La shell bash
4
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.
[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
La shell bash
5
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
predeterminado
Efectos
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.
Trucos del historial de comandos
La shell bash ofrece muy pocas técnicas para acceder previamente los comandos
tecleados (o elementos del mismo).
La shell bash
6
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.
[madonna@station madonna]$ nano hello.c
[madonna@station madonna]$ cat hello.c
#include "stdio.h"
int main(void)
{
printf("hello worldn");
return 0;
La shell bash
7
}
[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 dollyn");
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.
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
La shell bash
8
[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.
2. date >> .bash_timestamps
3. Observe el archivo .bash_timestamps, y confirme si se agrega una nueva
marca de tiempo cada vez que inicia una nueva shell bash.
4. 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
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.
2. El archivo .bashrc debe también contener una línea de comentario que incluya
su nombre de usuario.
La shell bash
9
Capítulo 2 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.
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
10
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:
[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).
La shell bash
11
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 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,
La shell bash
12
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:
[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.
La shell bash
13
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.
[elvis@station elvis]$ ls -l /etc/passwd
-rw-r--r-- 1 root root 3694 Aug 15 16:26 /etc/passwd
[elvis@station elvis]$ echo $?
0
En contraste, los siguientes ejemplos muestran cómo responde el comando ls al listar un
archivo que no existe.
[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
La shell bash
14
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.
[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 $?
La shell bash
15
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.
[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
La shell bash
16
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:
[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.
Capítulo 3 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.
La shell bash
17
• 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.
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 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
La shell bash
18
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.
[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.
La shell bash
19
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]$
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.
La shell bash
20
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
La shell bash
21
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 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
La shell bash
22
llamada LANG para determinar el lenguaje del usuario y modificar su salida como
corresponde.
[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.
[prince@station prince]$ set
BASH=/bin/bash
La shell bash
23
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.
La shell bash
24
[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.
La shell bash
25
links: Can't access startfile
http://www.redhat.com/opensourcenow/key_issues.html
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
La shell bash
26
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.
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
La shell bash
27
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
Ejercicios en línea
Lab Exercise
Objetivo: Establecer y apuntar correctamente varias variables de shell y de
entorno.
Estimated Time: 30 mins.
Especificaciones
Estas especificaciones deben aplicarse a las shells recién iniciadas. Edite el script de
arranque de bash .bashrc (que se encuentra al comienzo de su directorio de inicio)
para incluir los comandos apropiados.
1. Su shell debe incluir el directorio /usr/sbin en su ruta de búsqueda de archivos
ejecutables.
2. Tras el arranque, su shell debería crear la variable de entorno PRINTER que
apunte a la palabra sales.
3. Sólo por gusto, tras el arranque, haga que su shell establezca la variable
HISTSIZE en su proceso actual de shell, (¿qué efecto tendrá esto en su historial
de comandos de shell?)
4. Tras el arranque, su shell debería crear la variable de shellCLICHE, la cual
debería apuntar a la frase en inglés that is how the cookie crumbles. Asegúrese
que la variable no se convierta en una variable de entorno.
5. Tras el arranque, su shell debe redirigir la salida del comando date al archivo en
su directorio de inicio titulado ppid_is_my_parent, en donde ppid es
remplazado por su id del proceso padre de shell (almacenado en la variable de
shell PPID).
Si ha configurado su archivo de shell .bashrc correctamente, debería poder reproducir
una salida similar a la siguiente.
[student@station student]$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/sbin:/ho
me/student/bin
[student@station student]$ echo $PRINTER
sales
[student@station student]$ ps
PID TTY TIME CMD
3914 pts/3 00:00:00 bash
3948 pts/3 00:00:00 ps
[student@station student]$ echo $HISTSIZE
3914
[student@station student]$ echo $CLICHE
that is how the cookie crumbles
La shell bash
28
[student@station student]$ echo $PPID
4293
[student@station student]$ ls
4293_is_my_parent
Deliverables
A title
Question 1
Un archivo de arranque bash.bashrc configurado correctamente, para que las shells
recién creadas bash tengan la siguiente configuración.
1. El directorio /usr/sbin está incluído en la ruta de búsqueda de la shell.
2. La variable de entorno PRINTER apunta a sales.
3. La variable de entorno HISTSIZE apunta al id (PID) del proceso actual de la
shell.
4. La variable de shell CLICHE (no es una variable de entorno) apunta a la frase en
inglés that is how the cookie crumbles.
5. Tras el arranque, la salida del comando date es redirigida al archivo titulado
ppid_is_my_parent en su directorio de inicio, donde ppid es remplazado por
el id del proceso padre de la shell.
Limpieza
Después de que su ejercicio haya sido calificado, probablemente querrá suprimir los
cambios hechos en el archivo .bashrc, (en caso contrario, podría terminar con un
amplio historial, y demasiados archivos molestos soso_is_my_parent.)
Capítulo 4 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.
La shell bash
29
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
comandos
`...`, $(...)
Salida de la ejecución del comando en una
subshell
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 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/
La shell bash
30
`-- 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.
[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
La shell bash
31
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 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
La shell bash
32
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
33
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 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>
La shell bash
34
Una nota sobre las comillas
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
La shell bash
35
/etc/X11/gdm/gdm.conf
/etc/modprobe.conf
...
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
...
La shell bash
36
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 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 $,
La shell bash
37
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 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.
[prince@station prince]$ ls -l
total 0
La shell bash
38
-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
La shell bash
39
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!! <<
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.
Capítulo 5 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.
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
La shell bash
40
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 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
...
La shell bash
41
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.
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
La shell bash
42
# /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]
...
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'
La shell bash
43
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).
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).
La shell bash
44
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
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.
La shell bash
45
[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.
La shell bash
46
Opciones y banderas de la shell de bash
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
nombredeopción
Establece la opción especificada. Algunas de las opciones más
comunes 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
La shell bash
47
(+) (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).
[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.
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash
Semana 4 y_5_-_la_shell_bash

Más contenido relacionado

La actualidad más candente

2 filesystem basics
2 filesystem basics2 filesystem basics
2 filesystem basicscyberleon95
 
Maria jose hernandez c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...
Maria jose hernandez   c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...Maria jose hernandez   c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...
Maria jose hernandez c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...MariaJoseHernndez2
 
Tutorial Comandos
Tutorial ComandosTutorial Comandos
Tutorial Comandoseguzman
 
Texto ejemploparacomandoslinux
Texto ejemploparacomandoslinuxTexto ejemploparacomandoslinux
Texto ejemploparacomandoslinuxIsmael Abad
 
Comandos GNU/Linux-Unix y programación shell.
Comandos GNU/Linux-Unix y programación shell.Comandos GNU/Linux-Unix y programación shell.
Comandos GNU/Linux-Unix y programación shell.Alan Resendiz
 
Tareas programadas
Tareas programadasTareas programadas
Tareas programadasLauC2457
 
8 herramientas de procesos de string
8  herramientas de procesos de string8  herramientas de procesos de string
8 herramientas de procesos de stringcyberleon95
 
Comandos básicos para la terminal de ubuntu
Comandos básicos para la terminal de ubuntuComandos básicos para la terminal de ubuntu
Comandos básicos para la terminal de ubuntuMonchitocm Cuemtz
 
Tutorial 18pag
Tutorial 18pagTutorial 18pag
Tutorial 18pageckoby
 
Comandos de ubuntu
Comandos de ubuntuComandos de ubuntu
Comandos de ubuntuAny Saula
 

La actualidad más candente (18)

2 filesystem basics
2 filesystem basics2 filesystem basics
2 filesystem basics
 
11 suplemments
11 suplemments11 suplemments
11 suplemments
 
Manual linux
Manual linuxManual linux
Manual linux
 
Maria jose hernandez c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...
Maria jose hernandez   c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...Maria jose hernandez   c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...
Maria jose hernandez c.i. 27.878.738 - seccion pnf if-02 t1 f2 - administra...
 
Tutorial Comandos
Tutorial ComandosTutorial Comandos
Tutorial Comandos
 
Linux comandos 1
Linux comandos 1Linux comandos 1
Linux comandos 1
 
Comandos linux
Comandos linuxComandos linux
Comandos linux
 
EL SHELL Y COMANDOS BASICOS DE LINUX
EL SHELL Y COMANDOS BASICOS DE LINUXEL SHELL Y COMANDOS BASICOS DE LINUX
EL SHELL Y COMANDOS BASICOS DE LINUX
 
Fedora
FedoraFedora
Fedora
 
Texto ejemploparacomandoslinux
Texto ejemploparacomandoslinuxTexto ejemploparacomandoslinux
Texto ejemploparacomandoslinux
 
Unix 3.1
Unix 3.1Unix 3.1
Unix 3.1
 
Comandos GNU/Linux-Unix y programación shell.
Comandos GNU/Linux-Unix y programación shell.Comandos GNU/Linux-Unix y programación shell.
Comandos GNU/Linux-Unix y programación shell.
 
Tareas programadas
Tareas programadasTareas programadas
Tareas programadas
 
8 herramientas de procesos de string
8  herramientas de procesos de string8  herramientas de procesos de string
8 herramientas de procesos de string
 
Comandos básicos para la terminal de ubuntu
Comandos básicos para la terminal de ubuntuComandos básicos para la terminal de ubuntu
Comandos básicos para la terminal de ubuntu
 
Comandos
ComandosComandos
Comandos
 
Tutorial 18pag
Tutorial 18pagTutorial 18pag
Tutorial 18pag
 
Comandos de ubuntu
Comandos de ubuntuComandos de ubuntu
Comandos de ubuntu
 

Destacado

Clase 8 completa
Clase 8 completaClase 8 completa
Clase 8 completavictdiazm
 
modulo 3
modulo 3 modulo 3
modulo 3 kevin
 
Exploration network chapter4
Exploration network chapter4Exploration network chapter4
Exploration network chapter4victdiazm
 
Programación III. TP 03. Nieva
Programación III. TP 03. NievaProgramación III. TP 03. Nieva
Programación III. TP 03. NievaMultimediaUNLaR
 
Gianni rodari
Gianni rodariGianni rodari
Gianni rodariMagpiza
 
Web2.0 (2)
Web2.0 (2)Web2.0 (2)
Web2.0 (2)Esus28
 
Semana 3 estructuras de control
Semana 3 estructuras de controlSemana 3 estructuras de control
Semana 3 estructuras de controlvictdiazm
 
Democracia y participaci n ciudadana
Democracia y participaci n ciudadanaDemocracia y participaci n ciudadana
Democracia y participaci n ciudadanaarturovt01
 
La meva primera pesentació
La meva primera pesentacióLa meva primera pesentació
La meva primera pesentacióFidelviu
 
Abf lec dictionary
Abf lec dictionaryAbf lec dictionary
Abf lec dictionaryvictdiazm
 
Exploration network chapter5
Exploration network chapter5Exploration network chapter5
Exploration network chapter5victdiazm
 

Destacado (20)

Clase 8 completa
Clase 8 completaClase 8 completa
Clase 8 completa
 
modulo 3
modulo 3 modulo 3
modulo 3
 
Exploration network chapter4
Exploration network chapter4Exploration network chapter4
Exploration network chapter4
 
Clase 16
Clase 16Clase 16
Clase 16
 
962
962962
962
 
Proteã nas
Proteã nasProteã nas
Proteã nas
 
955 10 ojogorev42008espanhol
955 10 ojogorev42008espanhol955 10 ojogorev42008espanhol
955 10 ojogorev42008espanhol
 
Programación III. TP 03. Nieva
Programación III. TP 03. NievaProgramación III. TP 03. Nieva
Programación III. TP 03. Nieva
 
I expo feria i acecore
I  expo feria i acecoreI  expo feria i acecore
I expo feria i acecore
 
Gianni rodari
Gianni rodariGianni rodari
Gianni rodari
 
Web2.0 (2)
Web2.0 (2)Web2.0 (2)
Web2.0 (2)
 
Semana 3 estructuras de control
Semana 3 estructuras de controlSemana 3 estructuras de control
Semana 3 estructuras de control
 
El amor
El amorEl amor
El amor
 
Clase7
Clase7Clase7
Clase7
 
Presentación TH
Presentación THPresentación TH
Presentación TH
 
Dgp dr-01-rev-01
Dgp dr-01-rev-01Dgp dr-01-rev-01
Dgp dr-01-rev-01
 
Democracia y participaci n ciudadana
Democracia y participaci n ciudadanaDemocracia y participaci n ciudadana
Democracia y participaci n ciudadana
 
La meva primera pesentació
La meva primera pesentacióLa meva primera pesentació
La meva primera pesentació
 
Abf lec dictionary
Abf lec dictionaryAbf lec dictionary
Abf lec dictionary
 
Exploration network chapter5
Exploration network chapter5Exploration network chapter5
Exploration network chapter5
 

Similar a Semana 4 y_5_-_la_shell_bash

Similar a Semana 4 y_5_-_la_shell_bash (20)

6 la shell bash
6 la shell bash6 la shell bash
6 la shell bash
 
6 la shell bash
6 la shell bash6 la shell bash
6 la shell bash
 
Scripts
ScriptsScripts
Scripts
 
Programacinenshell linux
Programacinenshell linuxProgramacinenshell linux
Programacinenshell linux
 
Linux Programacion en Shell
Linux Programacion en ShellLinux Programacion en Shell
Linux Programacion en Shell
 
Giseproi hacking ético - bash scripting
Giseproi   hacking ético - bash scriptingGiseproi   hacking ético - bash scripting
Giseproi hacking ético - bash scripting
 
Script
ScriptScript
Script
 
Script Y Comandos De Linux
Script Y Comandos De LinuxScript Y Comandos De Linux
Script Y Comandos De Linux
 
The linux shell. Shell Scripting desde 0
The linux shell. Shell Scripting desde 0The linux shell. Shell Scripting desde 0
The linux shell. Shell Scripting desde 0
 
[ES] Línea de Comandos GNU/Linux
[ES] Línea de Comandos GNU/Linux[ES] Línea de Comandos GNU/Linux
[ES] Línea de Comandos GNU/Linux
 
Script presentacion
Script presentacionScript presentacion
Script presentacion
 
Shell script en linux
Shell script en linuxShell script en linux
Shell script en linux
 
17 comandos basicoslinuxasoitson
17 comandos basicoslinuxasoitson17 comandos basicoslinuxasoitson
17 comandos basicoslinuxasoitson
 
Conceptos básicos del shell
Conceptos básicos del shellConceptos básicos del shell
Conceptos básicos del shell
 
Agilidad en shell de linux
Agilidad en shell de linuxAgilidad en shell de linux
Agilidad en shell de linux
 
[ES] Administración básica de GNU / Linux
[ES] Administración básica de GNU / Linux[ES] Administración básica de GNU / Linux
[ES] Administración básica de GNU / Linux
 
Curso Bash 1
Curso Bash 1Curso Bash 1
Curso Bash 1
 
Trabajo digital.
Trabajo digital.Trabajo digital.
Trabajo digital.
 
Quasi - scripts-linux
Quasi - scripts-linuxQuasi - scripts-linux
Quasi - scripts-linux
 
Julissa
JulissaJulissa
Julissa
 

Más de victdiazm

Semana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsSemana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsvictdiazm
 
Semana 1 quick tours guia de ejercicios resuelta
Semana 1   quick tours guia de ejercicios resueltaSemana 1   quick tours guia de ejercicios resuelta
Semana 1 quick tours guia de ejercicios resueltavictdiazm
 
Semana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsSemana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsvictdiazm
 
Semana 1 -_quick_tours
Semana 1 -_quick_toursSemana 1 -_quick_tours
Semana 1 -_quick_toursvictdiazm
 
Semana 16 usuarios y grupos
Semana 16 usuarios y gruposSemana 16 usuarios y grupos
Semana 16 usuarios y gruposvictdiazm
 
Semana 13 y 14 aplicaciones de redes
Semana 13 y 14 aplicaciones de redesSemana 13 y 14 aplicaciones de redes
Semana 13 y 14 aplicaciones de redesvictdiazm
 
Semana 12 filesystem basico
Semana 12  filesystem basicoSemana 12  filesystem basico
Semana 12 filesystem basicovictdiazm
 
Semana 10 administracion de procesos
Semana 10 administracion de procesosSemana 10 administracion de procesos
Semana 10 administracion de procesosvictdiazm
 
Semana 9 entradas salidas estandar y pipes
Semana 9 entradas salidas estandar y pipesSemana 9 entradas salidas estandar y pipes
Semana 9 entradas salidas estandar y pipesvictdiazm
 
Semana 8 herramientas de procesos de string
Semana 8  herramientas de procesos de stringSemana 8  herramientas de procesos de string
Semana 8 herramientas de procesos de stringvictdiazm
 
Semana 7 y 8 sistemas de archivos linux
Semana 7 y 8 sistemas de archivos linuxSemana 7 y 8 sistemas de archivos linux
Semana 7 y 8 sistemas de archivos linuxvictdiazm
 
Control1 victoria diaz
Control1   victoria diazControl1   victoria diaz
Control1 victoria diazvictdiazm
 
Comandos basicos linux
Comandos basicos linuxComandos basicos linux
Comandos basicos linuxvictdiazm
 
8 herramientas de procesos de string
8  herramientas de procesos de string8  herramientas de procesos de string
8 herramientas de procesos de stringvictdiazm
 
Semana 9 -_standard_io_and_pipes
Semana 9 -_standard_io_and_pipesSemana 9 -_standard_io_and_pipes
Semana 9 -_standard_io_and_pipesvictdiazm
 
Dce1 introduccion microsoft.net
Dce1 introduccion microsoft.netDce1 introduccion microsoft.net
Dce1 introduccion microsoft.netvictdiazm
 
Dce0 programacion oo_c__vbnet
Dce0 programacion oo_c__vbnetDce0 programacion oo_c__vbnet
Dce0 programacion oo_c__vbnetvictdiazm
 
Dce0 fundamentos deprogramacion
Dce0 fundamentos deprogramacionDce0 fundamentos deprogramacion
Dce0 fundamentos deprogramacionvictdiazm
 
Sql server 2005
Sql server 2005Sql server 2005
Sql server 2005victdiazm
 

Más de victdiazm (20)

Semana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsSemana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissions
 
Semana 1 quick tours guia de ejercicios resuelta
Semana 1   quick tours guia de ejercicios resueltaSemana 1   quick tours guia de ejercicios resuelta
Semana 1 quick tours guia de ejercicios resuelta
 
Semana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissionsSemana 2 y_3_-_file_ownerships_and_permissions
Semana 2 y_3_-_file_ownerships_and_permissions
 
Semana 1 -_quick_tours
Semana 1 -_quick_toursSemana 1 -_quick_tours
Semana 1 -_quick_tours
 
Semana 16 usuarios y grupos
Semana 16 usuarios y gruposSemana 16 usuarios y grupos
Semana 16 usuarios y grupos
 
Semana 13 y 14 aplicaciones de redes
Semana 13 y 14 aplicaciones de redesSemana 13 y 14 aplicaciones de redes
Semana 13 y 14 aplicaciones de redes
 
Semana 12 filesystem basico
Semana 12  filesystem basicoSemana 12  filesystem basico
Semana 12 filesystem basico
 
Semana 10 administracion de procesos
Semana 10 administracion de procesosSemana 10 administracion de procesos
Semana 10 administracion de procesos
 
Semana 9 entradas salidas estandar y pipes
Semana 9 entradas salidas estandar y pipesSemana 9 entradas salidas estandar y pipes
Semana 9 entradas salidas estandar y pipes
 
Semana 8 herramientas de procesos de string
Semana 8  herramientas de procesos de stringSemana 8  herramientas de procesos de string
Semana 8 herramientas de procesos de string
 
Semana 7 y 8 sistemas de archivos linux
Semana 7 y 8 sistemas de archivos linuxSemana 7 y 8 sistemas de archivos linux
Semana 7 y 8 sistemas de archivos linux
 
Control1 victoria diaz
Control1   victoria diazControl1   victoria diaz
Control1 victoria diaz
 
Compresor
CompresorCompresor
Compresor
 
Comandos basicos linux
Comandos basicos linuxComandos basicos linux
Comandos basicos linux
 
8 herramientas de procesos de string
8  herramientas de procesos de string8  herramientas de procesos de string
8 herramientas de procesos de string
 
Semana 9 -_standard_io_and_pipes
Semana 9 -_standard_io_and_pipesSemana 9 -_standard_io_and_pipes
Semana 9 -_standard_io_and_pipes
 
Dce1 introduccion microsoft.net
Dce1 introduccion microsoft.netDce1 introduccion microsoft.net
Dce1 introduccion microsoft.net
 
Dce0 programacion oo_c__vbnet
Dce0 programacion oo_c__vbnetDce0 programacion oo_c__vbnet
Dce0 programacion oo_c__vbnet
 
Dce0 fundamentos deprogramacion
Dce0 fundamentos deprogramacionDce0 fundamentos deprogramacion
Dce0 fundamentos deprogramacion
 
Sql server 2005
Sql server 2005Sql server 2005
Sql server 2005
 

Semana 4 y_5_-_la_shell_bash

  • 1. La shell bash 1 Capítulo 1 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 "!". 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.
  • 2. La shell bash 2 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 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. [madonna@station madonna]$ nano .bashrc ... (madonna appends a single line containing the command "cal") ... [madonna@station madonna]$ cat .bashrc
  • 3. La shell bash 3 # .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. [blondie@station blondie]$ history 1 ls -l /home/ 2 ls -ln /home/ 3 exit 4 exit 5 id ... 167 mv rhyme stuff/
  • 4. La shell bash 4 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. [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
  • 5. La shell bash 5 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 predeterminado Efectos 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. Trucos del historial de comandos La shell bash ofrece muy pocas técnicas para acceder previamente los comandos tecleados (o elementos del mismo).
  • 6. La shell bash 6 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. [madonna@station madonna]$ nano hello.c [madonna@station madonna]$ cat hello.c #include "stdio.h" int main(void) { printf("hello worldn"); return 0;
  • 7. La shell bash 7 } [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 dollyn"); 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. 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
  • 8. La shell bash 8 [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. 2. date >> .bash_timestamps 3. Observe el archivo .bash_timestamps, y confirme si se agrega una nueva marca de tiempo cada vez que inicia una nueva shell bash. 4. 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 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. 2. El archivo .bashrc debe también contener una línea de comentario que incluya su nombre de usuario.
  • 9. La shell bash 9 Capítulo 2 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. 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
  • 10. La shell bash 10 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: [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).
  • 11. La shell bash 11 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 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,
  • 12. La shell bash 12 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: [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.
  • 13. La shell bash 13 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. [elvis@station elvis]$ ls -l /etc/passwd -rw-r--r-- 1 root root 3694 Aug 15 16:26 /etc/passwd [elvis@station elvis]$ echo $? 0 En contraste, los siguientes ejemplos muestran cómo responde el comando ls al listar un archivo que no existe. [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
  • 14. La shell bash 14 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. [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 $?
  • 15. La shell bash 15 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. [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
  • 16. La shell bash 16 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: [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. Capítulo 3 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.
  • 17. La shell bash 17 • 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. 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 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
  • 18. La shell bash 18 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. [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.
  • 19. La shell bash 19 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]$ 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.
  • 20. La shell bash 20 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
  • 21. La shell bash 21 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 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
  • 22. La shell bash 22 llamada LANG para determinar el lenguaje del usuario y modificar su salida como corresponde. [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. [prince@station prince]$ set BASH=/bin/bash
  • 23. La shell bash 23 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.
  • 24. La shell bash 24 [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.
  • 25. La shell bash 25 links: Can't access startfile http://www.redhat.com/opensourcenow/key_issues.html 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
  • 26. La shell bash 26 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. 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
  • 27. La shell bash 27 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 Ejercicios en línea Lab Exercise Objetivo: Establecer y apuntar correctamente varias variables de shell y de entorno. Estimated Time: 30 mins. Especificaciones Estas especificaciones deben aplicarse a las shells recién iniciadas. Edite el script de arranque de bash .bashrc (que se encuentra al comienzo de su directorio de inicio) para incluir los comandos apropiados. 1. Su shell debe incluir el directorio /usr/sbin en su ruta de búsqueda de archivos ejecutables. 2. Tras el arranque, su shell debería crear la variable de entorno PRINTER que apunte a la palabra sales. 3. Sólo por gusto, tras el arranque, haga que su shell establezca la variable HISTSIZE en su proceso actual de shell, (¿qué efecto tendrá esto en su historial de comandos de shell?) 4. Tras el arranque, su shell debería crear la variable de shellCLICHE, la cual debería apuntar a la frase en inglés that is how the cookie crumbles. Asegúrese que la variable no se convierta en una variable de entorno. 5. Tras el arranque, su shell debe redirigir la salida del comando date al archivo en su directorio de inicio titulado ppid_is_my_parent, en donde ppid es remplazado por su id del proceso padre de shell (almacenado en la variable de shell PPID). Si ha configurado su archivo de shell .bashrc correctamente, debería poder reproducir una salida similar a la siguiente. [student@station student]$ echo $PATH /bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/sbin:/ho me/student/bin [student@station student]$ echo $PRINTER sales [student@station student]$ ps PID TTY TIME CMD 3914 pts/3 00:00:00 bash 3948 pts/3 00:00:00 ps [student@station student]$ echo $HISTSIZE 3914 [student@station student]$ echo $CLICHE that is how the cookie crumbles
  • 28. La shell bash 28 [student@station student]$ echo $PPID 4293 [student@station student]$ ls 4293_is_my_parent Deliverables A title Question 1 Un archivo de arranque bash.bashrc configurado correctamente, para que las shells recién creadas bash tengan la siguiente configuración. 1. El directorio /usr/sbin está incluído en la ruta de búsqueda de la shell. 2. La variable de entorno PRINTER apunta a sales. 3. La variable de entorno HISTSIZE apunta al id (PID) del proceso actual de la shell. 4. La variable de shell CLICHE (no es una variable de entorno) apunta a la frase en inglés that is how the cookie crumbles. 5. Tras el arranque, la salida del comando date es redirigida al archivo titulado ppid_is_my_parent en su directorio de inicio, donde ppid es remplazado por el id del proceso padre de la shell. Limpieza Después de que su ejercicio haya sido calificado, probablemente querrá suprimir los cambios hechos en el archivo .bashrc, (en caso contrario, podría terminar con un amplio historial, y demasiados archivos molestos soso_is_my_parent.) Capítulo 4 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.
  • 29. La shell bash 29 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 comandos `...`, $(...) Salida de la ejecución del comando en una subshell 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 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/
  • 30. La shell bash 30 `-- 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. [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
  • 31. La shell bash 31 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 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
  • 32. La shell bash 32 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
  • 33. La shell bash 33 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 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>
  • 34. La shell bash 34 Una nota sobre las comillas 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
  • 35. La shell bash 35 /etc/X11/gdm/gdm.conf /etc/modprobe.conf ... 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 ...
  • 36. La shell bash 36 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 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 $,
  • 37. La shell bash 37 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 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. [prince@station prince]$ ls -l total 0
  • 38. La shell bash 38 -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
  • 39. La shell bash 39 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!! << 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. Capítulo 5 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. 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
  • 40. La shell bash 40 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 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 ...
  • 41. La shell bash 41 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. 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
  • 42. La shell bash 42 # /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] ... 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'
  • 43. La shell bash 43 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). 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).
  • 44. La shell bash 44 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 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.
  • 45. La shell bash 45 [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.
  • 46. La shell bash 46 Opciones y banderas de la shell de bash 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 nombredeopción Establece la opción especificada. Algunas de las opciones más comunes 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
  • 47. La shell bash 47 (+) (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). [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.