Practicas de Sistemas Telemáticos Guión 2 1 0. OPERANDO CON ARCHIVOS (cont.) Como comentamos en el guión previo, los ficheros tienen asociados una serie de permisos en función de los cuales, los usuarios podrán leerlos, escribir sobre ellos y ejecutarlos (en el caso de un directorio, una ejecución sería poder acceder a ese directorio). Para establecer esos permisos debemos usar la orden chmod (change mode). La sintaxis es la siguiente (ver pag. man): chmod [ugoa] {+ | - | =} [rwxlsStTugo] lista_archivos donde la primera opción se refiere a los usuarios sobre los que vamos a hacer la modificación de permisos: u = propietario del fichero g = grupo o = el resto a = todos la segunda opción se refiere a la operación que vamos a realizar: + = añadir - = eliminar = = asignar La tercera opción se refiere al permiso que vamos a dat, utilizaremos con más frecuencia r,w,x que se refieren a lectura, escritura y ejecución respectivamente. Si hemos creado un archivo y deseamos ejecutarlo, al no tener por defecto el permiso de escritura, deberemos asignárselo. 1. ACCEDIENDO A LOS DISPOSITIVOS Y OTROS SISTEMAS DE FICHEROS Antes de poder acceder a un sistema de ficheros, hemos de montarlo previamente. En el caso de la partición nativa de Linux, este paso no es necesario. El proceso de montaje consiste en asignarle un directorio a nuestro dispositivo, especificando el sistema de 2 ficheros que este posee mediante la instrucción “mount”. Dentro de los posibles sistemas de ficheros que nos podemos encontrar tenemos: SISTEMA DE TIPO DESCRIPCIÖN FICHEROS Sistema Extendido nº2 ext2 Sistema normal de Linux Sistema Extendido nº3 ext3 Sistema normal de Linux, con journaling ISO 9660/Joliet Iso9660 Sistema habitual de los CD y su extensión para aceptar código Unicode en los nombres de archivos. Sistema de archivos de red NFS Permite el acceso remoto a los archivos mediante una red UMSDOS Umsdos Permite la instalación de Linux en una partición de MSDOS DOS-FAT Msdos Permite acceder a los archivos de MSDOS VFAT Vfat Acceso a los archivos pertenecientes a Windows 95/98 NT Ntfs Acceso a los archivos de Windows NT HPFS Hpfs Sistema de archivos de OS/2 SMB Smbfs Acceso a ficheros desde grupos de trabajo com Windows o desde servidores Windows NT. 3 1.1 Fundamentos teóricos La instrucción mount permite a los usuarios acceder a los datos que se encuentran en un dispositivo como si de un sistema de ficheros se tratara y no de una secuencia de bloques de disco. La sintaxis para la instrucción mount es: Mount directorio_dispositivo, directorio_montaje, opciones donde directorio_dispositivo es el nombre del directorio correspondiente a el dispositivo, directorio_montaje es el directorio donde el sistema de ficheros contenido en el dispositivo será montado y mediante el cual accederemos a los datos y opciones indica el tipo de sistema de ficheros a ser montado, si queremos que sea de lectura escritura o solo lectura, etc. (para más detalles ver man mount). El directorio_montaje es también conocido por punto de montaje. A continuación se muestra una figura donde se ve como son conectados los dos sistemas de ficheros: mount(“/dev/disk2”,”/particion1”,0) / grupo1 datos Particion1 person al / G1 Sistema de ficheros contenido en /dev/disk2 datos G2 person al 4 El kernel mantiene una tabla interna con una entrada para cada sistema de archivos que hayamos montado. Al directorio raiz del sistema de archivos del dispositivo se le asigna un I-nodo que nos va a permitir movernos por todo el sistema de ficheros. Cuando hayamos terminado de utilizar los datos del sistema de ficheros, deberemos “desmontarlo”, para ello, utilizaremos la instrucción umount, viendo el efecto sobre el ejemplo anterior, obtendríamos: Umount(“/particion1”) / Particion1 grupo1 datos person al El SO se encargará de comprobar que ningún fichero del sistema de ficheros que vamos a desmontar está en uso, para ello recorre la tabla de i-nodos interna y mira si el campo de dispositivo coincide con el dispositivo que vamos a desmontar. Con este concepto podemos imaginar como podría constituirse un sistema de ficheros distribuido, en el que los archivos esten distribuidos en varias computadoras. Podríamos montar un nodo cualquiera del sistema remoto de modo que accederemos a estos ficheros de manera transparente (al igual que accedemos a los dispositivos). 1.2 Ejemplos prácticos Para poder montar ficheros deberemos haber accedido al sistema como el usuario root. Los usuarios normales podrán utilizar el comando mount pero con las restricción de acceder únicamente a los dispositivos especificados en “/etc/fstab”. 5 Como ejemplo vamos a montar un disco flexible que ha sido creado en formato MSDOS, para ello deberemos especificar explícitamente el tipo de sistema de ficheros que vamos a montar: mount –t MSDOS /dev/fd0 /mnt Si la instrucción tiene éxito, accediendo al directorio /mnt normalmente, estaremos accediendo a los datos contenidos en el disco flexible. Para montar un CD-ROM deberemos utilizar la instrucción: mount –t iso9669 /dev/cdrom /mnt debido a que no hemos especificado explícitamente el montaje en modo solo lectura, nos aparecerá un mensaje indicando que se ha montado en solo lectura. Antes de sacar el disco flexible o el CD o cualquier dispositivo montado, hemos de desmontarlo antes, incluso aunque a continuación vayamos a montar otro nuevo. Para ello podemos desmontar el directorio destino donde se montó el fichero o desmontar el directorio del dispositivo montado: umount /dev/fd0 o bien umount /mnt Cuando montamos un dispositivo para lectura/escritura, las modificaciones, por defecto, no se actualizan directamente sobre el dispositivo, sino que se almacenan en un buffer para que cuando haya un número significativo de ellas, se acceda al dispositivo y se realicen varias seguidas, optimizando así el acceso a disco. Podemos especificar que las modificaciones se hagan en “tiempo real” mediante la opción sync. El directorio del dispositivo para montar las unidades de memoria flash por USB es /dev/sd1. 6 1.3 Las mtools Las mtools son unas ordenes desarrolladas para poder acceder a discos flexibles con formato MSDOS sin tener que montarlos. Prácticamente vienen instaladas en todas las instalaciones, especialmente si los usuarios normales no tienen privilegios para montar ningún dispositivo. Los comandos básicos para manipular los ficheros en MSDOS son los siguientes: dir -> lista el contenido de un directorio (equivale a ls) cd -> accede a un directorio copy .> copia dicheros (equivale a cp) del -> borra ficheros (equivale a rm) move -> mueve ficheros (equivale a mv) rd -> borra directorios md -> Crea directorios Para suplirlos las siguientes ordenes realizan las funciones equivalentes sin tener que montar la unidad de disco: Comando Descripción mdir Muestra el contenido del dispositivo dir. mcopy Copia archivos copy. mdel Borra archivos del. mformat Formatea la unidad format. mcd Cambia de directorio cd. mmd Crea un directorio md. mrd Borra un directorio rd. 7 Tras cada orden, deberemos de escribir la unidad y los argumentos. La unidad de disco se denomina “a:” al igual que en MSDOS. 2. ALIAS (CSH y TCSH) El mecanismo de alias nos va a permitir personalizar las ordenes que utilicemos en el shell pudiendo asignar el nombre que nos parezca más conveniente a una orden incluyendo sus parámetros. Cuando definimos un alias estamos definiendo una cadena que será sustituida a la hora de ejecutar un comando cuando el shell lo lea de la línea de comandos. Para listar los alias que tenemos definidos debemos usar la orden: alias Para crear un alias, la sintaxis es la siguiente: alias nombre_alias definición_orden Veamos unos cuantos ejemplos: Renombrando una orden: alias rename mv Redefiniendo una orden: alias ls ‘ls –l’ Creando una nueva orden: alias hp ‘history|more’ Cada shell tiene un archivo de configuración que se carga cuando se ejecuta, en el caso del csh, el fichero es .cshrc y para el bash tenemos el .bashrc .Deberemos incluir la definición de nuestros alias en esos ficheros de modo que cuando habramos un shell y un subshell, esos alias permanezcan. Deberemos incluir las definiciones que tengan varias palabras entre comillas simples. Además, cuando creemos un alias, no podremos referenciar a ese mismo alias aunque sí podremos referenciar a otros alias. 8 2.1 Incluyendo argumentos en los alias Ahora veremos como podemos pasar parámetros desde la línea de ordenes cuando usamos un alias, a las ordenes que están contenidas en ese alias. Para poder realizar esta tarea, deberemos de hacer uso del siguiente conjunto de metacaracteres: Metacaracter !^ Función Inserta el primer argumento de la línea de órdenes !* Inserta todos los argumentos de la línea de órdenes !x-y Inserta un rango de palabras; desde la x a la y Por ejemplo: alias cd ‘cd \!^ ; pwd’ 2.2 Deshaciendo alias Cuando un alias ya no nos sea de interés, podremos deshacerlo con la orden unalias o bien borrarlo del fichero .cshrc de nuestro directorio “home” o de /etc/cshrc. 3. VARIABLES (cshell) 3.1 Variables de entorno (globales) y variables locales El shell, al ser un lenguaje de programación, necesita poder utilizar variables, siendo estas de dos tipos: locales y de entorno (también conocidas como globales). Las dos variables pueden almacenar valores de todo tipo, la única diferencia es el ámbito en el que son visibles. 9 Cuando se crea un nuevo proceso para procesar una nueva orden, el proceso hijo, hereda algunos valores de su predecesor, estos valores son transmitidos mediante las variables globales. Las variables locales se utilizan a nivel local de proceso, sin ser vistas ni utilizadas por otros procesos y su contenido se pierde cuando salimos del shell en el que se definieron. Aunque hay algunas excepciones en las que al asignar una variable local, se modifica su correspondiente variable global. Como convención, el nombre de las variables globales se escribe en mayuscula y el de las locales en minuscula. En UNIX, el signo de dólar $ es el que identifica que una palabra es el nombre de una variable, así que en este guión mantendremos estas dos convenciones. 3.1 Asignando variables al shell Variables locales La orden para mostrar los valores de las variables locales es set. Con esta orden, también podremos asignar una variable al shell: set varprueba = prueba123 set matriz1 = (prueba 1 2 3) set var_vacia set matriz1[3] = dos Antes de que se le asigne a la variable su valor, este es expandido en ordenes y en nombres de archivos, es decir, podemos asignar a una variable el resultado de la ejecución de una orden englobando esta entre acentos graves (` orden `). Variables globales Para ver el contenido de todas las variables globales, utilizaremos la instrucción setenv. Esta instrucción es la equivalente a la anterior, aunque con algunas restricciones. Para 10 las varias globales no podremos tener variables multipalabra. La sintaxis con respecto a set también es distinta ya que no se introduce el signo = entre el nombre de la variable y el valor que se le va a asignar, en su lugar, se deja un espacio en blanco. setenv MYVAR 500 setenv DISPLAY username:0.0 setenv CADENA “Esto es una cadena” 3.2 Variable empotradas o predefinidas Existen unas variables especiales que su valor les es asignado al arrancar el shell, estas variables son conocidas como variables empotradas. La definición del valor que tomarán estas variables está contenida en el fichero .cshrc y puede ser modificado. A continuación, comentaremos algunas de las más comunes. 3.2.1 La lista de argumentos $argv Es una variable cuyo valor es multipalabra y en ella se contienen todos los parámetros de la orden que estamos ejecutando, es decir, cada palabra tecleada en la línea de comandos se corresponderá con una entrada en el valor de esta variable. 3.2.2 El cronómetro de salida $autologout Para proteger el sistema de accesos indebidos, podemos establecer una variable que establecerá el tiempo limite que la consola puede estar inactiva, una vez superado este tiempo, se bloquea la sesión automáticamente. El valor se asigna en minutos. 3.2.3 La pila de directorios $cdpath Cuando estamos navegando por la estructura de directorios, si intentamos cambiar a un directorio solo especificando el nombre, sin la ruta completa, si el directorio no se encuentra en el directorio actual, se recorreran los directorios contenidos en esta 11 variable y si en alguno de ellos hay un directorio que coincida con el que estamos intentando acceder, accederemos a ese. 3.2.4 Indentificadores de procesos de fondo $child Cuando una shell lanza un proceso, este es asignado un PID (process Identification Number) como ya vimos cuando lanzamos un proceso en segundo plano. Cuando el proceso finaliza, esta variable pierde su valor. 3.2.5 El directorio de trabajo acutal $cwd La variable $cwd (Current Working Directory) contiene en todo momento el camino completo del directorio en el que estamos situados, dependiendo de la shell, la variable global $PWD es actualizada cada vez que esta variable local se modifica. Es equivalente a ejecutar la instrucción pwd como ya vimos, la diferencia es que es menos costoso ver el contenido de una variable que ejecutar una orden. 3.2.6 Sufijos de terminación nombres $fignore Hay una forma de autocompletar la palabra que estamos escribiendo, pulsando la tecla de tabulación. Cuando pulsamos esta tecla, la shell busca una equivalencia en todos los directorios contenidos en $path. Si queremos excluir que se nos muestren archivos con determinadas extensiones, deberemos incluirlas en esta variable. 3.2.7 El tamaño de la historia $history Podemos establecer el número de ordenes a almacenar en la historia de ordenes asignandole ese valor a esta variable. 3.2.8 El directorio home $home Como ya comentamos anteriormente, cada usuario tiene un directorio home al cual accede cuando inicia una sesión, en esta variable se almacena la ruta a este directorio, 12 permitiendonos hacer referencias a archivos contenidos en el mismo sin tener que escribir todo el path. 3.2.9 La lista de búsqueda de directorios $path Cuando ejecutamos una orden, en primer lugar se buscara el correspondiente fichero en el directorio actual, en caso de no existir ningún comando con ese nombre, empezará a recorrer los directorios contenidos en esta variable hasta que encuentre uno igual y lo ejecutará. Esta variable toma su valor de la variable global $PATH y cuando la variable local se cambia, la global es actualizada, de este modo, se puede mantener un mismo path entre procesos hijos y padre. Los archivos ejecutables en esos directorios se encuentran localizados mediante una tabla hash para acelerar la busqueda, cuando añadamos un directorio a $path deberemos ejecutar la orden rehash para que la tabla hash sea actualizada. 3.2.10 La cadena del indicador del shell $prompt Esta variable nos va a permitir modificar la apariencia del indicador de ordenes en un shell interactivo. 3.2.11 El tamaño de la historia salvada $savehist Como hemos visto, se van almacenando los comandos que vamos ejecutando durante una sesión. Si queremos que esos comandos permanezcan en la historia cuando terminemos una sesión de modo que cuando iniciemos otra estén todavía allí, deberemos asignarle un valor a esta variable. 3.2.12 El estado de retorno de una orden $status Cuando termina la ejecución de una orden o programa, se envia un código de terminación al SO que es almacenado en esta variable, de este modo podremos saber si hubo algún problema en la ejecución. Si todo fue correcto, la variable tomará el valor 0, cuando haya habido algún problema, tomará un valor distinto de cero. 13 3.2.13 El identificador de proceso actual $$ Esta variable contiene el PID del proceso actual. Se suele emplear para la creación de archivos temporales (normalmente en el directorio /tmp). Al incluir el PID dentro del nombre del fichero, estamos haciendo que ese fichero sea único. Por ejemplo: set architemp=/tmp/temp1.$$ echo $architemp /tmp/temp1.1543 3.3 VARIABLES CONMUTADORES Hay algunas variables empotradas que solo pueden tomar dos valores: ON y OFF, debido a esto, son conocidas como conmutadores. Si una variable esta definida, significa que tiene su valor en ON, de lo contrario, esta OFF. Para activarlas y desactivarlas utilizaremos: set variable_conmutador unset variable_conmutador 3.3.1 $echo Esta variable hará que la shell muestre la orden a ejecutar tras la expansión de metacaracteres y la sustitución de variables. Es útil porque podremos depurar fallos al escribir ordenes. Otra forma de activar esta variable es iniciar el shell (chs y tcsh) con la opción –x o –X. 3.3.2 $filec Esta variable activa la terminación de nombres en la línea de comandos. Como comentamos anteriormente, cuando estamos escribiendo, pulsando la tecla ‘Tab’, 14 podremos completar el resto de la palabra. En caso de que haya más de una posibilidad, se nos mostrarán las posibles opciones. 3.3.2 $nobeep Cuando la variable anterior no encuentra ningun resultado a la comparación, emite un beep. Desactivando esta variable, suprimiremos los beeps. 3.3.3 $notify Cuando lanzamos un proceso en segundo plano, el shell notifica la finalización solo cuando la orden que estamos ejecutando en primer plano ha terminado. Activando esta variable, en cuanto la orden en segundo plano termine, se notificará. 3.3.4 $noglob Gracias a esta instrucción, podemos inhibir la expansión de metacaracteres en la línea de comandos, de modo que un metacaracter solo tendrá su significado como carácter. Por ejemplo: set $noglob echo * * ls * (listado de el fichero con nombre *) 3.4 VARIABLES NUMERICAS (csh y tcsh) Aunque las variables anteriores podían contener todo tipo de valores, incluyendo números, no podíamos realizar operaciones aritméticas con ellas. Cuando estemos programando ordenes y comandos, necesitaremos realizar operaciones matemáticas con variables. Para esta tarea podemos utilizar las variables numéricas. 15 El operador @ Con el símbolo @, podremos asignar y realizar operaciones con variables numéricas, si escribimos únicamente @ en la línea de comandos y se comporta igual que la orden set. @ name = exp. ? Asigna el valor de la expresión exp a la variable name @ name[index] = expr ? Asigna el valor de la expresión exp a la componente index de la variable name, la variable y la componente deben haberse declarado previamente. Las expresiones anteriores pueden contener operadores com ‘*’,’+’,etc. como los operadores de C. El espacio entre @ y el nombre de la variable es necesario al igual que la separación entre los componentes de las expresiones. 16