Práctica 1: Uso del Shell

Anuncio
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
Práctica 1: Uso del Shell
1. Introducción
Entrada en el sistema o login
Unix es un sistema multiusuario, es decir, permite que varios usuarios utilicen la misma máquina
de forma segura. Para ello es necesario que cada usuario tenga una identificación que permita al
sistema saber quién está utilizando la máquina en cada momento, y qué cosas tiene permiso para
hacer (qué operaciones y sobre qué recursos). Esta identificación es lo que se conoce como nombre
de usuario o login name, y es lo primero que el sistema nos pide que introduzcamos cuando queremos abrir una sesión.
Para evitar que ningún usuario pueda hacerse pasar por otro, cada usuario tiene asociada una
clave de acceso o password, que el sistema nos pide que introduzcamos a continuación y que le
permitirá verificar que realmente el usuario es quien dice ser. Si la clave de acceso es la correcta,
el usuario puede empezar a trabajar en el sistema.
angren
login: e3432065 <cr>
password: ???????? <cr>
Figura 1: Entrada en el sistema
Cuando introducimos el password éste no aparece por la pantalla, para evitar que nadie descubra
nuestra contraseña por accidente.
En Unix existe un usuario especial, root (superusuario), que es el único con privilegios para acceder a todos los datos del sistema y realizar las tareas de administración.
Password
El password es una secuencia de entre 6 y 8 caracteres alfanuméricos (si se introducen más caracteres se ignoran los finales). Es recomendable que sea una combinación de letras mayúsculas,
minúsculas, caracteres especiales y números, y que no sea fácilmente deducible, para dificultar que
otros usuarios la descubran. Por este motivo, también es conveniente cambiarla periódicamente.
Para modificar la contraseña, disponemos del comando passwd.
angren% passwd
Changing password for e3432065
Old password:
New password:
Retype new password:
Figura 2: Cambio de password para el usuario e3432065
Existe un fichero en el sistema que almacena los passwords de todos los usuarios (/etc/passwd).
Este fichero puede ser leído por cualquier usuario, pero sólo puede ser modificado por el superusuario (y por el comando passwd). La clave de acceso se guarda encriptada, para evitar que se pueda descubrir al leer este fichero. Además de la contraseña, para cada usuario se guarda información
adicional, como por ejemplo cuál es el primer programa que se debe ejecutar cuando ese usuario
inicia una sesión o cuál es el directorio del sistema de ficheros en el que inicia la sesión (ver figura
Práctica 1: Uso del Shell
1
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
3).
login_name:passwd_encriptado:uid:gid:comentarios:login_directory:/usr/bin/csh
• Nombre de usuario o login name
• Clave de acceso
• Identificador de usuario (uid): internamente, el sistema operativo identifica
cada usuario a través de este entero
• Identificador de grupo del usuario (gid): en Unix es posible agrupar los usuarios
en función de alguna característica común, y dar un identificador a cada grupo.
Por ejemplo, todos los alumnos podrían formar un grupo y los profesores otro.
• Comentario sobre el usuario: depende del administrador, por ejemplo puede ser el
nombre y apellidos del usuario, teléfono de contacto, etc
• Directorio base de los ficheros del usuario (directorio de login): normalmente
cada usuario tiene asignada una zona de trabajo dentro del sistema de ficheros, y
cuando el usuario entra en el sistema lo hace en el directorio base de esa zona
• Primer programa de usuario que se tiene que ejecutar cuando éste inicia la sesión
(normalmente es un intérprete de comandos)
Figura 3: Línea del fichero de passwords: información de un usuario
Intérprete de comandos
Un intérprete de comandos (shell en UNIX) es un programa que facilita el uso interactivo del
sistema operativo. El shell recibe las operaciones o comandos que el usuario quiere realizar y solicita al sistema operativo que las lleve a cabo. Existen varios intérpretes de comandos muy conocidos, y adenás cada usuario podría programar el suyo propio. Alguno de los intérpretes más
difundidos con UNIX son el C-shell (/bin/csh), el Bourne shell (/bin/sh) y el Korn shell (/bin/ksh).
El intérprete de comandos que utilizaremos en las prácticas de ISOP es el C-shell.
Normalmente, los usuarios tienen un intérprete de comandos como programa de inicio de sesión,
y cada usuario puede decidir cuál quiere utilizar mediante el comando chsh (figura 4) De esta
angren% chsh -s /bin/csh e3432065
Figura 4: El shell inicial del usuario e3432065 pasa a ser el c-shell
manera, la próxima vez que el usuario inicie una sesión lo hará ejecutando el nuevo shell. Además,
un shell se puede lanzar en cualquier momento como cualquier otro programa de usuario, y finalizar su ejecución con los comandos exit o logout o pulsando las teclas ctrl-d.
El comportamiento habitual de un intérprete de comandos es el siguiente. Cuando el shell está
preparado para recibir un comando, se lo indica al usuario mostrando por pantalla el prompt. El
prompt puede ser un único carácter ($, %, >, ...), o una cadena de carácteres (el login name del
usuario, el nombre de la máquina, ...), y cada usuario puede decidir el prompt que quiere utilizar
en sus sesiones. Una vez que el usuario introduzca un comando, el shell hará lo necesario para que
se ejecute y esperará a que finalice la ejecución. Cuando esto ocurra, volverá a mostrar por pantalla
el prompt para que el usuario sepa que el shell ya está preparado para recibir la siguiente petición.
Comandos
Los comandos son la forma que tiene un usuario (no programador) de solicitar servicios al sistema.
Estos comandos pueden ser funciones que los intérpretes implementan (comandos internos), o
pueden ser programas separados (comandos externos) que los intérpretes lanzan. Por lo tanto, los
comandos internos disponibles dependerán del intérprete de comandos que se esté utilizando. Bajo
el punto de vista del shell, cualquier programa que el usuario intente lanzar es un comando externo.
Práctica 1: Uso del Shell
2
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
Salida del sistema o logout
Para finalizar la sesión el usuario debe introducir los comandos logout o exit, o pulsar ctrl-d.
Esto provocará que el intérprete de comandos finalice su ejecución, haciendo que vuelva a ejecutarse el proceso encargado de recibir peticiones de entrada (vuelve a salir la petición de login).
2. Primeros Comandos
Examinar el entorno
date
cal [[mes] año]
who
finger
ps
muestra la fecha y hora actual
muestra el calendario de la fecha especificada
lista todos los usuarios que en ese momento tienen una sesión abierta en la máquina.
lista de todos los usuarios con información general almacenada
muestra los procesos que el usuario tiene en ejecución
Gestionar el directorio
ls
cd nombre_directorio
pwd
mkdir nombre_directorio
rmdir nombre_directorio
cp fuente destino
rm fichero
mv fichero nuevo_nombre
cat [fichero]
more [fichero]
wc [fichero]
lista de los ficheros de un directorio
hace que el directorio actual pase a ser nombre_directorio
muestra cuál es el directorio actual
crea un subdirectorio llamado nombre_directorio
borra el subdirectorio nombre_directorio
copia el fichero fuente sobre el fichero destino
borra un fichero
cambia el nombre de un fichero; si nuevo_nombre es un directorio, el fichero
conserva el nombre pero se mueve al directorio especificado
muestra el contenido de un fichero
muestra el fichero pantalla a pantalla
cuenta el número de líneas, palabras y caracteres del fichero
3. El Sistema de Ficheros
3.1. Nombres de ficheros
Un nombre válido de fichero es cualquier concatenación de caracteres de longitud inferior a 256.
Conviene que los nombres no contengan caracteres especiales del shell (? * ' “ / \) para no complicar el uso de esos nombres. Los nombres de fichero que empiezan por punto (.) sólo se visualizan
con la opción -a del comando ls.
3.2. Organización del sistema de ficheros
Los ficheros se pueden agrupar en directorios que a su vez pueden contener otros directorios. De
esta manera, se obtiene un sistema de ficheros organizado de forma jerárquica. Normalmente un
usuario tiene asignado un directorio de login, en el que está situado cuando entra en la sesión, y en
el que puede dejar sus ficheros y crear sus propios directorios. Una vez dentro de la sesión el usuario puede moverse por el sistema de ficheros utilizando el comando cd, siendo el directorio actual
o current working directory aquél en el que se encuentra en cada momento.
El directorio raíz (root) es el origen de la jerarquía y su nombre es una barra (/). Tradicionalmente este directorio, contenía los siguientes directorios:
Práctica 1: Uso del Shell
3
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
• el directorio /bin contiene los programas de utilidad más utilizados en el sistema.
• en el directorio /etc se encuentran ficheros con datos que se usan en la gestión del
sistema. Por ejemplo el fichero /etc/passwd.
• el directorio /tmp sirve para almacenar ficheros temporales. Los comandos y utilidades
del sistema pueden crear ficheros en este área que tras su ejecución pueden ser borrados.
• en el directorio /lib se encuentran las librerías de programas que se pueden montar con
programas creados por el usuario en C, FORTRAN o cualquier otro lenguaje de
programación disponible.
• el directorio /usr es un directorio de propósito general que algunas veces contiene las
áreas de trabajo de los usuario. Contiene también otros directorios como el /usr/bin con
programas de utilidad.
• el directorio /dev contiene ficheros de tipo dispositivo: impresoras, terminales, cintas,...
Aunque este tipo de organización no es obligatoria, todavía es la elegida por muchos administradores de sistemas.
3.3. Pathnames
A la hora de identificar un fichero concreto dentro de la estructura de directorios se puede usar su
pathname absoluto o pathnames relativos. El pathname absoluto de un fichero consiste en todos
los directorios que se deben seguir desde la raíz hasta llegar a él, finalizando con el nombre del
fichero. Los pathnames relativos consisten en los directorios que hay que recorrer desde el directorio actual hasta el fichero, finalizando también con el nombre del fichero.
Por ejemplo, el fichero llamado fichero1 que aparece en el sistema de ficheros de la figura 5
tiene como pathname absoluto: /u2/est/e3432065/practica1/fichero1; suponiendo que el directorio
actual sea /u2/est/e3432065, el pathname relativo del mismo fichero sería: practica1/fichero1; por
último, si el directorio actual fuera /u2/est/e3432065/practica1, entonces el pathname relativo sería
únicamente su nombre: fichero1.
/
pathname
absoluto
u2
est
directorio
de trabajo a
pathname
relativo a
e3432065
practica1
fichero1
directorio
de trabajo b
pathname
relativo b
Figura 5: Pathname de un fichero
3.4. Permisos de acceso a los ficheros
La opción -l del comando ls produce un listado de los ficheros del directorio con una serie de
información adicional acerca de cada fichero. Entre esta información encontramos el tipo de
fichero, el propietario del fichero y el grupo al que pertenece el fichero, la fecha y hora en las que
fue modificado por última vez y los permisos de acceso que tiene asociados.
El primer carácter de la información del fichero indica el tipo de fichero (por ejemplo, una d
significa que se trata de un directorio, y un - significa que es un fichero ordinario). Los siguientes
tres caracteres indican si el propietario del fichero puede leerlo, escribir en él o ejecutarlo, respecPráctica 1: Uso del Shell
4
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
tivamente. La representación que se utiliza es un guión (-) para indicar que no se puede realizar esa
operación o las letras r (lectura), w (escritura) o x (ejecución), para indicar que si que es posible. A
continuación vienen otros 6 caracteres que se interpretan de la misma manera, pero referidos a los
usuarios del mismo grupo que el propietario y al resto de usuarios.
En el ejemplo de la figura 6, el propietario de fichero1 (e3432065) lo puede leer y modificar,
pero no lo puede ejecutar. Los usuarios del mismo grupo que el propietario (est) sólo lo pueden
leer, y el resto de usuarios del sistema también pueden leerlo únicamente.
angren% pwd
/u2/est/e3432065/practica1
angren% ls -l
-rw-r--r-- 1 e3432065 est 1024 Sep 15 10:00 fichero1
angren%
Figura 6: Permisos de acceso de un fichero
La codificación interna de estos permisos es mediante 3 dígitos en octal, tal y como se ve en la
figura 7.
rw-r--r-1 1 0/10 0/100
4 (resto de usuarios)
4 (usuarios del mismo grupo)
5 (propietario del fichero)
Figura 7: Representación en octal de los permisos de acceso
Tener permiso de ejecución sobre un directorio significa que se puede atravesar o hacer cualquier operación sobre los ficheros que contiene (siempre respetando los permisos de acceso al fichero en cuestión). El permiso de lectura sobre un directorio nos autoriza a listar su contenido, y
el permiso de escritura añadir ficheros dentro de él.
Para poder acceder de alguna manera a un fichero, es necesario que todos los directorios que
hay en el camino hasta ese fichero nos permitan hacerlo.
Cuando se trata de un fichero que contiene un script, para poder ejecutarlo no basta con tener
permiso de ejecución, sino que también es necesario tener permiso de lectura. Si por el contrario
es un fichero en formato ejecutable, con el permiso de ejecución es suficiente.
Cuando se crea un fichero, se hace con unos permisos por defecto (determinados por el valor de
una máscara de bits, que el usuario puede modificar). Si posteriormente se quieren modificar estos
permisos se puede utilizar el comando chmod. Este comando se puede utilizar de varias maneras
dos de las cuales aparecen en la figura 8, en la que se añade a fichero1 permiso de ejecución tanto
para el propietario del fichero como para los miembros de su grupo. La primera manera que se
angren% chmod ugo+x fichero1
angren% ls -l
-rwxr-xr-x 1 e3432065 est 1024 Sep 15 10:00 fichero1
angren% chmod 755 fichero1
angren% ls -l
-rwxr-xr-x 1 e3432065 est 1024 Sep 15 10:00 fichero1
Figura 8: Modificación de los permisos de acceso de un fichero
muestra indica que a los permisos del propietario (u), de su grupo (g) y del resto de usuarios (o)hay
que añadir (+) permiso de ejecución (x). Si en lugar de añadir se quisiera eliminar un permiso, se
Práctica 1: Uso del Shell
5
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
utilizaría el símbolo -. La segunda manera consiste en indicar, codificado en octal, como queremos
que queden los permisos asociados al fichero (755).
Otros comandos para la gestión de ficheros
También existen comandos que nos permiten comparar el contenido de dos ficheros (diff, cmp),
averiguar el directorio en el que se encuentra un determinado fichero (find), o el pathname de un
determinado comando (whereis o which), cambiar el propietario o el grupo de un fichero
(chown, chgrp), etc.
4. El C-shell: uso interactivo
El C-Shell es el intérprete de comandos que se usará en las prácticas de laboratorio. Muchas de las
características descritas a continuación están también presentes en los otros shells que vienen con
Unix, aunque a veces hay variaciones en la sintaxis o en los nombres de los comandos internos.
El C-shell utiliza dos ficheros de control, en los que el usuario puede dejar comandos para que
se configure el entorno de trabajo tal y como lo desea. Estos dos ficheros son los llamados .login
y .cshrc, y deben estar en el directorio base de la zona de trabajo del usuario (podéis ver como
ejemplo los que tenéis en vuestra cuenta de angren: more .login, more .cshrc).
Cuando el C-shell inicia su ejecución interpreta el fichero .cshrc. Si además, el inicio de ejecución coincide con el inicio de la sesión del usuario, el C-shell interpreta a continuación el contenido
del fichero .login.
4.1. El Entorno de trabajo
4.1.1. Variables
El C-shell tiene variables que le permiten caracterizar el entorno de trabajo. El usuario puede consultar qué variables hay definidas y el valor que tienen asociado mediante el comando set (figura
9).
angren% set
argv
autologout
cwd
history
home
noclobber
path
prompt
savehist
shell
status
system
term
user
()
600
/u2/est/e3432065/practicas
20
/u2/est/e3432065
(/usr/bin .)
angren.eupvg.upc.es !:
20
/usr/bin/csh
0
angren.eupvg.upc.es
vt100
e3432065
Figura 9: Ejemplo de variables del shell definidas
Para modificar el valor de una variable o para definirla se puede usar también el comando set,
Práctica 1: Uso del Shell
6
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
pero añadiendo el nombre de la variable y el nuevo valor que se le quiere dar.
angren% set history=10
angren% set
argv
()
autologout
600
cwd
/u2/est/e3432065/practicas
history
10
. . .
user
e3432065
Figura 10: Modificación de una variable del shell
No todas las variables tiene sentido que sean modificadas por el usuario. Por ejemplo, la variable cwd (current working directory) indica el directorio actual, y el shell se encarga de actualizarla
cada vez que el usuario cambia de directorio.
Las modificaciones de las variables sólo son válidas durante la ejecución del C-shell en el que
se hacen, y se pierden una vez que el shell finaliza la ejecución. Cuando se lance un nuevo shell
las variables vuelven a inicializarse con los valores por defecto. Si queremos que ciertas variables
siempre tomen por defecto los valores que nos interesan podemos incluir en el fichero .cshrc los
comandos que modifican los valores de esas variables. De esta manera cuando iniciemos una sesión, automáticamente se configurará nuestro entorno de trabajo tal y como lo queremos.
El significado de alguna de estas variables es:
• history: se utiliza para el mecanismo de historia, explicado más adelante.
• home: habitualmente contiene el directorio base del usuario en el sistema de ficheros.
Cuando introducimos el comando cd sin ningún argumento, hacemos que el directorio
actual pase a ser el indicado por esta variable.
• prompt: lo muestra el shell por pantalla para indicar al usuario que está preparado para
recibir comandos. Puede asignársele el valor de otra variable, como la que contiene el
username (user), o el directorio actual (cwd).
• status: contiene el valor de retorno del último comando que se ha ejecutado.
• path: contiene una lista de directorios, separados entre si por un espacio en blanco.
Cuando el usuario introduce el nombre de un programa que quiere lanzar, el shell lo
busca en los directorios que indica esta variable, de izquierda a derecha, y para de buscar
cuando encuentra un fichero con el nombre que el usuario ha introducido (ver sección
4.1.7. Ejecución de comandos). El usuario puede añadir a esta variable todos los
directorios que considere oportunos.
• term: esta variable indica el tipo de terminal desde el que se está trabajando.
• shell: contiene el login shell del usuario.
Además de las variables que usa el shell, existen otro tipo de variables que describen el entorno
de trabajo (variables de entorno) que el shell pasa como parámetros a los procesos que lanza. Un
usuario puede definir sus propias variables de entorno, para describir características que el shell no
contemple. El valor de estas variables se puede consultar con el comando printenv, y para asig-
Práctica 1: Uso del Shell
7
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
narles valores se utiliza el comando setenv.
angren% setenv MAIL /var/mail/e3432065
angren%
Figura 11: Definición de una variable de entorno
Para distinguir los dos tipos de variables, se suelen dar nombres con letras mayúsculas a las variables de entorno, mientras que las variables del shell suelen tener nombres con letras minúscula.
4.1.2. Patrones de nombres de archivo
Los metacaracteres son caracteres especiales, que el shell interpreta y substituye por el significado
que tienen asociado. Algunos de estos metacaracteres se utilizan para definir patrones de nombres.
Por ejemplo, un asterisco (*) significa “cualquier grupo de caracteres”; un interrogante (?) significa
“cualquier carácter” (uno sólo); y los corchetes ([]) pueden servir para especificar un rango de
caracteres.
angren% ls
f1 f2 f3 fichero1 fichero2 fichero3
angren% ls *1
f1 fichero1
angren% ls ?1
f1
angren% ls f[1-3]
f1 f2 f3
angren%
Figura 12: Ejemplo de patrones de nombres
Otro carácter con significado especial es la tilde (~), que seguida de un username se interpreta
como el home directory del usuario con ese username. Si no se pone username se substituye por
nuestro home directory (por ejemplo, el comando ls ~ listará el contenido de nuestro home directory).
4.1.3. Inhibición de los caracteres interpretados
Si se desea que el shell no interprete algún carácter, éste se puede preceder de la barra invertida (\)
o bien, si se trata de un grupo de caracteres, encerrarlos entre comillas dobles o simples (“) (').
En la figura 13 tenemos un ejemplo que muestra la necesidad de poder evitar la interpretación
de estos caracteres. En el ejemplo se pretende borrar un fichero al que hemos llamado temp?, en
el caso a, el shell interpreta que queremos borrar cualquier fichero cuyo nombre coincida con el
patrón (por ejemplo, intentaría borrar temp1, temp2, temp?, etc...). Si embargo, en el caso b, con
el uso de la \ le indicamos al shell que en esta situación el carácter ? debe ser tratado como cualquier otro carácter.
angren% rm -i temp?
temp1: ? (y/n) n
temp2: ? (y/n) n
temp?: ? (y/n) y
angren%
caso a
angren% rm -i temp\?
temp?: ? (y/n) y
angren%
caso b
Figura 13: Inhibición de caracteres interpretados
Práctica 1: Uso del Shell
8
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
4.1.4. History
El C-shell ofrece un mecanismo de historia de los últimos comandos que el usuario ha ejecutado.
Mediante este mecanismo el usuario puede recuperar estos comandos sin necesidad de volver a
teclearlos. La variable history del C-shell contiene la cantidad de comandos que debe recordar
(si no está definida, entonces el Cangrenangrenangren-shell no recuerda ningún comando).
Utilizando el comando history se obtiene la lista de comandos guardados en la historia. Cada
comando aparece precedido por un número que puede usarse para referirse a él. Los siguientes comandos permiten reejecutar alguno de los comandos guardados en la lista de history:
!!
!cadena
!#
^vieja^nueva
ejecuta el comando más reciente
ejecuta el comando más reciente que comience por cadena.
ejecuta el comando asociado al número #.
ejecuta el comando más reciente, pero substituyendo la aparición de la cadena vieja por
la cadena nueva
La figura 14 muestra un ejemplo del uso del history. En este ejemplo, pedimos que se vuelva a
ejecutar el último comando que empezaba por c, y el resultado será la compilación del fichero programa.c.
angren% history
. . .
19: cc -o programa programa.c
20: vi programa.c
angren% !c
cc -o programa programa.c
Figura 14: Ejemplo del uso del history
4.1.5. Alias
El mecanismo de alias permite que el usuario asocie durante una sesión sus propios nombres a los
comandos. Cuando la primera palabra que aparece en la línea de comandos se corresponde con un
alias, el C-shell la substituye por la definición que el usuario le haya asociado y ejecuta el comando
resultante.
Este mecanismo permite que un usuario utilice nombres que le resultan más cómodos o fáciles
de recordar, así como modificar el comportamiento por defecto de un determinado comando. Para
la definición de un alias podemos utilizar el comando alias, pasándole como argumento el nombre que le queremos dar y a continuación su definición. En la figura 15 vemos dos ejemplos de la
definición y uso de los alias. El primero crea un alias llamado isop, cuya definición consiste en
cambiar al directorio de isop. Con un alias de este tipo evitamos tener que recordar el directorio de
la asignatura, y además con este alias será necesario escribir menos cada vez que queramos movernos a ese directorio. El segundo ejemplo hace que cuando el usuario introduzca rm, el shell lo substituya por rm -i, haciendo que por defecto el intérprete le pida confirmación antes de borrar un
Práctica 1: Uso del Shell
9
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
fichero.
angren% pwd
/u2/est/e3432065
angren% alias isop cd /u2/practiques/isop
angren% isop
angren% pwd
/u2/practiques/isop
angren% alias rm ‘rm -i’
Figura 15: Definición de alias
Para saber qué alias hay definidos en una sesión, se puede introducir el comando alias, sin
ningún argumento. Para eliminar la definición de un alias, se puede utilizar el comando unalias,
seguido del alias que queremos eliminar.
La definición de un alias sólo tiene efecto durante la ejecución del shell en la que se hacen. Por
lo tanto, cuando el usuario sale de la sesión el alias se pierde, y será necesario volver a definirlo la
próxima vez que el usuario entre en el sistema. Si queremos que cada vez que entremos en el sistema se definan automáticamente los alias que nos interesan (sin preocuparnos de hacerlo explícitamente), podemos incluir los comandos de alias en el fichero .cshrc. De esta manera, cada vez que
se lance un C-shell, éste definirá los alias que le indiquemos.
4.1.6. Caracteres de control
En UNIX es posible programar el teclado para que realice ciertas funciones como detener la salida
por pantalla o abortar el comando actual. A continuación se explican algunas de estas funciones
junto con los caracteres que habitualmente las realizan.
función
tecla habitual
erase
DEL/ctrl-h
stop
ctrl-s
start
ctrl-q
intr
ctrl-c
eof
ctrl-d
Descripción
borra la tecla introducida anteriormente
detiene la salida de datos por el terminal
reanuda la salida de datos por el terminal
aborta el comando que se ejecuta en ese instante
señala el fin de fichero
El comando stty se utiliza para configurar las características de la entrada y salida de datos por
el terminal desde el que se trabaja. Entre otras cosas, permite consultar o cambiar el carácter o grupo de caracteres que realiza una función. Por ejemplo, para hacer que la tecla de borrado pase a ser
la tecla DEL, habría que introducir: stty erase DEL. Otras características que permite modificar
son por ejemplo el número de columnas o filas que forman la pantalla, desactivar el echo, etc. Para
consultar la configuración actual del terminal se puede introducir stty sin ningún argumento.
4.1.7. Ejecución de comandos
Cuando el usuario introduce un comando, el shell tiene que localizar en qué lugar del sistema de
ficheros se encuentra ese comando (es decir, qué fichero ejecutable está intentando lanzar). Si el
nombre que ha recibido contiene el carácter /, el shell asume que el usuario ha introducido el directorio donde se encuentra el comando, y que tiene que buscarlo en ese punto. Si no lo encontrara
allí daría un mensaje de error. Si por el contrario, el usuario sólo introduce el nombre del comando,
el shell comprobará primero si hay definido algún alias con ese nombre. De ser así, substituirá el
alias por su definición, y ejecutará esta definición. Si no se trata de un alias, entonces el shell buscará el comando en los directorios indicados por la variable path, de izquierda a derecha. La búsPráctica 1: Uso del Shell
10
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
queda finaliza cuando encuentre un comando con el nombre que busca. Es decir, si existen varios
ficheros ejecutables con el mismo nombre, el shell ejecutará el que se encuentre en el directorio
que aparece más a la izquierda en la variable path. Si no encuentra un ejecutable con ese nombre
en ninguno de los directorios del path, entonces el shell dará un mensaje de error.
Si el comando introducido es externo, el shell crea un proceso separado que ejecutará ese comando. Si el comando que se intenta lanzar es un script, el shell creará otro shell que será el encargado de interpretar el script, mientras que el shell inicial se quedará a la espera de que finalice la
ejecución del script.
Una vez lanzado el comando, puede ser que el shell se quede a la espera de que acabe su ejecución antes de aceptar una nueva petición del usuario. Si esto es así, se dice que es una ejecución en
primer plano (foreground).
Si un comando no necesita intercambiar datos con el usuario, y además se espera que va a tardar
bastante tiempo en ejecutarse, el usuario puede querer aprovechar el tiempo y ejecutar otros comandos al mismo tiempo (esto es posible porque Unix es un sistema multiprogramado: permite tener varios programas ejecutándose al mismo tiempo). Para ello, se puede lanzar el comando en
segundo plano (background), usando el carácter & al final de la línea. Cuando se lanza un comando
en background, el shell crea el proceso que lo va a ejecutar, informa al usuario del identificador de
proceso que el sistema operativo le ha asignado (pid), a continuación muestra el prompt y queda a
la espera de la siguiente petición del usuario. Cuando el proceso en background finalice, el shell
informará al usuario mostrando su pid y un mensaje que indique la finalización.
El comando fg, se utiliza para hacer que un proceso que se está ejecutando en background pase
a ejecutarse en foreground (es decir, el intérprete de comandos quedará a la espera de que el comando finalice la ejecución). Si por el contrario, queremos que un proceso lanzado en foreground
pase a estar en background debemos en primer lugar parar momentáneamente su ejecución (suspender la ejecución mediante ctrl-z), y a continuación ejecutar el comando bg.
Si un comando lanzado en background necesita mostrar por el terminal algún mensaje, es necesario que el terminal esté configurado para permitirlo (la opción tostop tiene que estar desactivada:
stty -tostop). Si no es así, el shell parará la ejecución del proceso cuando intente escribir en
el terminal, y no podrá continuar hasta que el usuario ordene su ejecución en foreground.
Además de estos dos comandos existen otros dos comandos relacionados con la gestión de procesos que conviene conocer. El primero es ps, que nos permite saber todos los procesos que en ese
instante estamos ejecutando. El segundo comando es kill, que utilizado con la opción -9 nos
permite abortar la ejecución de todos los procesos cuyo identificador le pasemos como argumento.
Un usuario sólo puede abortar los procesos que él haya lanzado.
4.2. Usar el resultado de un comando como argumento
Usando las comillas invertidas (`) podemos hacer que el resultado de la ejecución de un comando
pase a ser un argumento de otro comando. Por ejemplo, el comando cat muestra por pantalla el
contenido de los ficheros que se le pasan como argumentos. Si queremos mostrar por pantalla el
contenido de todos los ficheros del directorio actual, cuyo nombre empieza por t, podríamos introducir: cat ‘ls t*‘. Ante esta petición, el shell ejecutará el comando ls t*. El resultado de esta
ejecución será el nombre de todos los ficheros del directorio actual cuya primera letra sea t, y,
seguidamente el shell ejecutará el comando cat pasándole como argumentos todos estos nombres.
Práctica 1: Uso del Shell
11
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
4.3. Redireccionamiento de entrada/salida
En Unix, todos los procesos tienen asociado un dispositivo que actúa como entrada de datos
estándar, otro como salida estándar y un tercero que hace de salida de errores estándar. Si no se
indica lo contrario, el shell hace que el terminal en el que se trabaja sea tanto la entrada como la
salida de datos estándar, y por tanto siempre que el proceso intente leer de su entrada estándar lo
hará del terminal (esto es, del teclado).
Es posible modificar este comportamiento sin necesidad de reescribir el código del programa.
El shell permite asociar un fichero a la entrada estándar del proceso, haciendo que pase a leer los
datos del fichero asociado en lugar de hacerlo del teclado. De la misma manera se puede cambiar
la asociación de la salida y del error estándar. Esto es lo que se llama redirección de entrada/salida.
Para redireccionar la entrada estándar del proceso se puede utilizar el símbolo <, seguido del
fichero que queremos asociar a la entrada de datos. Para redireccionar la salida se utiliza el símbolo
> y para redireccionar la salida de errores se utiliza >&. En el caso de la redirección de la salida,
hay que decir que si el fichero que se está usando ya existía se perderá su contenido. Si queremos
conservarlo y añadir al final los datos del proceso podemos utilizar el símbolo >>.
Pipe
Utilizando el mecanismo de redirección de la entrada y la salida estándar, el shell permite conectar
dos procesos, haciendo que la salida estándar de uno de ellos pase a ser la entrada estándar del otro.
Esto se hace utilizando una pipe (tubería), cuyo símbolo en el shell es |. La manera de utilizarlo es
situando la pipe como separador entre los dos comandos que se quieren conectar. El shell creará
dos procesos, uno para cada comando, que se ejecutarán al mismo tiempo, y hará que el proceso
que ejecuta el comando situado a la izquierda de la pipe utilice como salida de datos estándar la
entrada de datos del proceso que ejecuta el comando situado a la derecha. Esta es una manera sencilla que permite que haya comunicación de datos entre dos procesos. Todos los comandos conectados de esta manera en una sola línea de comandos se llaman pipeline.
El siguiente ejemplo permite saber cuantos ficheros hay en el directorio actual puesto que ls
escribe en su salida estándar una línea por fichero y wc cuenta las líneas que encuentra en su entrada estándar.
angren% ls -a | wc
Figura 16: Ejemplo de pipeline
Filtros
Se llaman filtros a los comandos que leen datos de su entrada estándar, realizan sobre ellos un tratamiento, y muestran el resultado de ese tratamiento sobre su salida estándar. El comando dejará
de aceptar datos de entrada cuando lea el carácter de final de fichero. Normalmente pueden aceptar
un argumento que actúe como su entrada de datos, en lugar de su entrada estándar. En este caso, el
comando no se verá afectado si se redirecciona su entrada estándar (porque no la utiliza).
A continuación se describen brevemente algunos filtros muy comunes (para más información
sobre alguno de ellos podéis consultar el man):
more
cat
head [-n count]
tail [-n count]
Práctica 1: Uso del Shell
Muestra página a página por su salida estándar lo que lee por su entrada estándar.
Muestra por salida estándar lo que recibe por su entrada estándar.
Muestra por salida estándar las primeras líneas que recibe por su entrada estándar. Por
defecto intenta mostrar 10 líneas.
Muestra por salida estándar las últimas líneas que ha recibido por entrada estándar.
Por defecto son 10 líneas.
12
ISOP - Documentación para las Prácticas de Laboratorio
sort
wc
grep patrón
cut campos
tee
EUPVG - UPC
Ordena los datos que le llegan por la entrada estándar y los escribe por la salida
estándar. Por defecto ordena alfabéticamente en orden ascendente pero también puede
ordenar en orden descendente, numérico y por alguna columna que no sea la primera.
Cuenta las líneas, palabras y caracteres de la entrada estándar.
Busca el patrón en los datos de entrada y muestra por salida estándar la línea que lo
contiene.
Considera cada línea que recibe por su entrada estándar dividida en campos, y selecciona el campo que se le indica. Por defecto el carácter que separa campos es el tabulador, pero se le puede indicar que sea otro mediante la opción -d.
envía su entrada estándar hacia su salida estándar pero además escribe la entrada
estándar en el fichero que se le indique.
5. El C-shell: programación de shell-scripts
El shell no sólo actúa como intérprete de comandos interactivo sino que además se puede utilizar
como lenguaje de programación, en el que cada sentencia ejecuta un comando.
Los programas escritos para el shell se llaman scripts. Para ejecutar un script es necesario tener
permiso tanto para leer como para ejecutar el fichero que los contiene. Cuando el usuario ejecuta
un script, el shell crea un subshell que será el encargado de interpretar los comandos del script. Una
vez finalice el script, el subshell también acabará la ejecución. Es importante tener esto en cuenta
porque las modificaciones que haga el script sobre las variables del shell o del entorno desaparecerán una vez finalizado el script.
La primera línea de un script suele utilizarse para indicar el shell que queremos utilizar para interpretarlo. Esta línea tiene que empezar con los caracteres #!, y a continuación debe contener el
pathname absoluto del shell que queremos utilizar. Si la primera línea del fichero no tiene este formato, se utilizará el Bourne Shell para interpretar el script.
El carácter # a principio de línea también se utilizar para marcar toda la línea como un comentario.
5.1. Variables y parámetros
En un script se pueden usar tanto las variables del shell, como cualquier otra variable que el usuario
necesite definir. Estas variables no necesitan una sentencia de declaración explícita, sino que se
declaran en el momento de asignarles el primer valor.
Los valores de las variables son cadenas de caracteres, aunque es posible asignar el resultado de
una operación numérica mediante el operador @ (@ nombre_var=expresión, nótese el espacio
en blanco entre el operador @ y el nombre de la variable). Para asignar a una variable cualquier
cadena de caracteres se puede utilizar el comando set, tal y como se ha explicado para las variables del shell.
Para obtener el valor de una variable, es necesario preceder el nombre de la variable por el carácter $.
Un script puede recibir parámetros en la variable del entorno argv. Esta variable es equivalente
a un array que almacena cada uno de los parámetros que se le pasan (el índice del primer elemento
es 1). Una manera de referenciar el valor de los parámetros dentro del script es utilizando el carácter $ seguido del índice que le corresponde en el array de parámetros argv (esto es equivalente a
$argv[indice]). Para saber el número de elementos que contiene una variable de este tipo se
puede utilizar la expresión $#nombre_var.
El comando shift se utiliza para desplazar los parámetros del script una posición a la izquierda
Práctica 1: Uso del Shell
13
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
dentro de la variable argv (el parámetro que en ese momento ocupaba la primera posición se pierde).
5.2. Expresiones
Los operadores disponibles para construir expresiones son prácticamente iguales a los del lenguaje
C. Los operadores de igualdad (==, !=) consideran que los operandos son cadenas de caracteres.
Unos operadores que en C no existen son =~ y !~, equivalentes a == y != pero tomando el operando del lado derecho como un patrón de caracteres. El resto de operadores actúan sobre números
(+, -, *, /, %, <, >,...). Los operadores tienen que estar rodeados de espacios en blanco.
También soporta unos operadores sobre ficheros que permiten saber, por ejemplo, si existe un
fichero con ese nombre ( -e nombre_fichero ), si se tiene un determinado permiso de acceso
(-r nombre_fichero, -w nombre_fichero, -x nombre_fichero), etc.
5.3. Estructuras de control
A continuación se describen brevemente algunas estructuras de control que ofrece el C-shell: las
repetitivas y las condicionales.
Repetitivas
El C-shell ofrece tres estructuras de control que permiten la repetición de varios comandos.
La más sencilla es repeat, que permite ejecutar tantas veces como se le indique un comando
simple (no puede ser un pipeline, ni un alias, ni una lista de comandos). Esta estructura de control
y el comando tiene que aparecer en una sola línea.
También tenemos un bucle similar al de cualquier lenguaje de alto nivel, en el que se repiten los
comandos mientras la expresión no evalúe a 0. Las líneas que marcan el inicio y el fin del bucle no
pueden contener otros comandos.
Por último la estructura de control foreach ejecuta tantas iteraciones como valores haya en la
lista de palabras (wordlist), y en cada iteración asigna uno de esos valores a la variable name.
Igual que en el caso anterior las líneas de inicio y fin del bucle no pueden contener otros comandos.
repeat count command
while (expression)
. . .
end
foreach name (wordlist)
. . .
end
Figura 17: Estructuras de control repetitivas
Condicionales
Las estructuras condicionales de las que disponemos son unas equivalentes al if y al switch del
lenguaje C.
La primera que vamos a describir es un condicional sencillo, en el que si la expresión evalúa a
cierto se ejecuta un comando simple. Toda la sentencia tiene que ocupar una sola línea.
Además de este condicional sencillo, también podemos utilizar pares de else-if, como se ve
en la figura 18, marcando el final de la estructura con la palabra endif (uno solo para todas las
condiciones anidadas). Las palabras else y endif tienen que aparecer al principio de línea, y la
sentencia del if tiene que estar sola en la línea (o precedida por un else).
También disponemos de un switch, en el que para decidir la rama que se ejecuta se hace pat-
Práctica 1: Uso del Shell
14
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
tern matching entre el string del switch y cada uno de los casos contemplados.
if (expression) command
if (expression1) then
. . .
else if (expression2) then
. . .
else
. . .
endif
switch (string)
case str1:
. . .
breaksw
. . .
default:
. . .
endsw
Figura 18: Estructuras de control condicionales
5.4. Ejemplo: which_name
En la figura 19 y en la figura 20 podemos ver dos shell script que implementan el mismo trabajo.
Los dos aceptan como parámetros una lista de usernames y nos devuelven para cada usuario el
comentario que tiene asociado en el fichero de passwords (típicamente, su nombre).
La diferencia básica entre los dos scripts es la estructura de control que hemos utilizado. En la
figura 19 hemos usado un bucle while, cuya condición de finalización es que el número de iteraciones sea igual al número de parámetros que le hemos pasado. En la figura 20 utilizamos un bucle
foreach, lo que nos ha simplificado el control del bucle. _
#!/bin/csh
# queremos utilizar el C-shell para ejecutar el script
@ I = 0
@ NUMARG = $#argv
# la variable I hara de contador en el bucle y NUMARG sera el limite del bucle
while ($I < $NUMARG)
grep $1 /etc/passwd | cut -d: -f5
@ I=$I + 1
shift
# el comando shift desplaza una posicion a la izquierda el contenido de argv,
# asi que el parametro que ocupaba la posicion 2, pasa a estar en la posicion 1: $1
end
Figura 19: which_name: bucle while
En ambos casos, para cada username utilizamos el comando grep para buscar ese username en
el fichero de passwords. Si existe, este comando mostrará por su salida estándar toda la línea asociada al username, pero a nosotros nos interesa sólo la parte del comentario. Para seleccionar únicamente esa parte utilizamos el comando cut, que recibe por su entrada estándar la línea que le
pasa el comando grep (gracias a la pipe). Al comando cut le decimos que el carácter separador
de campos es el : (-d:), y que nos interesa seleccionar el campo número cinco (-f5), que es el
que se corresponde con el comentario asociado al username.
#!/usr/bin/csh
foreach NAME ($argv)
grep $NAME /etc/passwd | cut -d: -f5
end
Figura 20: which_name: bucle foreach
Práctica 1: Uso del Shell
15
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
6. Manuales
El comando man permite consultar el manual del sistema de forma interactiva. Mediante este
comando podemos consultar la ayuda a cualquier otra utilidad disponible en el sistema (figura 21).
angren% man nombre_comando
Figura 21: Ayuda sobre
El manual está organizado en varias secciones, identificadas con un número. Típicamente los
sistemas incluyen las secciones que se muestran en la figura 22, numeradas de la misma manera
(el resto de secciones y de numeración varía entre sistemas).
(1) Comandos y programas de aplicación
(2) Llamadas al sistema
(3) Subrutinas y funciones de librería
(4) Formatos de ficheros
(5) Miscelánea
..............
Figura 22: Secciones del manual de Unix
La búsqueda en el manual se inicia en las secciones de número más bajo y finaliza en el momento de encontrar información sobre la palabra introducida. Si se quiere información de una determinada sección hay que introducir el número de sección antes del nombre del comando. Es
posible que una misma palabra se encuentre en varias secciones (porque pueda tratarse tanto de un
comando como una llamada a sistema, por ejemplo). Por ejemplo, hay un comando del shell llamado read, y por lo tanto tiene una página en la sección 1 del manual, y también existe una llamada a sistema con el mismo nombre, que por lo tanto tiene una página en la sección 2 del manual.
Si introducimos man read, obtendremos ayuda sobre el comando que se llama así. Si lo que queremos es obtener ayuda sobre la llamada a sistema deberíamos introducir man 2 read.
El manual también nos puede ayudar a encontrar un comando capaz de realizar la operación que
nos interesa (figura 23). Para ello podemos utilizar la opción -k seguida de una palabra clave, y el
angren% man -k palabras_clave
Figura 23: Comandos relacionados con palabra_clave
resultado de la operación será una lista de todos aquellos comandos en cuya descripción aparezca
la palabra clave. Por ejemplo, si queremos saber los editores de texto que hay en el sistema, podríamos introducir la consulta que se muestra en la figura 24.
angren% man -k “text editor”
ed, red(1)
- line-oriented text editor
ex, edit(1)
- extended line-oriented text editor
sed(1)
- stream text editor
vi, view, vedit(1)
- screen-oriented (visual) text editor
Figura 24: Buscando comandos relacionados con las palabras text editor
Práctica 1: Uso del Shell
16
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
7. El editor vi
El editor vi viene con todas las distribuciones UNIX, y por eso es conveniente estar familiarizado
con su uso. Es un editor sencillo aunque no tiene un interfaz muy amigable.
Este editor tiene dos posibles estados: modo inserción y modo comando. Si el estado activo es
el de inserción, entonces se puede introducir el texto que se quiere editar. Si por el contrario se encuentra en modo comando, las teclas introducidas se interpretan como operaciones de control.
Cuando se entra en el editor el modo inicial es comando, y para pasar a modo inserción existen
varios comandos, por ejemplo el comando i. Si se esta en modo inserción y se desea pasar de nuevo a modo comando basta con pulsar la tecla ESC (en los vt100 ctrl-3).
Si se introduce el comando :set showmode, aparecerá siempre en pantalla el estado en el que
se encuentra el editor (para desactivar esta opción el comando es :set noshowmode).
A continuación se describen algunos comandos básicos:
i
I
a
A
o
O
x
dw
cw
C
dd
d#d
yy
y#y
p
P
u
G
ctrl-f
ctrl-b
ctrl-g
Pasa a modo inserción. Los caracteres que se introduzcan aparecerán antes de la posición actual del
cursor
Pasa a modo inserción y sitúa el cursor al inicio de la línea en la que se encuentra
Pasa a modo inserción y sitúa el cursor en la siguiente posición a la que tiene en ese momento
Pasa a modo inserción situando el cursor al final de la línea actual
Pasa a modo inserción, abre una nueva línea debajo de la actual, y sitúa el cursor al inicio de esta
nueva línea
Pasa a modo inserción, abre una nueva línea encima de la actual, y sitúa el cursor al principio de la
nueva línea
Borra el carácter que se encuentra debajo del cursor
Borra la palabra sobre la que está el cursor
Reemplaza la palabra actual por lo que se introduzca hasta que se pase a modo comando
Reemplaza todas las palabras desde la posición actual hasta el final de la línea por lo que se introduzca hasta pasar a modo comando
Borra la línea en la que se encuentra el cursor (y la guarda en el buffer intermedio)
Borra # líneas a partir de la línea actual, incluida ésta (y las guarda en el buffer intermedio)
Copia en un buffer intermedio el contenido de la línea actual
Copia en un buffer intermedio el contenido de # líneas a partir de la actual (incluída ésta)
Pega debajo de la línea actual el contenido del buffer intermedio
Pega encima de la línea actual el contenido del buffer intermedio
Deshace los efectos de la última acción
Mueve el cursor al final del fichero
Mueve el cursor a la siguiente página
Mueve el cursor a la página anterior
Muestra el nombre del fichero, el número de línea actual, y el número de líneas del fichero
El comando :set number permite ver el numero de cada línea (para desactivar esta opción se
utiliza :set nonumber). Para ir a una línea determinada basta con introducir el comando :i, donde i es el número de línea deseado, y para ir a la última línea el comando :$.
El comando para grabar el contenido del fichero es :w. Para salir del editor grabando las últimas
modificaciones :wq o :x. Si se quiere salir sin conservar los últimos cambios :q!.
Un usuario puede guardar la configuración del editor que le interesa utilizar en un fichero de
Práctica 1: Uso del Shell
17
ISOP - Documentación para las Prácticas de Laboratorio
EUPVG - UPC
nombre .exrc en su home directory, en el que puede registrar los comandos tipo set que le interese.
angren% vi .exrc
set showmode
set number
.....
Figura 25: Ejemplo de fichero de configuración del vi
Práctica 1: Uso del Shell
18
Descargar