62
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.

6 la shell bash

  • Upload
    yimfer1

  • View
    167

  • Download
    1

Embed Size (px)

Citation preview

Page 1: 6 la shell bash

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.

Page 2: 6 la shell bash

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 c ommand "cal") ... [madonna@station madonna]$ cat .bashrc

Page 3: 6 la shell bash

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/

Page 4: 6 la shell bash

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

Page 5: 6 la shell bash

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).

Page 6: 6 la shell bash

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 world\n"); return 0;

Page 7: 6 la shell bash

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 dolly\n"); return 0; } [madonna@station madonna]$ !g gcc -o hello hello.c [madonna@station madonna]$ !. ./hello hello dolly

Observe que la shell bash imprime el comando seleccionado desde el historial de madonna antes de ejecutar el comando.

Uso de ESC.

Ahora madonna quisiera crear un subdirectorio bin , establece sus permisos para que sólo ella pueda acceder a éste y mover su archivo ejecutable hello en él. Usa la secuencia de teclas ESC-. para agilizar el proceso.

[madonna@station madonna]$ mkdir bin [madonna@station madonna]$ chmod 700 <ESC-.> [madonna@station madonna]$ mv hello <ESC-.> [madonna@station madonna]$ ls <ESC-.> hello

Quizas no es el ejemplo más interesante porque bin es un directorio muy pequeño para teclear de todas maneras. Sin embargo, si hubiera sido el directorio /usr/lib/perl5/ven or_perl/5.8.0/HTML/ , los golpes de teclado grabados serían impresionantes.

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

Page 8: 6 la shell bash

La shell bash

8

[madonna@station madonna]$ ln -s /dev/null .bash_hi story [madonna@station madonna]$ ls -l .bash_history lrwxrwxrwx 1 madonna madonna 9 Aug 26 1 6: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.

Page 9: 6 la shell bash

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

Page 10: 6 la shell bash

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).

Page 11: 6 la shell bash

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,

Page 12: 6 la shell bash

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@ IDL E JCPU PCPU WHAT student_a tty1 - Mon23 ?xd m? 2:43m 3.06s /bin/bash student tty2 :0.0 Tue17 0.0 0s 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.

Page 13: 6 la shell bash

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 1 6: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" > numbe rs.txt [elvis@station elvis]$ mkdir /tmp/boring && mv numb ers.txt /tmp/boring [elvis@station elvis]$ ls

Page 14: 6 la shell bash

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 sev en 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/number s.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/bor ing/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 $?

Page 15: 6 la shell bash

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" > re minders [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

Page 16: 6 la shell bash

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.

Page 17: 6 la shell bash

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 squi shy" >> ode_to_$A.txt [prince@station prince]$ ls

Page 18: 6 la shell bash

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 fru it banana is my favorite fruit [prince@station prince]$ echo $b is my favorite fru it 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.

