Shell y Comandos

Anuncio
CAPITULO IV
Shell y comandos
1
La Shell
Todo S.O. debe proveer un mecanismo para que el/los usuarios puedan comunicarle lo que
quieren realizar y para poder interactuar con el. Linux posee una interfase de comunicación
llamada "shell" y es el medio mediante el cual el usuario puede comunicarle comandos al sistema
y recibir la salida de los procesos con los que interactúa.
Básicamente, la shell es un proceso mas que obviamente se ejecuta en primer plano, ya que sino
seria imposible interactuar con el mismo. Su funcionamiento se limita a recibir comandos del
usuario, interpretarlos y ejecutar las tareas necesarias en respuesta a los mismos. El nombre
técnico de la shell puede ser "interprete de comandos". Su función se puede comparar a la del
programa "comand.com" en MS-DOS que esencialmente realiza las mismas tareas.
En los sistemas UNIX cada usuario puede elegir que shell quiere utilizar para comunicarse con el
sistema. Linux tiene varias shells las cuales pueden ser elegidas por el usuario. Inclusive es
posible que el usuario programe y utilice su propia shell si así lo desea. Las shells que Linux
provee son:
9
sh:
Shell de Bourne. Es la shell mas utilizada en los sistemas UNIX.
9
csh:
Shell de C. Es la shell preferida por los programadores. Es compatible con la shell
_______de Bourne.
9
ash:
Shell de Ash. Es una versión especial reducida. Se utiliza cuando existe muy poca
_______memoria disponible.
9
ksh - pdksh: Shell de Korn. Extensión de la shell de Bourne.
9
bash:
Bourne Again Shell. Es la shell de la FSF (Free Software Fundation). Amplia las
_______capacidades de la shell de Bourne y es utilizada por Linux como shell
_______predeterminada.
9
zsh:
Z Shell. Compatible con la shell de Bourne.
Funcionamiento de la Shell
La shell es iniciada inmediatamente cuando un periodo de inicio de sesión es autenticado
exitosamente. El sistema recuerda cual es la shell que utiliza cada usuario y carga la
correspondiente al usuario que inicio la sesión. Desde este momento, la shell muestra un
identificador llamado "prompt" que significa que esta esperando que el usuario ingrese una orden.
Una vez que se visualiza el prompt, el usuario puede ingresar cualquier orden, ya sea para que se
ejecute en primer plano o en "background". Si el pedido de ejecución dado por el comando
ingresado especifica que el proceso se debe ejecutar en "background", el proceso se inicia y se
comienza a ejecutar en "background", por lo que el shell inmediatamente vuelve a mostrar
el prompt y al estado de espera de mas ordenes. Así es posible seguir ejecutando órdenes. Si el
proceso se debía ejecutar en primer plano, la shell no retorna el prompt hasta que el proceso
2
ejecutado se termine. Por lo tanto debemos esperar a que termine el proceso para poder iniciar
otro.
Comandos
NOTA: Desde esta sección en adelante todo lo referente a la shell y sus comandos estará
basado en la shell bash (Bourne Again Shell) que es la shell predefinida en Linux :)
El uso interactivo típico de la shell se basa en ingresar comandos simples, comandos con
calificadores, comandos con facilidades de generación de nombres de archivos, redirección de
entrada-salida, y comandos combinados mediante el uso de "cañerías". Estas técnicas son
poderosas y extremadamente útiles, pero son solo una parte de las capacidades de la shell.
La shell es, además de intérprete interactivo de comandos, un intérprete de un lenguaje de
programación de comandos llamado "El lenguaje de programación de la shell". Este lenguaje nos
permite realizar nos permite realizar "scripts" que será posible ejecutar como un programa binario
mas, con la diferencia que lo interpreta la shell línea por línea y ejecuta los comandos
correspondientes. Más adelante nos ocuparemos de analizar este lenguaje de programación en
profundidad, ya que es una de las características más poderosas de la shell y nos sirve para
automatizar muchas de las tareas que tenemos que realizar en el sistema y nos ayuda a ahorrar la
cantidad de comandos que tenemos que tipear.
Comandos Simples
Un comando simple es una secuencia de (una o más) palabras separadas por espacios o
tabuladores. La primera palabra de la secuencia es el nombre del comando. Las palabras
subsiguientes son los argumentos del comando. Los comandos más simples son de una sola
palabra.
Los comandos más comunes pueden ser: ls para listar el contenido de un directorio, ps para ver
los procesos que se encuentran creados en el sistema, reboot para reiniciar el sistema, etc.
3
Argumentos
Los comandos, en su forma más simple, se ejecutan simplemente poniendo el nombre del archivo
correspondiente. Sin embrago, existen comandos que necesitan argumentos para trabajar. Un
ejemplo de esto puede ser el comando cp que sirve para copiar archivos. Este comando necesita
dos argumentos obligatorios, el/los archivo fuente y el destino de la copia.
Por ejemplo:
==> cp /home/juan/cuotas.tex /home/tony/
Los argumentos se utilizan para pasar información adicional a los programas que ejecutamos. En
algunos casos son opcionales, en otros obligatorios y puede ser que la cantidad de argumentos de
algunos comandos pueda ser variable. La gran mayoría de las veces los argumentos serán
nombres de archivos o de directorios, pero esto es dependiente de cada programa.
El nombre del comando y sus argumentos deben ser separados por uno o mas espacios, sino la
shell nos informara del error con un mensaje. Ejemplo:
==> ls/bin
bash: ls/bin:
No such file or directory
Otros argumentos son los "modificadores" que son formas de pasar opciones a los programas y
serán tratados a continuación.
Modificadores
Los comandos, usualmente, sirven para realizar una función pero pueden aceptar varias opciones
que especifiquen como se debe realizar esta tarea. Las opciones que cada comando acepta y la
sintaxis con la que se especifica la opción dependen exclusivamente del comando en cuestión.
Aunque en general se puede hablar de "modificadores" que son la forma general de ingresar las
Opciones a los comandos. Consideremos el siguiente comando:
==> ls -a
Este comando listara el contenido del directorio actual, pero mostrara además los que comienzan
con ".", ya que estos son ocultos y al ejecutar ls no son mostrados. Este comportamiento es
especificado por la opción de mostrar los archivos ocultos que es seleccionada con el modificador a (all).
NOTA: Un modificador muy útil es -h que sirve para especificarle a un comando que
nos muestre su sintaxis y las opciones que soporta. Esto sirve como referencia del
funcionamiento del comando. Este modificador se puede usar con la mayoría de los
comandos de Linux. Algunos comandos soportan --help o -help para la misma función.
4
Separador de Comandos
Para ingresar varios comandos en una sola linea es necesario separarlos por ";". Por ejemplo:
==> date;df -h
La salida de este comando sera la siguiente:
Thu Apr 15 17:29:15 ART 2004
Filesystem
Size Used
/dev/hda3
1.6G 613M
/dev/hdc1
2.0G 1.9G
/dev/hda2
298M 238M
/dev/hda1
2.0G 1.5G
Avail
963M
138M
60M
546M
Capacity
39%
93%
80%
73%
Mounted on
/
/akenaton
/games
/nt
La primera línea de la salida es generada por el comando date y muestra la hora y el día actual en
el sistema. La tabla que es mostrada a continuación es generada por el comando df y muestra las
capacidades, tamaños utilizados y disponibles, y puntos de montaje de los distintos sistemas de
archivos que se encuentran montados. Notemos que las unidades se muestran en distintos
formatos de acuerdo al valor que tenga cada campo. Esto es causado por la opción -h que indica
al comando que muestre los valores con unidades significativas y no en numero de bloques.
La entrada estándar y la salida estándar
Los programas basados en el modelo de entrada/salida por teletipo son aquellos en los que su
salida consiste en líneas de texto ASCII. Estos programas ofrecen solo una primitiva interfase con
el usuario basada en línea de comandos. Pero justamente por esto, y por la funcionalidad que
provee la shell, es posible interconectar varios programas que realizan tareas simples para realizar
tareas mas complejas. Todos los comandos de Linux y la mayoría de sus utilidades se encuentran
basados en este modelo. Por esto es importante entender el funcionamiento e interacción de los
programas, la shell y la entrada/salida para sacar provecho a estas facilidades.
Cuando un programa, del modelo de teletipo, produce una salida sobre una Terminal el programa,
en general, esta realizando operaciones de salida a lo que se denomina salida estándar (stdout).
Asimismo, cuando tipeamos algo en el teclado de la Terminal, un programa lee los caracteres de lo
que se llama entrada estándar (stdin). Para comunicar errores y mensajes de diagnostico, existe
una conexión de salida separada llamada stderr.
5
La shell, por ejemplo, es un programa que lee caracteres de stdin e interpreta los mismos como
comandos, argumentos, etc. El comando ls envía su salida (el contenido del directorio de trabajo)
a stdout y luego se visualiza en nuestra pantalla. Este funcionamiento es el predefinido, ya que
la entrada estándar y la salida estándar se encuentran, normalmente, asociadas a la terminal de la
computadora, stdin el teclado y stdout a la pantalla.
La shell, sin embargo, nos permite reasignar o redireccionar las conexiones de entrada, salida o la
de diagnostico de errores. Esta es una de las características mas poderosas de Linux :)
Redireccionando la Salida
Supongamos que ejecutamos el comando ps (process status), el cual nos reporta del estado de los
procesos, que nosotros iniciamos, que se están ejecutando en el sistema. La figura nos muestra
la salida generada por una ejecución del comando ps. Así visualizamos la salida en nuestra
pantalla.
# ps
PID TTY STAT
338
1 S
356
1 S
368
1 S
372
1 S
373
1 S
377
1 S
381
1 S
394
1 S
412 p0 S
415
1 S
479
1 S
515 p0 R
TIME COMMAND
0:00 /bin/login -- root
0:00 -bash
0:00 sh /usr/X11R6/bin/startx
0:01 wmaker
0:06 kfm
0:00 wmmon
0:00 mount.app
0:37 emacs
0:01 kdvi apunte.dvi
0:01 /usr/local/bin/x11amp
0:00 kvt
0:00 ps
Ejecucion del comando ps
Si nos interesa guardar la salida del comando ps, por ejemplo para analizarla posteriormente,
podemos hacer uso de la redirección de la salida que nos brinda la shell. Le indicamos a la shell
que queremos redireccionar la salida con el símbolo ">". Entonces, en nuestro ejemplo, debemos
ejecutar el comando como indica la figura. En la misma, observamos que el comando termina de
ejecutarse sin realizar ninguna salida en la pantalla, pues la salida del comando se envió al archivo
"procesos" y fue guardada en el mismo. Luego mostramos el contenido del archivo procesos, con
el comando cat, y visualizamos la salida que el comando ps realizo al ejecutarse.
6
# ps > procesos
# cat procesos
PID TTY STAT TIME COMMAND
338
1 S
0:00 /bin/login -- root
356
1 S
0:00 -bash
368
1 S
0:00 sh /usr/X11R6/bin/startx
372
1 S
0:01 wmaker
373
1 S
0:06 kfm
377
1 S
0:00 wmmon
381
1 S
0:00 mount.app
394
1 S
0:37 emacs
412 p0 S
0:01 kdvi apunte.dvi
415
1 S
0:01 /usr/local/bin/x11amp
479
1 S
0:00 kvt
515 p0 R
0:00 ps
b. Ejecución del comando ps redireccionando la salida al archivo
"procesos"
NOTA: No es necesario que el archivo sobre el cual escribimos al redireccionar la salida exista
antes de ejecutar el comando ya que la shell crea el archivo, si es necesario.
Redirección no-destructiva de la Salida
Al redireccionar la salida de un comando a un archivo se sobrescribe completamente los
contenidos del mismo. Hay ocasiones en las que no queremos perder la información almacenada
en un archivo, sino agregarle datos al final del mismo. En el ejemplo de la figura anterior, los
contenidos del archivo procesos, si existían antes de ejecutarse el comando, son sobrescritos.
Para poder concatenar información en un archivo usamos ">>" en vez de ">".
Redireccionando la conexión de errores estándar
La conexión de errores estándar es la segunda conexión de salida que el S.O. Linux abre para
cada programa. Normalmente es conectada a la Terminal, o sea a nuestra pantalla, y es por eso
que cada vez que un programa muestra un mensaje de error, este es visualizado en ella. Si
ejecutamos un comando y redireccionamos la salida del mismo a un archivo, no estamos
cambiando para nada la conexión de errores estándar de ese comando, por lo que cualquier
mensaje de error que el comando reporte será visualizado en pantalla. Esto ocurre porque la
conexión de errores estándar no se encuentra redireccionada. Hay programas que producen una
cantidad voluminosa de salida. En estos casos uno puede querer redireccionar la conexión de
errores estándar a un archivo, para luego examinar los mensajes que el programa genero. Para
redireccionar la conexión de errores estándar se utiliza "2>". El numero 2 indica el numero de
conexión de salida que es justamente la conexión de errores estándar.
7
Redireccionando la entrada
También es posible redireccionar la entrada. Ya vimos que uno de los programas que lee la
información de la entrada es la shell, los demás programas que vimos (ls, ps, cat, etc.) producen
su salida sin leer de la entrada estándar. La shell lee los comandos a ejecutar de la entrada
Standard. Como la entrada estándar puede ser redireccionada a un archivo, es posible que la shell
obtenga los comandos a ejecutar desde un archivo. Un ejemplo de esta situación se muestra en la
figura 6.2. En la misma vemos que los contenidos del archivo "comandos" son los nombres de dos
comandos de Linux: date y ps. Luego utilizando el símbolo "<" redireccionamos la entrada del
programa bash (Bourne Again Shell) al archivo comandos y los resultados se muestran en
pantalla.
Redireccionando la salida y la entrada simultáneamente
Es posible redireccionar, simultáneamente, la entrada estándar y la salida estándar. Cuando esto
sucede, el único rol que cumple la Terminal es ingresar el comando que vamos a ejecutar, pero
luego el programa trabaja sin tener asociada la entrada ni la salida a la Terminal. Salvo que no se
redireccione la conexión de errores estándar porque los mensajes de error serian visualizados en
pantalla. La forma de redireccionar la salida y la entrada simultáneamente se muestra con un
ejemplo en la figura 6.3.
Cañerías: la interconexión entre programas
Las cañerías (pipes) conectan la salida estándar de un programa con la entrada estándar de otro
programa. Una cañería es diferente a la redirección de la entrada/salida. Al redireccionar la
entrada conectamos la entrada de un programa a un archivo y al redireccionar la salida
conectamos la salida del programa a un archivo. Una cañería conecta la salida de un programa
directamente con la entrada de otro programa. Ver figura 6.4.
Para construir una cañería debemos separar los comandos que queremos conectar con el símbolo
"|".
En el ejemplo de la figura 6.5, conectamos dos comandos: ls y wc. El primero nos lista el
contenido de un directorio, en este caso del directorio /bin. El segundo comando, wc (word count)
sirve para contar palabras, líneas y caracteres, pero al pasarle la opción -w le estamos diciendo
que solo cuente palabras. El funcionamiento de este pipe es muy simple: El comando ls lee el
contenido del directorio /bin y genera una lista de palabras con los nombres de los archivos y
8
directorios encontrados. Esta lista, en vez de ser enviada a la Terminal, es redireccionada a la
entrada estándar del comando wc que comienza a contar las palabras y muestra el resultado en la
salida estándar del mismo que es la Terminal.
Generación de nombres de archivos
El S.O. Linux nos permite especificar conjuntos de nombres de archivos automáticamente
utilizando "generación de nombres de archivos y caracteres comodines". Cuando ingresamos
argumentos a un comando, la shell examina los mismos con el objeto de detectar el uso de la
generación de nombres de archivos. El usuario controla la generación de nombres de archivos
especificando un modelo para los nombres de archivo. La shell compara el modelo provisto con
todos los archivos del directorio de trabajo. Si alguno de los nombres de archivo responde al
modelo, entonces una lista ordenada alfabéticamente con todos los nombres de archivos que
responden al modelo es enviada al programa. Si ninguno de los nombres de archivo del directorio
actual cumple con el modelo, entonces el modelo (en forma textual) es enviado al programa como
argumento. Un modelo consiste de caracteres ordinarios y de "metacaracteres" llamados
caracteres
comodines.
Los
caracteres
ordinarios
son
interpretados
textualmente;
los
metacaracteres tiene un significado propio. Los metacaracteres utilizados para la generación de
nombres de archivo y sus significados se muestran en la tabla 6.1.
|øøøøøøøøøøøøøø|øøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøø|
| Metacaracter |
Significado
|
|--------------|----------------------------------------------------------|
|
*
| Equivale a cualquier cadena de caracteres
|
|
?
| Equivale a cualquier caracter
|
|
[
| Comienza una clase de caracteres
|
|
]
| Termina una clase de caracteres
|
|
| Indica un rango de caracteres en una clase de caracteres |
|______________|__________________________________________________________|
Tabla 6.1: Metacaracteres utilizados para generacion de nombres de archivo.
El asterisco y el signo de pregunta son muy fáciles de usar. Por ejemplo *.c equivale a todos los
archivos que tienen como sufijo .c como pueden ser: prog.c, ab.c, Main.c; los siguientes nombres
no satisfacen el modelo unit2.cc, main.c.cc; el modelo ???.tex equivale a todos los nombres de
archivo que tengan tres caracteres cualesquiera y luego el sufijo .tex,
Por ejemplo:
ref.tex, cp1.tex, bea.tex, c++.tex, cumplen con el modelo pero ab.tex, tony.tex, intro.tex
chapter1.tex.z no lo satisfacen.
9
Los corchetes y el signo menos se utilizan para formar modelos para grupos de caracteres. Los
caracteres en el grupo (o clase) son especificados dentro de los corchetes. El modelo abc[aeiou]
representa todo nombre de archivo que comience con abc y culmine con una única vocal. El signo
menos se utiliza para especificar rangos de caracteres. El modelo chapter[0-9] representa a todos
los nombres de archivo que comienzan con chapter y finalizan con un digito. Notemos que el
rango incluye a sus límites.
Es necesario realizar una aclaración con respecto a los archivos ocultos. Recordemos que todo
archivo tal que su nombre comience con un punto es considerado un archivo oculto. La generación
de nombres de archivos no considerara que un modelo representa a un archivo oculto si no se
especifica explícitamente el punto al comienzo del modelo.
Por ejemplo: El modelo xinit* no representara al archivo cuyo nombre es .xinitrc. Para solucionar
esto es necesario especificar el modelo de la siguiente forma .xinit*.
# ps
PID TTY STAT
338
1 S
356
1 S
368
1 S
372
1 S
373
1 S
377
1 S
381
1 S
394
1 S
412 p0 S
415
1 S
479
1 S
515 p0 R
TIME COMMAND
0:00 /bin/login -- root
0:00 -bash
0:00 sh /usr/X11R6/bin/startx
0:01 wmaker
0:06 kfm
0:00 wmmon
0:00 mount.app
0:37 emacs
0:01 kdvi apunte.dvi
0:01 /usr/local/bin/x11amp
0:00 kvt
0:00 ps
a. Ejecucion del comando ps
# ps > procesos
# cat procesos
PID TTY STAT TIME COMMAND
338
1 S
0:00 /bin/login -- root
356
1 S
0:00 -bash
368
1 S
0:00 sh /usr/X11R6/bin/startx
372
1 S
0:01 wmaker
373
1 S
0:06 kfm
377
1 S
0:00 wmmon
381
1 S
0:00 mount.app
394
1 S
0:37 emacs
412 p0 S
0:01 kdvi apunte.dvi
415
1 S
0:01 /usr/local/bin/x11amp
479
1 S
0:00 kvt
515 p0 R
0:00 ps
b. Ejecucion del comando ps redireccionando la salida al archivo
"procesos"
Figura 6.1: Redireccionando la salida del comando ps.
10
# cat comandos
date
ps
# bash < comandos
Thu Apr 15 19:47:03 ART 1999
PID TTY STAT TIME COMMAND
338
1 S
0:00 /bin/login -- root
356
1 S
0:00 -bash
368
1 S
0:00 sh /usr/X11R6/bin/startx
372
1 S
0:01 wmaker
373
1 S
0:06 kfm
377
1 S
0:00 wmmon
381
1 S
0:00 mount.app
394
1 S
0:37 emacs
412 p0 S
0:01 kdvi apunte.dvi
415
1 S
0:01 /usr/local/bin/x11amp
479
1 S
0:00 kvt
515 p0 R
0:00 ps
Figura 6.2: Redireccionando la entrada para que la shell ejecute
comandos desde un archivo.
# cat comandos
date
pwd
# bash < comandos > salida
# cat salida
Thu Apr 15 20:06:30 ART 1999
/home/tony/docs/linux
Figura 6.3: Redireccionando la entrada y la salida.
|øøøø|__
<------------------------------------------------------\
|---|____| |_____
|
|
|
|
|
stderr
|
|
|______|
| -----------------------------------> |øøøøøøøø|
|
|
|
|
|
|
|
|---------|
|
_--> |________|
|
| PROG1
|
|
|
|
|
|______________| --\
|
/øøøøøøøøø\ --/
| stdout
|
øøøøøøøøøøøøø
|
|
|
|
|
|
\
|
|
|
|øøøø|__
|
|
|---|____| |_____
|
|
|
|
|
| <--/ stdin
|
|
|______|
|
|
|
|
|
|
|---------|
|
stdout & stderr |
| PROG2
|
|
|______________| -----------------------------/
Figura 6.4: Ca¤eria de dos programas.
# ls /bin | wc -w
75
Figura 6.5: Ejemplo de una ca¤eria. Contar la acntidad de
archivos en un directorio.
11
Descargar