Page 19: 6 la shell bash

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 squi shy" > $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 .p lan .. .bashrc .kde .t xt .bash_history .gnome-desktop ode_to_apple.txt .v iminfo .bash_logout .gnupg .pgpkey .x authizv2EF [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 squi shy" > ${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.

Page 20: 6 la shell bash

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:intera ctive-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

Page 21: 6 la shell bash

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

Page 22: 6 la shell bash

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

Page 23: 6 la shell 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.

Page 24: 6 la shell bash

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_i ssues.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 o f proxy servers that can act as firewall gateways and caching servers. They are preferable to the old er gateway servers (see WWW_access_GATEWAY, bel ow). Each protocol used by Links, (http, ftp, gophe r, etc), can be mapped sepa- rately by setting enviro nment variables of the form PROTOCOL_proxy (literall y: 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.

Page 25: 6 la shell bash

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/X11R 6/bin:/home/prince/bin

Page 26: 6 la shell bash

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 N AME 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/X11R 6/bin:/home/prince/bin:/usr/sbin [prince@station prince]$ lsof -c init COMMAND PID USER FD TYPE DEVICE SIZE NODE N AME init 1 root mem REG 3,3 27036 245377 / sbin/init

Page 27: 6 la shell bash

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/X11R 6/bin:/usr/sbin:/home/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

Page 28: 6 la shell bash

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.

Page 29: 6 la shell bash

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/

Page 30: 6 la shell bash

La shell bash

30

`-- chap04/ 4 directories, 0 files [prince@station prince]$ mkdir chap{01,02,03,04}/{h tml,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 1 7:41 /home/elvis drwx-----x 9 prince prince 4096 Aug 4 0 6:58 /home/prince [prince@station prince]$ ls -l ~elvis/pub total 4 drwxrwxr-x 2 elvis music 4096 Jul 13 0 5:46 music

Page 31: 6 la shell bash

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

Page 32: 6 la shell bash

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

Page 33: 6 la shell bash

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 $CA R\</pre\> <pre>little red corvette</pre> [prince@station prince]$ echo \<pre\>little red \$C AR\</pre\> >pre<little red $CAR</pre>

Page 34: 6 la shell bash

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.c onf /etc/sysconfig/networking/profiles/netup/resolv.con f find: /etc/default: Permission denied /etc/X11/gdm/factory-gdm.conf

Page 35: 6 la shell bash

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.c onf /etc/sysconfig/networking/profiles/netup/resolv.con f /etc/X11/gdm/factory-gdm.conf /etc/X11/gdm/gdm.conf /etc/modprobe.conf ...

Page 36: 6 la shell bash

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 d irectory

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 $,

Page 37: 6 la shell bash

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

Page 38: 6 la shell bash

La shell bash

38

-rw-rw-r-- 1 prince prince 0 Aug 31 0 6:19 13986$ -rw-rw-r-- 1 prince prince 0 Aug 31 0 6:19 *Fast* -rw-rw-r-- 1 prince prince 0 Aug 31 0 6:19 l -rw-rw-r-- 1 prince prince 0 Aug 31 0 6:19 Make -rw-rw-r-- 1 prince prince 0 Aug 31 0 6: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

Page 39: 6 la shell bash

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

Page 40: 6 la shell bash

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-l inux-gnu) These shell commands are defined internally. Type `help' to see this list. Type `help name' to find out more about the functio n `name'. Use `info bash' to find out more about the shell in general. Use `man -k' or `info' to find out more about comma nds 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 [P ATTERN [| PATTERN]. cd [-L|-P] [dir] command [-pVv] command [arg ...] compgen [-abcdefgjksuv] [-o option complete [-abcd efgjksuv] [-pr] [-o ...

Page 41: 6 la shell bash

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 varia ble $HOME is the default DIR. The variable CDPATH defines the s earch path for the directory containing DIR. Alternative dire ctory 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 n ot 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

Page 42: 6 la shell bash

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 a ssign a single well-known # port number for both TCP and UDP; hence, most ent ries here have two entries # even if the protocol doesn't support UDP operatio ns. # Updated from RFC 1700, ``Assigned Numbers'' (Octo ber 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 S TART TIME COMMAND root 1 0.0 0.0 1376 72 ? S A ug30 0:04 init [ root 2 0.0 0.0 0 0 ? SW A ug30 0:00 [keventd] root 3 0.0 0.0 0 0 ? SW A ug30 0:00 [kapmd] root 4 0.0 0.0 0 0 ? SWN A ug30 0:00 [ksoftirqd_CPU0] root 9 0.0 0.0 0 0 ? SW A ug30 0:00 [bdflush] root 5 0.0 0.0 0 0 ? SW A ug30 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 --re ad-alias --show-dot --show-tilde'

Page 43: 6 la shell bash

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).

Page 44: 6 la shell bash

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.

Page 45: 6 la shell bash

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.

Page 46: 6 la shell bash

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

Page 47: 6 la shell bash

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/pnm2p pa.conf /etc/aeplog.conf /etc/libuser.conf /etc/pwdb. conf /etc/cdrecord.conf /etc/logrotate.conf /etc/resol v.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ón establece 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.

Page 48: 6 la shell bash

La shell bash

48

[madonna@station madonna]$ shopt cdspell cdspell off [madonna@station madonna]$ shopt -s cdspell [madonna@station madonna]$ cd /ect /etc

Una vez allá, descubre que la opción de shell solo efectúa el comando interno de cd. El comando ls, por ejemplo, que no es un incorporado de shell, no se afecta por esta opción. Después de observar este hecho, madonna, inhabilita la opción cdspell.

[madonna@station etc]$ ls -d /ect ls: /ect: No such file or directory [madonna@station etc]$ shopt -u cdspell [madonna@station etc]$ cd /ect -bash: cd: /ect: No such file or directory

Se estará preguntando cómo recordar todas estas opciones y cómo recordar cuáles se modifican con set y cuáles con shopt. La respuesta es que no es necesario. Recuerde sin embargo, que hay dos mecanismos para establecer banderas de shell y opciones de shell (set y shopt, respectivamente) y recuerde dónde buscar información sobre cada una (el comando help y la página de manual bash(1)).

Ejemplos

Alias predeterminados en Red Hat Enterprise Linux

La configuración predeterminada en Red Hat Enterprise Linux proporciona varios usos ilustrativos de alias. Tras iniciar sesión en el comando alias se revela lo siguiente.

[madonna@station madonna]$ alias alias l.='ls -d .* --color=tty' alias ll='ls -l --color=tty' alias ls='ls --color=tty' alias vi='vim' alias which='alias | /usr/bin/which --tty-only --re ad-alias --show-dot --show-tilde'

El primer alias, l., se utiliza para listar todos los archivos ocultos (aquellos que comienzan por ".") en el directorio actual.

[madonna@station madonna]$ l. . .bash_profile .gconfd .gn ome-desktop .xauthxLTmDk .. .bashrc .gnome .gt krc .bash_history .fonts.cache-1 .gnome2 .kd e .bash_logout .gconf .gnome2_private .vi minfo

Observe que la shell bash ejecuta la expansión de nombre de ruta después de expandir el alias, para que .* sea remplazado por cada archivo en el directorio local que comienza con ".".

Page 49: 6 la shell bash

La shell bash

49

El segundo alias, ll , provee una forma más fácil para invocar el comando ls con su opción de línea de comando más usada -l. El tercer alias, ls, en efecto cambia la conducta por defecto del comando ls, para que cada invocación de ls incluya la opción de línea de comandos --color=tty .

Si consideramos cómo bash evalúa alias, alguna redundancia se descubre. Cuando un usuario ejecuta ll , bash expande el alias a ls -l --color=tty. La shell de bash luego examina la primera palabra de la expansión, ls, la cual es en sí misma un alias. La expansión de alias resulta en ls --color=tty -l --color=tty. Puesto que el alias ls se expandió al comando cuya primera palabra fue otra vez ls, bash no intenta otras expansiones de alias. Sin embargo, la expansión resultante ll especifica dos veces --color=tty .

La bandera de shell bash "x" es útil para descubrir estos tipos de problemas. Cuando sea habilitado, cada comando se imprime en pantalla (con un prefijo "+") después de que todos los alias y expansiones se hayan aplicado.

íneas [madonna@station madonna]$ set -x ++ echo -ne '\033]0;madonna@station:~\007' [madonna@station madonna]$ ll + ls --color=tty -l --color=tty total 12 drwx------ 2 madonna madonna 4096 Aug 26 1 6:23 bin -rw-rw-r-- 1 madonna madonna 76 Aug 26 1 6:10 hello.c drwxr-xr-x 4 madonna madonna 4096 Jul 21 1 7:05 networking ++ echo -ne '\033]0;madonna@station:~\007' [madonna@station madonna]$ set +x + set +x [madonna@station madonna]$

Infortunadamente, al habilitar la bandera "x" de la shell genera líneas complejas reflejando la generación de cada intérprete de comandos, pero expandido totalmente el ls --color=tty -l --color=tty se ve con claridad que es en realidad ejecutado como resultado del comando ll .

El cuarto alias, vi, se utilliza para reasignar un comando empleado para una implementación alterna. Uno de los editores más comunes de Linux (y Unix) es el editor vi. Red Hat Enterprise Linux se distribuye con una versión mejorada de vi, conocida como vim (para "Vi IMproved"). Con el fin de hacer uso transparente del editor mejorado, el comando más utilizado vi ha sido reasignado.

El último alias crea un delimitador para el comando which, para que los alias también sean reportados como sitios de archivos ejecutables hallados en la ruta de un usuario.

Uso de alias para crear comandos rm, mv, y cp más seguros

El examen de los usos de las opciones de los comandos rm , mv y cp revela que todos comparten la opción -i que se utiliza para invocar un modo interactivo. Cuando se utiliza, estos comandos le pedirán al usuario confirmación antes de ejecutar una

Page 50: 6 la shell bash

La shell bash

50

operación que causaría la pérdida de información (tal como los comandos comodines cp o mv de un archivo de destino ya existente o cualquier uso del comando rm ). El uso de la opción -i se ilustra a continuación.

[madonna@station madonna]$ date > a [madonna@station madonna]$ date > b [madonna@station madonna]$ cp -i a b cp: overwrite `b'? y [madonna@station madonna]$ mv -i a b mv: overwrite `b'? y [madonna@station madonna]$ rm -i b rm: remove regular file `b'? y

Muchos administradores de sistemas establecen alias por defecto para estos comandos, para que cada invocación de estos comandos sea una invocación interactiva.

[madonna@station madonna]$ alias cp="cp -i" mv="mv -i" rm="rm -i" [madonna@station madonna]$ alias cp mv rm alias cp='cp -i' alias mv='mv -i' alias rm='rm -i' [madonna@station madonna]$ date > a [madonna@station madonna]$ date > b [madonna@station madonna]$ cp a b cp: overwrite `b'? y [madonna@station madonna]$ rm a b rm: remove regular file `a'? y rm: remove regular file `b'? y

En Red Hat Enterprise Linux, la cuenta de root tiene dichos alias establecidos por defecto. Sin embargo, los usuarios estándar, pueden configurar estas protecciones por su cuenta si así lo desean.

Cada uno de estos comandos también viene con la opción -f para "forzar" la conducta requerida. Dado que la opción -f anula la opción -i y puede emplearse para evitar la aburridora interrogación al suprimir un gran número de archivos.

Uso de alias para crear marcadores de tiempo

La usuaria madonna quiere saber cuál de sus archivos y directorios "ocultos" en su directorio de inicio son creados o modificados por aplicaciones que ella ejecuta. Quisiera saber una forma fácil de controlar cuáles archivos se crean o cambian antes o después de ciertas operaciones. Ella sabe que el comando find implementa un criterio -newer, el cual listará todos los archivos que han sido modificados antes que un archivo especificado. Desearía crear dos alias. El primero llamado

Para crear el primer alias, primero dedica un poco de su tiempo a la lectura de la página de manual date(1) y determina que el siguiente comando generará el nombre de archivo apropiado para el archivo marcador de tiempo.

[madonna@station madonna]$ date +timestamp.%H:%M:%S

Page 51: 6 la shell bash

La shell bash

51

timestamp.19:30:23

Para crear los alias, agrega las dos líneas siguientes a su directorio ~/.bashrc . Observe el uso de la sustitución de comandos para determinar el tiempo actual en el primer alias.

alias ts="touch $(date +timestamp.%H:%M:%S)" alias tsc="find . -newer"

Abre una nueva shell (para que el .bashrc modificado tenga efecto), y ensaya sus nuevos alias. Primero utiliza ts para crear un archivo marcador de tiempo.

[madonna@station madonna]$ ts [madonna@station madonna]$ ls bin hello.c networking timestamp.19:39:18

El alias ts parece funcionar, creando el archivotimestamp.19:39:18 . Luego hace clic derecho en la ventana secundaria del escritorio Gnome y elige "Nuevo Folder" desde el menu emergente. Un folder recién creado untitled folder aparece en su ventana del escritorio. A continuación ejecuta el alias tsc especificando su archivo marcador de tiempo recién creado como el archivo con el que se compara.

[madonna@station madonna]$ tsc timestamp.19:39:18 ./.gnome-desktop ./.gnome-desktop/untitled folder ./.nautilus/metafiles ./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna% 2F.gnome-desktop.xml

Como se esperaba, el alias lista todos los archivos que han sido modificado más recientemente que el archivo marcador de tiempo especificado. Observando que un archivo titulado untitled folder fue creado en un subdirectorio llamado .gnome-

desktop , madonna asume (correctamente) que el directorio ~/.gnome-desktop contiene todos los elementos que se muestran en el escritorio de Gnome.

Ella quiere sondear un poco más, esta vez explorando la conducta de la papelera. Decide crear un nuevo archivo marcador de tiempo, mover su nueva carpeta a la papelera y luego buscar archivos modificados relativos a sus nuevo archivo marcador de tiempo.

[madonna@station madonna]$ ts [madonna@station madonna]$ ls bin hello.c networking timestamp.19:39:18

Asombrada, madonna no ve su nuevo archivo. Examina la hora modificada del archivo original ejecutando un ls -l.

[madonna@station madonna]$ ls -l timestamp.19:39:18 -rw-rw-r-- 1 madonna madonna 0 Sep 1 1 9:42 timestamp.19:39:18

Page 52: 6 la shell bash

La shell bash

52

Extrañamente, la hora modificada del archivo implica que se ha modificado aproximadamente tres minutos después de su tiempo de creación hallado en el nombre del archivo. Explorando aún más madonna confirma el alias ts.

[madonna@station madonna]$ alias ts alias ts='touch timestamp.19:39:18'

Ahora madonna entiende el problema. Vuelve a llamar la línea desde su directorio ~/.bashrc donde definió el alias ts:

alias ts="touch $(date +timestamp.%H:%M:%S)"

Aunque intentó la sustitución de comandos date para que se produjera cada vez que se invocara el alias

Para confirmar sus instintos, edita su archivo~/.bashrc , renombrando el alias ts ts_incorrect y agregando la siguiente línea.

alias ts_correct='touch $(date +timestamp.%H:%M:%S) '

Esta vez, el alias se define mediante comillas sencillas, evitando que la sustitución de comandos sea evaluada al crearse el alias. Después de comenzar una nueva shell (para que ~/.bashrc surta efecto), madonna confirma sus definiciones de alias.

[madonna@station madonna]$ alias ts_incorrect ts_co rrect alias ts_incorrect='touch timestamp.19:47:18' alias ts_correct='touch $(date +timestamp.%H:%M:%S) '

Ahora, al utilizar ts_correct, la sustitución de comandos se realiza cuando se invoca el alias (contrario a cuando éste se define). Esta es la conducta que madonna deseaba. Luego sigue explorando para saber qué archivos se modifican al utilizar la aplicación de la papelera Nautilus.

[madonna@station madonna]$ ts_correct [madonna@station madonna]$ ls bin hello.c networking timestamp.19:39:18 times tamp.19:48:12

Después de arrastrar el icono untitled folder del escritorio al icono basura , busca de nuevo archivos modificados.

[madonna@station madonna]$ tsc timestamp.19:48:12 ./.gnome-desktop ./.nautilus/metafiles ./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna% 2F.gnome-desktop.xml ./.nautilus/metafiles/file:%2F%2F%2Fhome%2Fmadonna% 2F.Trash.xml ./.Trash

Aparentemente, la carpeta fue removida del directorio .gnome-desktop a la carpeta .Trash , (el archivo untitled folder no es listado, porque el hecho de mover un

Page 53: 6 la shell bash

La shell bash

53

archivo de un directorio a otro no afecta la hora modificada del archivo, sólo las horas modificadas de los directorios.)

Ejercicios en línea

Lab Exercise Objetivo: laboratorio de práctica

Tiempo estimado: 15 minutos.

Especificaciones

Edite su archivo ~/.bashrc para que las shellsbash recién creadas tengan las siguientes propiedades.

1. El alias dir ejecuta el comando ls -l. 2. El alias globoff inhabilita la expansión de nombre de ruta (habilitando la

bandera de shell apropiada). 3. El alias complementario globon habilita la expansión del nombre de ruta

(inhabilitando la bandera de shell apropiada). 4. Al redireccionar la salida a un archivo, la shell bash no sobrescribirá un archivo

existente. 5. La shell tiene la opción de shell cdspell habilitada. 6. El comando rm es un alias para rm -i.

Ejercicio de desafio

El siguiente ejercicio debe completarse como un ejercicio de desafio. No será calificado por el script automático de calificación.

Configure el intérprete primario para que contenga el número de historial y el código de salida del comando previamente ejecutado, separado por un : (sin espacios). La coma debería ser la única coma incluida en el intérprete.

Si está bien configurado, el intérprete debería tener una conducta igual a la siguiente. Observe con cuidado la conducta del intérprete de comandos después de un comando con éxito, después de un comando fallido, y cómo se relaciona con el número de historial del comando previamente ejecutado.

[madonna@station madonna] 40:0 $ ls -d /tmp /tmp [madonna@station madonna] 41:0 $ ls -d /TMP ls: /TMP: No such file or directory [madonna@station madonna] 42:1 $ history ... 41 ls -d /tmp 42 ls -d /TMP 43 history

Page 54: 6 la shell bash

La shell bash

54

[madonna@station madonna] 43:0 $ !42 ls -d /TMP ls: /TMP: No such file or directory [madonna@station madonna] 44:1 $

Deliverables

A title

Question 1

Un archivo ~/.bashrc bien configurado, de tal forma que shells bash recién iniciadas tengan las siguientes características.

1. El alias dir ejecuta ls -l 2. El alias globoff inhabilita las expansiones de nombre de ruta. 3. El alias globon habilita expansiones del nombre de ruta. 4. Al redireccionar la salida, la shell no sobrescribirá los archivos existentes. 5. La shell tiene habilitada la opción de shell cdspell. 6. Un alias rm, el cual ejecuta el comando rm -i .

Capítulo 6 Lectura de scripts de shell e inicialización de shell

Conceptos clave

• Los scripts de shell son leídos con el comando source o con .. • Todos los scripts de shell se ejecutan en la misma shell que lee el script. • Las shells bash pueden ser tanto shells de inicio como de no inicio. • Las shells bash pueden ser tanto shells interactivas como no-interactivas. • /etc/profile , archivos dentro del directorio /etc/profile.d y

~/.bash_profile leídos en el arranque de cada shell de inicio de sesión. • /etc/bashrc y ~/.bashrc se leen en el arranque de cada shell de inicio. • ~/.bash_logout es leída por cada salida de shell de inicio de sesión.

Hasta el momento en este cuaderno, hemos estado utilizando el archivo ~/.bashrc como si fuera el único archivo que pudiera ser usado para personalizar la shell bash. Esto nos ha permitido enfocarnos en temas, tales como los alias y expansiones de shell, sin complicarnos con detalles de scripts e inicialización de shell, a riesgo de dejar al estudiante con la impresión de que el archivo ~/.bashrc es el único que puede utilizarse para personalizar la shell bash. Si esta es la impresión que se ha dado, el propósito de esta lección es cambiar esa idea.

Page 55: 6 la shell bash

La shell bash

55

En esta lección, discutiremos cómo se pueden leer los scripts de shell y cuáles scripts se leen por defecto en el arranque con Red Hat Enterprise Linux. El saber qué scripts son leídos en el arranque, le permite a los usuarios aplicar automáticamente muchas de las personalizaciones aprendidas en lecciones anteriores.

Lectura de scripts

La shell bash permite a los usuarios coleccionar múltiples comandos dentro de un sólo archivo y luego ejecutar los comandos como si fueran tecleados directamente en ese intérprete. Esto se conoce como leer el archivo. De modo apropiado, el comando usado para leer un archivo es el comando interno de shell source.

Como ejemplo, blondie desearía explorar diferentes estilos de intérpretes de shell. Para ayudar a comparar, utiliza un editor para crear un archivo de texto llamado prompts.script . Agrega varias líneas, cada una proporcionando una definición diferente para la variable PS1. Por último, comenta todo menos la primera línea.

[blondie@station blondie]$ cat prompts.script PS1="whadda you want? " #PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ " #PS1="[\u@\h \W]\$ "

Con el fin de ensayar el primer intérprete, lee el archivoprompts.script .

[blondie@station blondie]$ source prompts.script whadda you want?

Tras originar el archivo, la variable PS1 se modifica como si el contenido del script fuera tecleado en la línea de comando. Este punto importante merece repetición: cuando se originan los scripts de shell, el contenido del script se ejecuta (y puede modificarse) dentro de la shell actual.

Luego, blondie edita prompts.script , comentando la primera línea y sin comentar la segunda. Luego lee el script otra vez.

whadda you want? cat prompts.script #PS1="whadda you want? " PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ " #PS1="[\u@\h \W]\$ " whadda you want? source prompts.script [email protected] 2003-09-02 05:55:35 [15 ] $

Edita de nuevo el archivo, comentando la segunda línea y dejando de comentar la última (que restaura su intérprete al predeterminado de Red Hat Enterprise Linux).

[email protected] 2003-09-02 05:57:07 [16 ] $ cat prompts.script #PS1="whadda you want? " #PS1="\a\u@\H \$(date --iso-8601) \t [\!] \$ " PS1="[\u@\h \W]\$ "

Page 56: 6 la shell bash

La shell bash

56

Como un atajo, la shell bash también tiene un comando interno llamado ., el cual es un sinónimo para el comando source. Esta vez, blondie hace uso de su atajo al originar el archivo.

[email protected] 2003-09-02 05:57:09 [17 ] $ . prompts.script [blondie@station blondie]$

(Algo confuso, la palabra . adquiere diferentes significados en diferentes contextos. Cuando . aparece como la primera palabra en la línea, es sinónimo del comando source. Cuando . aparece en cualquier otra parte, es el directorio de inicio actual)

Inicialización de bash

Shells de Inicio, no inicio, interactivas y no interactivas

Habiendo aprendido cómo leer scripts de shell de modo arbitrario, ahora volvemos la atención a la inicialización de bash, la cual tiende a ser un tema demasiado complicado. Después de describir la secuencia de arranque, el proceso será resumido en una forma más sucinta. Para comenzar a distinguir sutilmente entre diferente tipos de shells: shells deinicio y no-inicio, y shells interactivasy no-interactivas.

Como el nombre lo dice, las shells de inicio de sesión son la primera shell que usted ve cuando inicia sesión en una máquina. Cuando usted inicia utilizando la consola virtual o dentro de una máquina remota, su primera shell interactiva es una shell de inicio. Cuando inicie mediante el entorno gráfico X, la shell no vista utilizada para empezar su inicialización X es una shell de inicio de sesión.

Cada shell de por medio se conoce como una shell de no-inicio de sesión. ¿Con qué frecuencia ve shells de no-inicio de sesión? Por todas partes. Obviamente, si usted fuera a iniciar manualmente una subshell, ésta sería una shell de no-inicio. Cada vez que usted abre una nueva terminal en un entorno gráfico X, la shell es una shell de no-inicio. Cada vez que usted usa la sustitución de comandos o comandos de grupo entre paréntesis, o ejecuta scripts de shell (como se describirá en la siguiente lección), se crea una nueva shell de inicio de sesión.

Además, las shells pueden ser interactivas o no-interactivas. Usualmente, las subshells iniciadas de forma manual o las shells en terminales X recién abiertas, son shells interactivas. Las shells invocadas como resultado de una sustitución de comandos y similares son shells no-interactivas. El siguiente cuadro ayudará a distinguir los diferentes tipos de shells.

Table 1. Diferentes tipos de shells bash

Contexto ¿Shell de inicio de sesión?

¿Shell interactiva?

Shells de inicio de sesión desde consolas virtuales Si Si

Page 57: 6 la shell bash

La shell bash

57

Contexto ¿Shell de inicio

de sesión? ¿Shell

interactiva?

Shells de inicio de sesión cuando se inicie dentro de una máquina a través de la red

Si Si

Shell de inicialización X Si Si

Shell de terminal X No Si

subshell iniciada al ejecutar manualmente bash No Si

subshell utilizada en sustitución de comandos No No

subshell utilizada para comandos agrupados en () No No

subshell utilizada al ejecutar scripts No No

El cuadro de arriba lista los predeterminados para Red Hat Enterprise Linux. Diferentes conductas pueden invocarse al especificar explícitamente ciertas opciones de línea de comandos. Vea la página del manual de bash(1) para obtener mayor información.

Scripts bash de arranque

¿Cuál es la diferencia entre una shell de inicio de sesión y una shell de no-inicio de sesión? o entre una shell interactiva y una no-interactiva? Principalmente, las shells difieren en qué archivos de inicialización se leen tras el inicio. A continuación, se indicará el bash de inicialización de shell como se presenta en Red Hat Enterprise Linux.

Shells de inicio de sesión

Tras el arranque, las shells de inicio de sesión primero leen el archivo /etc/profile . En Red Hat Enterprise Linux, este archivo inicializa varias variables de entorno tales como PATH, USER, HOSTNAME, y HISTSIZE . El script /etc/profile luego origina todos los archivos coincidentes al patrón /etc/profile.d/*.sh . [1]

Luego, la shell bash busca una serie de archivos en el directorio de inicio del usuario, y lee la primera que existe. En Red Hat Enterprise Linux, el archivo por defecto es ~/.bash_profile . La version por defecto de este archivo apenas agrega $HOME/bin al PATH del usuario, y busca y origina el archivo~/.bashrc descrito a continuación.

Shells de no-inicio de sesión (interactivas)

En lo que concierne al programa bash, el único archivo utilizado para personalizar shells de no-inicio de sesión es el archivo ~/.bashrc hallado en el directorio de inicio del usuario. En la configuración por defecto de Red Hat Enterprise Linux, la única personalización que este archivo realiza es buscar y leer el archivo /etc/bashrc .

Page 58: 6 la shell bash

La shell bash

58

El archivo global /etc/bashrc realiza varias operaciones, incluso establece la usmask por defecto del usuario y define la variable PS1 (la cual define el prompt de shell).

Shells de no-inicio de sesión (no interactivas)

Las shells no-interactivas de no-inicio de sesión no leen por defecto ninguno de los archivos de arranque (aunque esta conducta puede cambiarse estableciendo la variable de entorno BASH_ENV. Para mayor información ver la página de manual bash(1)).

Figure 1. Archivos de configuración de arranque bash

¿Por qué hay shells de inicio de sesión y shells de no inicio de sesión?

¿Por qué tanta complejidad? Al arrancar, los varios scripts de arranque leídos por shells de inicio tienden a emplear mucho tiempo personalizando variables de entorno (tales como el PATH, HISTSIZE del usuario, etc). No obstante, cuando las subsehells se inician,

Page 59: 6 la shell bash

La shell bash

59

no se necesita repetir todo este trabajo. Siempre que un proceso hijo es generado por la shell de inicio de sesión, sea ésta una subshell u otro caso, las variables de entorno se copian automáticamente en el hijo (por el kernel de Linux). Si la subshell luego lee los mismos scripts de arranque como su shell de inicio del padre, el esfuerzo de inicializar variables de entorno se duplicaría sin necesidad. Por lo tanto, con el fin de agilizar los tiempos de arranque, las shells de no-inicio intentan acortar el proceso. Otras personalizaciones de shell, principalmente los alias, son conceptos específicos de bash, no de nivel de kernel y deben reinicializarse cada vez que se inicie una nueva shell.

Al examinar los scripts de arranque listados arriba, observe que los archivos /etc/profile y ~/.bash_profile son leídos śolo por las shells de inicio de sesión, mientras que los archivos ~/.bashrc y /etc/bashrc son leídos por todas las shells (de inicio y no-inicio). Los dos archivos anteriores suelen utilizarse para configurar variables de entorno, porque sólo tienen que ser inicializadas una vez. Mientras que los dos últimos archivos se utilizan para personalizaciones específicas de la shell tales como alias y opciones de shell.

Observe la simetría. Para la configuración de variables de entorno, hay un archivo de arranque global (/etc/profile ) y un archivo de arranque local (~/.bash_profile ). El primero puede utilizarse por el administrador del sistema para establecer la configuración de todo el sistema. El último lo pueden utilizar usuarios individuales para personalizar su propio entorno. Una situación parecida se presenta con /etc/bashrc y ~/.bashrc .

Table 1. Archivos de configuración de arranque bash

Archivo Tipo de shell Uso previsto

/etc/profile Shells de inicio de sesión

Variables de entorno globalmente útiles

/etc/profile.d/*.sh Shells de inicio de sesión

Variables de entorno de paquetes específicos

~/.bash_profile Shells de inicio de sesión

Variables de entorno de usuarios específicos

~/.bashrc Todas las shells interactivas

Alias de usuario específico, funciones de shell y opciones de shell

/etc/bashrc Todas las shells interactivas

Alias globales, funciones de shell y opciones de shell

¿Por qué hay shells interactivas y no-interactivas?

Las shells no-interactivas son shells iniciadas como resultado de ejecutar un script (ver la siguiente lección), usando paréntesis para agrupar comandos o usando sustitución de comandos. Con el fin de evitar posibles efectos secundarios del script de arranque, las shells no-interactivas no leen scripts de arranque tras el inicio.

Page 60: 6 la shell bash

La shell bash

60

Salida de las shells de inicio de sesión: ~/.bash_logout

Tras la salida, las shells de inicio de sesión leerán el archivo ~/.bash_logout si existe. En Red Hat Enterprise Linux, el archivo simplemente ejecuta el comando clear para que la pantalla se limpie de información tras la salida.

Ejemplos

El comando su revisitado

En un cuaderno anterior, presentamos el comando su como una forma de cambiar el userid (cambiar el id del usuario). En ese momento, introdujimos dos modos de usar el comando su. El primero era simplemente su nombredeusuario , el cual inicia una nueva shell de no-inicio como el nuevo usuario. El segundo es ejecutar su - nombredeusuario , el cual inicia una shell de inicio de sesión como el nuevo usuario.

Con el fin de explorar las implicaciones de estos dos modos haremos que blondie agregue la siguiente línea a su archivo ~/.bash_profile .

echo "~/.bash_profile sourcing"

Del mismo modo, agrega la siguiente línea a su archivo ~/.bashrc .

echo "~/.bashrc sourcing"

Ahora haremos que el usuario elvis haga su en blondie usando ambas formas.

[elvis@station elvis]$ su blondie Password: ~/.bashrc sourcing [blondie@station elvis]$ exit exit [elvis@station elvis]$ su - blondie Password: ~/.bashrc sourcing ~/.bash_profile sourcing

En el primer caso, sólo el archivo ~/.bashrc fue leído. En el segundo caso, tanto ~/.bash_profile como ~/.bashrc son leídos.

De modo explícito, ejecutando source en /etc/profile y ~/.bash_profile

A menudo en este cuaderno y en las direcciones de Linux (y Unix), en general, se les pide a los usuarios "salir e ingresar otra vez" para que los cambios de configuración surtan efecto. Esto suele darse porque al instalar un nuevo software o algún otro cambio se han alterado los archivos de configuración del usuario (o del sistema) bash y las direcciones desearían que el usuario reiniciara la shell para que los archivos de arranque sean leídos otra vez.

Page 61: 6 la shell bash

La shell bash

61

A menudo, los usuarios pueden evitarlo releyendo los archivos clave de configuración en su lugar. Por ejemplo, si blondie sospecha que un cambio ha ocurrido en el sistema de archivos de arranque bash, podría leer de modo manual el archivo /etc/profile .

[blondie@station blondie]$ . /etc/profile

De otro modo, si blondie sospecha que sus archivos de arranque locales bash han cambiado, entonces puede leer su archivo de configuración local bash manualmente.

[blondie@station blondie]$ . ~/.bash_profile

(Observe que esto no funcionaría para todos los cambios de configuración, sino sólo para aquellos relacionados con la shell bash. Por ejemplo, si una membresía de grupo de usuarios ha cambiado, entonces el usuario sí tiene que salir e ingresar otra vez para que los cambios surtan efecto)

Ejercicios en línea

Lab Exercise Objetivo: Configurar los scripts de arranque bash

Estimated Time: 10 mins.

Especificaciones

1. Agregue la siguiente línea a su archivo de arranque ~/.bashrc .

echo "sourcing ~/.bashrc"

2. Agregue la siguiente línea a su archivo de arranque ~/.bashrc .

echo "sourcing ~/.bash_profile"

3. Agregue la siguiente línea a su archivo ~/.bash_logout .

rm -fr ~/.Trash/*

Deliverables

A title

Question 1

1. Una shell bash que tras el arranque de una shell de no-inicio de sesión emita el

mensaje sourcing ~/.bashrc 2. Una shell bash que tras el arranque de una shell de inicio de sesión emita los

Page 62: 6 la shell bash

La shell bash

62

mensajes sourcing ~/.bashrc y sourcing ~/.bash_profile . 3. Una shell bash que tras la salida de una shell de inicio de sesión suprima el

contenido (no-oculto) de la papelera de Nautilus.