145
Tutorial del Shell Hablando con GNU/Linux a través del shell El shell o intérprete de comandos, como antes habíamos dicho, es una interfase con nuestro sistema operativo. Gracias a él podremos dar las órdenes y mandatos necesarios para que nuestro sistema informático realice las tareas que necesitamos. No debemos confundir al intérprete de comandos con el sistema operativo. Este es solo un programa que hará de mediador entre nosotros y el kernel del sistema. El shell puede ser tanto gráfico (Ej. La interfase X-Window), como de texto (Ej. El bash). En este capítulo trataremos el tema de shell al nivel de solo texto y en especial veremos un intérprete de comando que por su utilidad y su gran aceptación, es él mas usado tanto en Un*x como en GNU/Linux. Como veremos luego, el intérprete de comandos no solo tiene la labor de interpretar nuestros mandatos, también es un potente lenguaje de programación que nos será de gran utilidad a la hora de elaborar guiones (script) para poder automatizar nuestras tareas. Los usuarios de DOS estarán acostumbrados a la utilización de los archivos de procesamiento por lotes (.bat) o más bien denomina "batch". Existen varios tipos de intérpretes de comandos en UNIX de los cuales los más famosos e importantes son el "Bourne Shell" (sh) y el "C Shell" (csh). El intérprete de comandos Bourne, usa una sintaxis de comandos usada en los primeros sistemas UNIX, como el System III. El nombre de intérprete Bourne en la mayoría de los Un*x es /bin/sh (sh por shell). El C Shell posee una sintaxis muy parecida al lenguaje de programación C y se lo encontrara como /bin/csh. El más usado en el mundo GNU/Linux, como antes dijimos, es el bash por "Bourne Again Shell y se lo encontrará en /bin/bash. Bash posee toda la funcionalidad del sh con características avanzadas de C Shell, por esto cualquier guión escrito para un intérprete de comandos sh correrá perfectamente en él.

Tutorial del shell

  • Upload
    chiest

  • View
    233

  • Download
    0

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Tutorial del shell

Tutorial del Shell

Hablando con GNU/Linux a través del shellEl shell o intérprete de comandos, como antes habíamos dicho, es una interfase con nuestro sistema operativo. Gracias a él podremos dar las órdenes y mandatos necesarios para que nuestro sistema informático realice las tareas que necesitamos. No debemos confundir al intérprete de comandos con el sistema operativo. Este es solo un programa que hará de mediador entre nosotros y el kernel del sistema. El shell puede ser tanto gráfico (Ej. La interfase X-Window), como de texto (Ej. El bash).

En este capítulo trataremos el tema de shell al nivel de solo texto y en especial veremos un intérprete de comando que por su utilidad y su gran aceptación, es él mas usado tanto en Un*x como en GNU/Linux. Como veremos luego, el intérprete de comandos no solo tiene la labor de interpretar nuestros mandatos, también es un potente lenguaje de programación que nos será de gran utilidad a la hora de elaborar guiones (script) para poder automatizar nuestras tareas. Los usuarios de DOS estarán acostumbrados a la utilización de los archivos de procesamiento por lotes (.bat) o más bien denomina "batch".

Existen varios tipos de intérpretes de comandos en UNIX de los cuales los más famosos e importantes son el "Bourne Shell" (sh) y el "C Shell" (csh). El intérprete de comandos Bourne, usa una sintaxis de comandos usada en los primeros sistemas UNIX, como el System III. El nombre de intérprete Bourne en la mayoría de los Un*x es /bin/sh (sh por shell). El C Shell posee una sintaxis muy parecida al lenguaje de programación C y se lo encontrara como /bin/csh. El más usado en el mundo GNU/Linux, como antes dijimos, es el bash por "Bourne Again Shell y se lo encontrará en /bin/bash. Bash posee toda la funcionalidad del sh con características avanzadas de C Shell, por esto cualquier guión escrito para un intérprete de comandos sh correrá perfectamente en él. Si lo que se prefiere es el uso del intérprete de comandos basado en el lenguaje C, en GNU/Linux se podrá encontrar el Tcsh en /bin/tcsh, que es una versión extendida del C Shell. Los gustos de los usuarios son los que deciden que intérprete de comandos se usará, por esto es posible configurar para cada usuario un intérprete de comandos distintos y no afectar el funcionamiento de programas como el ls, cat o cp. Solo se vera afectada la funcionalidad de algún guión que esté preparado para ejecutar con un intérprete de comandos determinado, lo que veremos como se puede corregir al ver programación de script de shell.

Para más información respecto a cada uno de estos intérpretes de comandos se recomienda leer las páginas de manual de cada uno de ellos, lo que dará información muy detallada de estos.

Características

Comodines

Page 2: Tutorial del shell

Hablaremos de algunas característica de mucha utilidad y que harán mucho más fácil el trabajo, tanto en sh como en bash. Una de las características que poseen los intérpretes de comandos es el uso de comodines para reemplazar partes de archivos. Con esto, podría referirse a un archivo usando caracteres especiales como el "*" o "?". Supongamos que se desea listar todos los archivos que contengan la letra "ñ" en nuestro directorio. Para ello usaremos el comando ls

[shrek@pantano:~]$ ls *ñ*

Esto el intérprete de comandos lo vera como si quisiéramos listas todos los archivos que empezaran con ninguno, uno o varios caracteres, tuviesen una letra "ñ" y terminaran con ninguno, uno o varios caracteres.

[shrek@pantano:~]$ lshola heart texto.form manti.form[shrek@pantano:~]$ ls h*hola heart

Como puede observarse también nos es útil si se sabe como comienza el archivo pero no como termina. Lo que nuestro intérprete de comando esta haciendo es sustituir el "*" con cualquier combinación posible que coincida con los archivos que tenemos en el directorio donde estamos buscando. Si se utiliza solamente el "*" con el comando ls, este interpretará que se esta buscando cualquier combinación posible y listará todo como si se estuviese tratando de ejecutar el comando ls solo

[shrek@pantano:~]$ ls *hola heart texto.form manti.form

Este proceso es llamado "expansión de comodines" y lo efectúa el intérprete de comandos. Esto es muy importante ya que los comandos como el ls nunca ven el "*" en su lista de parámetros, es el intérprete de comandos quien expande los comodines para incluir todos los nombres de archivos que se adapten. Es decir que luego que se da la orden

[shrek@pantano:~]$ ls h*

es expandida para obtener

[shrek@pantano:~]$ ls hola heart

Otro comodín es el "?". Este carácter comodín solo expande un único carácter. Luego ls ? mostrará todos los nombres de archivos con un carácter de longitud. En cambio la orden ls hol? nos mostrará el archivo hola.

[shrek@pantano:~]$ ls ho?ahola[shrek@pantano:~]$ ls h????heart

Estos caracteres comodín nos permiten referirnos a más de un archivo al mismo tiempo y en conjunto con los comandos ya aprendidos, podrán ser de gran utilidad para realizar nuestras tareas de forma más fácil.

Page 3: Tutorial del shell

Ejecución de comandos uno detrás del otro

Supongamos que se necesita ejecutar un comando e inmediatamente después otro. En la forma común lo que haríamos seria ejecutar el primer comando y una vez que este haya finalizado, ejecutaríamos el segundo. Existe una segunda forma de hacerlo y es utilizando el carácter ";" inmediatamente después del primer comando y a continuación poner el segundo comando. Con esto lograríamos que se ejecutara el primer comando y al terminar se ejecutará el segundo.

[shrek@pantano:~]$ lshola heart texto.form manti.form[shrek@pantano:~]$ datemié jul 14 15:15:25 ART 2004

Utilizando el carácter ";" haremos

[shrek@pantano:~]$ ls;datehola heart texto.form manti.formmié jul 14 15:15:25 ART 2004

Comillas

Este punto viene bien aclararlo antes de empezar a ver características de alias y script para no tener complicaciones y confusiones. En GNU/Linux existen tres tipos de comillas: las dobles ("), comillas sencillas (') y comillas inversas o tics inversos (`). Empezaremos con las comillas inversas. Estas indican al shell que tendrá que remplazar lo que esta encerrado entre ellas con su resultado. Supongamos que quisiéramos ver solamente el día de hoy. Entonces teclearíamos el comando

[shrek@pantano:~]$ date +%d15

Ahora bien, cada vez que quisiéramos ver el día de hoy tendríamos que ingresar este comando nuevamente. Si le asignamos a una variable de entorno el resultado, solo tendríamos que mostrar esta variable.

[shrek@pantano:~]$ DIAHOY=`date +%d`[shrek@pantano:~]$ echo $DIAHOY15

Hay que tener en cuenta que para asignarle un valor a una variable tenemos que solo poner un nombre seguido del signo "=" y luego lo que queramos ponerle dentro. En cambio para mostrarla tendremos que anteponer el signo de dólar "$". Esto seria igual a poner

[shrek@pantano:~]$ DIAHOY=15

Lo único que el shell hace es expandir el comando para que solo se guarde el resultado de éste.

El otro tipo de comillas, la sencilla ('), le dice al sistema que no haga ninguna expansión.

Page 4: Tutorial del shell

[shrek@pantano:~]$ DIAHOY='date +%d'[shrek@pantano:~]$ echo $DIAHOYdate +%d

Lo que se obtiene es exactamente lo que le asignamos a la variable ya que el shell no realizo ninguna expansión y lo único que asigno fue la cadena 'date +%d' a la variable DIAHOY.

El ultimo tipo de comillas son las dobles, este tiene casi la misma funcionalidad que las comillas simples pero con la salvedad de que lo que se incluya dentro de estas estará sujeto a expansión por parte del shell, siendo los caracteres con significado especial los tics inversos (`) el signo de dólar ($), la diagonal (\) y las mismas comillas dobles ("). Por ejemplo podríamos ingresar el siguiente comando

[shrek@pantano:~]$ echo "`date`"Sat Apr 15 14:17:01 ART 2000

Alias

La utilización de alias nos da la capacidad de poder referenciar a un comando con otro nombre. La diferencia sustancial que podemos encontrar con los script de shell, es que los script para ejecutarse primero lanzaran a un subshell como un proceso hijo del shell que esta ejecutando en ese momento. En cambio un alias funciona en el proceso del shell siendo ejecutado en forma interna con la subsiguiente velocidad que esto otorga al no tener que crearse un nuevo proceso o de buscar en el disco rígido. Por supuesto que pueden usarse un conjunto de comandos para crear otro más complejos. Con los scripts se puede realizar lo mismo y lo veremos más adelante, pero para comandos simples y cortos no son necesarios. Los alias pertenecen a cada usuario, pudiendo éste configurarlos como más le convenga.

Supongamos que quisiéramos ver solo la hora cada vez que se lo pidamos al sistema y no quisiéramos poner el comando date con su modificador cada vez que lo queramos hacer. Lo que haremos será crear un "alias" al comando "date" con el modificador correspondiente. Para ello contamos con el comando alias, que seguido de argumentos nos permitirá crear uno, sin argumentos nos mostrará los alias que tenemos configurados.

[shrek@pantano:~]$ alias hora='date +%r'[shrek@pantano:~]$ hora02:45:04 PM

Ahora bien, esto funcionará mientras estemos en el sistema, ya que estos datos son cargados en memoria y al salir del sistema se perderán. Para que cada vez que entremos al sistema los alias sigan funcionando deberemos agregarlos a un archivo, que aparece en forma oculta en el directorio de cada usuario, denominado .bashrc o en caso de que se requiera que el alias funcione para todos los usuarios en el /etc/bashrc. Este archivo es leído por el /bin/bash cada vez que se entra al sistema. En él se tendrá que poner la línea alias en igual forma que lo haríamos en la interfaz de comandos.

Completado de línea

Page 5: Tutorial del shell

Se puede hacer que el shell complete la línea de comandos cuando se introduzca la primeras letras y se presione la tecla Tab. Esta propiedad también es útil para expandir la ruta a un directorio determinado. Supongamos que dentro del directorio /home existe un subdirectorio llamado /shrek

[shrek@pantano:~]$ cd /home/shr

Si presionamos la tecla Tab se completara la línea en /home/shrek. Si existiera más de un directorio que comenzará con "shr", el shell anunciaría con una señal audible, "bip", que existen más de una coincidencia, y al presionar nuevamente la tecla Tab mostraría una lista de todos los directorios que poseen "shr" al comienzo. Si dicha lista excediera la catidad de lineas a motrar en la consola, nos preguntará primero si es que queremos ver la cantidad "X" de posibilidades. Como ejemplo de esto podríamos citar el autocompletado de comandos. Si se oprime la tecla Tab sin haber introducido nada antes, el shell nos mostraría primero que existe un número "X" de posibilidades y al presionar nuevamente nos mostraría un listado de todos los comandos que son alcanzables.

PATHMuchas veces ocurre que al tratar de introducir un comando nos damos cuenta de que no tiene efecto y nos da un error en él intérprete de comandos. Tal vez se haya ingresado mal, pero tal vez no se posea el directorio que contiene dicho comando en la "ruta de búsqueda" o PATH. EL PATH es una variable de entorno que contiene un grupo de directorios predefinidos en los cuales el shell buscará el comando o programa a ejecutar. Esto ahorra tiempo ya que el sistema no tendrá que buscar en todos los directorios el programa a ejecutar. Por esto el sistema, en caso de que el directorio no figure en el PATH, no podrá ejecutar el programa hasta que le demos la ruta exacta en donde se encuentre.

Esta variable de entorno llamada PATH, es inicializada con un valor predeterminado en el archivo /etc/profile que es sólo modificable por el "root" y funciona como una referencia para todos los usuarios. Además cada usuario posee en un archivo oculto denominado .bash_profile o .profile, donde se le asigna además del PATH inicial, cualquier otra modificación exclusiva para él. También puede modificarse totalmente esta variable.

Volviendo a la especificación de la ruta completa, anteriormente dijimos que los archivos se referenciaban de esta forma, pero los programas también podrán referenciarse de la misma forma. Si le damos la ruta completa podremos ejecutar el programa, si es que se cuenta con los permisos adecuados, independientemente del valor de la variable PATH. Como ejemplo, si quisiéramos ejecutar el programa date, referenciándolo con una ruta completa, la sintaxis es

[shrek@pantano:~]$ /bin/datemié jul 14 15:15:25 ART 2004

Seguramente el directorio /bin estará en nuestra ruta, esto sirve solo como un ejemplo.

Page 6: Tutorial del shell

Existe otra forma de ejecutar el programa, y es haciendo referencia a su ruta relativa, que es la ruta con relación al directorio donde estamos parados actualmente. Para esto debemos saber que la forma de referenciar al directorio actual es mediante "." y a su directorio padre con ".." (Mencionándose comúnmente como "punto" y "punto - punto"). Dado que los directorios están divididos por una "/", se podría hacer referencia a un archivo en el directorio padre con ../archivo. De esta forma, si se quisiera hacer referencia a un archivo que se encuentra dos niveles encima nuestro, su referencia relativa seria ../../archivo.

Algo que difiere en la forma de ejecutar los programas en GNU/Linux y DOS, es que este último busca primero el archivo a ejecutar en el directorio actual y luego en la ruta de búsqueda. En cambio en GNU/Linux, solo se buscará en la ruta.

No es problema ejecutar un archivo que esta en el directorio actual ya que este está incluíido en la ruta, pero por seguridad, deberá estar agregado como el último directorio en la ruta, por lo menos en la cuenta "root" ya que si algún usuario creara un archivo malicioso que estuviera en el directorio donde esta parado el usuario root en ese momento, y lo nombrara "more", cuando el root ejecute este comando tendría resultados catastróficos. En cambio, si el directorio actual esta a lo último de la ruta, primero se ejecutara el que se encontré en el /bin en lugar que el que esté en el directorio actual. Igualmente para poder ejecutar directamente un programa que se encuentra en el directorio en que estamos parados actualmente podríamos ingresar la ruta relativa a este, anteponiendo la referencia al directorio actual "./" al programa. Para ejecutar el programa hola que se encuentra en el directorio donde estamos parados actualmente

[shrek@pantano:~]$ ./holaHola amigos !!!

No busquen el programa "hola" en su sistema, no lo he distribuido aún ya que esta en desarrollo :^).

Variables de entornoIndependientemente de shell que estemos usando, se contará con lo que se denomina "variable de entorno" o "variable de ambiente". Estas variables son como las que encontraremos en cualquier lenguaje de programación. Esto es tan esta forma que también podría ser accedidas desde los scripts que creemos. Para distinguir de los comando, la variables se ponen en letra mayúscula. Cuando uno entra al sistema, existen ciertas de estas variables ya están asignadas. Para ver estas variables y su contenidos se cuenta con el comando "set", y para ver el contenido de una de estas variables solo tenemos que usar el comando "echo" seguido del nombre de la variable con el signo "$" antepuesto. Ej. echo $LOGNAME, con lo obtendremos el nombre del usuario.

Siguiendo con la ruta de búsqueda o PATH, esta es guardada en una variable llamada "$PATH", con lo que si tecleamos "echo $PATH" veremos algo como esto

[shrek@pantano:~]$ echo $PATH/usr/local/bin:/bin:/usr/bin:/usr/X11/bin:/home/shrek:/:.

Page 7: Tutorial del shell

Nótese que el ultimo exponente de la ruta es el directorio actual que habíamos indicado en el punto anterior sobre "ruta de búsqueda". Como se puede observar cada uno de los directorios esta separado por ":" y en último lugar está la referencia al directorio actual que habíamos hablado anteriormente. Otra variable muy importante es el "prompt" que no es ni más ni menos que la secuencia de caracteres que aparecen justo antes de lo que ingresamos en la interfase de comandos. El entorno bash dispone de 4 prompt's, "PS1", "PS2", "PS3" y "PS4". Estas variables tienen un porqué. La denominación "PS1" es el prompt principal y es el que vemos al iniciar el sistema. El "PS2" es el que aparece si al introducir algo que sobrepasa la línea y se va a la siguiente. Su valor por defecto es ">". Se puede comprobar ingresando el carácter "\" en la línea que estemos ingresando, con lo que pasaremos a la siguiente línea. El "PS3" aparece cuando se utiliza el comando "select" de la interfase de comandos. El "PS4" aparece cuando se efectúa el seguimiento de un comando. El prompt y la mayoría de las variables de entorno pueden ser modificados con el comando "export", con el podremos modificar el contenido de las variables.

[shrek@pantano:~]$ export SECONDS=0[shrek@pantano:~]$ echo $SECONDS0

La variable $SECONDS cuenta la cantidad de segundos desde que entramos al sistema; con este mandato la seteamos a "0". Existen variables que no pueden ser cambiadas, como UID, EUID o PPID, (se muestra un detalle de las variables más útiles en la tabla 2). Volviendo al prompt, este puede ser cambiado para que, por ejemplo, nos muestre el nombre de usuario seguido de una "@" y el nombre del sistema, con la ayuda de caracteres especiales.

[shrek@pantano:~]$ export PS1='[\u@\h:\w]\$ '

Se muestra en la tabla los caracteres especiales del prompt.

Tabla 1. Caracteres especiales de la variable PROMPT

Caracter Que representa

\t La Hora actual en formato HH:MM:SS.

\d La fecha en formato "Día de la Semana Mes Fecha", como por ejemplo, "Sun Feb 4".

\n Salto de línea.

\s Nombre delshell.

\w El directorio actual.

\W El nombre base del directorio actual. Por ejemplo, del directorio /home/shrek, el nombre base es shrek.

\u Nombre de usuario.

\h Nombre de máquina.

Page 8: Tutorial del shell

Caracter Que representa

\# Número de comando del comando actual.

\! Posición en el historial de comandos del comando actual.

\$ Si la EUID es 0 (root), el carácter '#'. En cualquier otro caso el carácter es '$'.

\\ La barra inclinada hacia atrás.

\nnn El carácter correspondiente al numero octal nnn.

\[ Comienza una secuencia de caracteres no imprimibles, como los caracteres de escape o las secuencias de control. Estos caracteres pueden ser usados para definir colores.

\] Fin de la secuencia de caracteres no imprimibles.

Tabla 2. Variables más comunes

Variable Definición

PPID Número de identificación del proceso padre de la interfaz de comandos.

PWD Directorio de trabajo actual, establecido por el comando cd.

OLDPWD Anterior directorio de trabajo, establecido por el comando cd.

REPLY Cuando se usa el comando read de bash sin argumentos,esta variable recoge el contenido de la línea leída.

UID Número identificativo (ID) del usuario, establecida en el arranque del shell.

EUID ID eficaz de usuario, inicializada en el arranque del shell.

BASH Nombre completo, incluida la ruta, del archivo que se ejecutó para lanzar el shell.

BASH_VERSION Número de versión de Bash.

SHLVL Nivel del shell. Incrementa su valor en una unidad cada vez que se lanza una nueva interfaz de comandos.

RANDOM Cada vez que se invoca a esta variable se obtiene un número entero aleatorio. La secuencia de números aleatorios proporcionadas por RAMDOM se puede inicializar simplemente asignándole un nuevo valor a esta variable.

Page 9: Tutorial del shell

Variable Definición

SECONDS Mantiene el número de segundos que han transcurrido desde que se ejecutó el shell. Si asignamos un valor a esta variable, la cuenta indicará los segundos transcurridos desde dicha asignación, mas el valor asignado.

LINENO Cuando se hace referencia a esta variable desde un script, indica la línea dentro del script en la que se le esta haciendo referencia, considerando que la primera línea se numera como 1. Si se invoca desde la propia interfaz de comandos, el valor que devuelve es el número de línea que hace la orden ejecutada desde que se inició la interfaz de comandos.

HISTCMD Contiene la posición dentro del archivo de historia de comandos que ocupa el comando actual.

HOSTTYPE Se trata de una cadena de texto describiendo el tipo de máquina en la que esta ejecutando el bash.

HOSTNAME Nombre de la máquina.

OSTYPE Se trata de una cadena de texto describiendo el sistema operativo en el que sé esta ejecutando el bash.

PATH La ruta de búsqueda de comandos. Se trata de una secuencia de directorios en los que localizar los programas, separados entre sí por un signo de dos puntos (:). La interfaz de comandos recorrerá esta lista en el orden dado buscando los comandos que queramos ejecutar.

HOME Directorio raíz del usuario actual. Es el argumento usado por defecto cuando ejecutamos el comando cd sin especificar ninguno.

CDPATH Se trata de la ruta de búsqueda para el cd. Tiene una estructura similar a la variable PATH. Lo que indica es donde se deben buscar los directorios especificados como argumentos al comando. Como ejemplo habitual, podría contener :~:/usr.

MAIL Cuando contiene el nombre de un archivo, bash comprueba en él la llegada de correo nuevo y avisa en caso que se produzca.

MAILCHECK Determina el intervalo de tiempo en segundos que bash tomará para revisar si hay correos nuevos.

MAILPATH Al igual que PATH y CDPATH, esta variable contiene una lista, en este caso, de archivos que deberán ser comprobados para la posible llegada de correo. Se puede indicar un mensaje especifico para la llegada de correo en diferentes buzones usando el carácter '?' como separador

Page 10: Tutorial del shell

Variable Definición

entre el archivo y el mensaje. En ese caso, la variable $_ obtendrá el nombre del buzón. Un ejemplo: MAILPATH='/var/spool/mail/nlucas?"Tienes correo":~/mail/buzon?"Ha llegado algo al $_"'

PS1 Valor del prompt principal. En la tabla 1 se muestran los valores con los que puede expandirse.

PS2 Valor del prompt secundario. Este prompt es el que aparece cuando partimos una línea en la interfaz de comandos para continuar introduciendo en la siguiente línea de la pantalla.

PS3 Valor del tercer prompt. Este prompt es usado solamente por el comando select.

PS4 Valor del cuarto prompt y último. Tan solo se usa cuando se esta realizando un seguimiento de los comandos mostrándose para indicar los pasos por los que se va ejecutando el comando. Para entrar en el modo de seguimiento, basta con ejecutar set -x. Entonces veremos como cada comando que ejecutemos se expande, mostrando las sustituciones que se hacen con los alias, las variables, etc.

HISTSIZE Contiene él número de comandos a guardar en el historial de comandos.

HISTFILE Contiene el nombre del archivo en el que se almacena el historial de comandos. Por defecto se trata del archivo ~/.bash_history.

HISTFILESIZE Número máximo de líneas que puede contener el archivo de historial. Tengamos en cuenta que un comando puede ocupar varias líneas.

PROMPT_COMMAND Si esta definido, contiene el comando a ejecutar antes de presentar el prompt.

IGNOREEOF Indica cuantas veces ha de recibir el carácter EOF (End Of File, o la pulsación de la tecla Crtl-D) antes de salir de bash. Si el valor indicado no es numérico, se toma por defecto el 10. Si no esta seleccionado, una única pulsación basta.

TMOUT Si contiene un valor superior a cero, indica el número de segundos que se puede estar sin introducir un comando a el shell. Pasado este tiempo, la interfaz de comandos se cerrará.

FCEDIT Ruta y nombre del editor usado por defecto para el

Page 11: Tutorial del shell

Variable Definición

comando fc. Por defecto se usa Vi .

FIGNORE Lista de sufijos de archivos que se ignoraran al intentar completar un nombre de archivo desde bash. La lista estará formada por los sufijos ignorados, separados por un signo de dos puntos (:). Por ejemplo .0:.tmp

EDITOR En esta variable muchos programas buscaran la ruta y el nombre del editor a usar. Por defecto el editor usado es el Vi. Algunos de los programas que hacen uso de esta variable son crontab (con la opción -e), edquota y otros muchos.

TERM Contiene el tipo de terminal. Esta variable es importante, pues algunos tipos de terminales no son compatibles con algunos programas.

Expresiones regulares y uso de metacaracteresEmpezaremos ampliando el uso de los comodines que antesmencionamos (* y ?). Es muy frecuente el uso de esta clase de caracterespara que el shell los expanda a fin de que coincidan con cualquiercarácter, en el caso de "?", y con cualquier cadena de caracteres, en elcaso de "*". La utilización de estos ya la definimos anteriormente ysolo nos queda mostrar su utilización en función de las expresiones regulares.

La expresiones regulares son una serie de reglas que de cumplirsese expanden para poder ser utilizadas. Para esto se utiliza también otrotipo de metacaracteres "[]" donde los caracteres que se introduzcandentro serán reemplazados para completar el comando. Supongamos quequeremos editar con el programa vi los archivos carta.1, carta.2, carta.3, carta.4 y carta.5. Podríamos utilizar tanto el carácter ? como el * paraeditarlo. Pero también puede ser utilizado la serie de números del 1 al 5 encerrados dentro de los corchetes ([]).

[shrek@pantano:~]$ vi carta.*

Con esto editaríamos todos los archivos desde carta.1 a carta.5.

[shrek@pantano:~]$ vi carta.[12345]

Con esta expresión, el intérprete de comandos expandirá a cadauno de los caracteres encerrados entre los corchetes para que tome ellugar que corresponde en el nombre del archivo a editar. ¿Pero que pasaría si solo se quisiera editar el archivo carta.1, carta.2 y carta.5? No podríamos utilizar ni el carácter "*" ni el "?" para hacerlo de un solo paso, pero si podremos usar la expresión regular de esta forma

[shrek@pantano:~]$ vi carta.[125]

Page 12: Tutorial del shell

Con esto, y dado que el intérprete de comandos solo interpreta deun carácter por vez, se editaran solamente los archivos carta.1, carta.2y carta.5. Los números serán tomados dentro de los corchetes comocaracteres individuales.

La utilidad de las expresiones regulares es muy grande, y existencasos que es solamente con su utilización que puede realizarse untrabajo. Las expresiones regulares podrán ser usadas, junto con otroscomandos, también para identificar grupos de caracteres en un texto yrepresentarlos según se pida. Por ejemplo, utilizando el comando grep,que casualmente significa Global Regular Expresión Print, se podrábuscar dentro de un texto una cadena que se requiera y mostrarla por pantalla. Supongamos que necesitamos mostrar todas las líneas que posean la palabra carta en el archivo documentos

[shrek@pantano:~]$ grep carta documentos

Lo que nos devolverá las líneas que posean la palabra carta, aun aquellas que tengan entre sus letras un grupo de caracteres que sea igual al buscado, por ejemplo "cartas" o "pancarta". Ahora bien, que pasaría si la palabra carta estuviese escrita con el primer carácter en mayúsculas. Entonces el comando grep no la mostraría, para esto podríamos usar una expresión regular de esta forma

[shrek@pantano:~]$ grep [Cc]arta documentos

Si lo que necesitáramos es buscar las líneas que comiencen con la palabra carta, tanto con la "C" en mayúsculas o minúsculas usaríamos el símbolo circunflejo (^) y el comando es

[shrek@pantano:~]$ grep ^[Cc]arta documentos

Con esto indicaríamos que mostrará todas las líneas que tuviesen como primer palabra a "carta" tanto con la primera letra en mayúscula o minúscula. Si lo que quisiéramos es mostrar todas las líneas de documentos que terminaran con la palabra "carta", tendríamos que usar la función que cumple el símbolo "$" (ya habíamos visto que era usado para referenciar a una variable de entorno) que en las expresiónes regulares, colocado al final, indica que esta tendrá que ser buscada al final de la línea. Primero le asignaremos la expresión a una variable para que el mandato sea más legible y se vea la utilización de las dos funciones del símbolo $

[shrek@pantano:~]$ VAR=^[Cc]arta[shrek@pantano:~]$ grep $VAR$ documentos

Explicamos el uso de expresiones regulares solo con el comando grep, pero existe un sin número de oportunidades para usarlas con los comandos. Se verá más adelante que pueden ser muy utilizadas en el editor Vi y nos harán muy fácil el trabajo con éste.

Interpretación de comandosHemos podido apreciar la utilización de una serie de comandosjunto con aplicaciones comunes de estos, pero es de necesidad poderentender el método por el cual estos comandos son interpretados por elshell, para tener un poco más de entendimientos a la hora de elaborarnuestros propios script y programas. Lo primero que se nos puede

Page 13: Tutorial del shell

ocurrir averiguar, es el orden en que son interpretados los comandos. Partiremos de la base que se pueden ejecutar más de un comando en una línea. Esto se logra separándolos con un punto y coma (;).

Lo primero que el shell realiza es dividir estos comandos en lo que se denomina "tokens". Cada token es un comando, junto con sus argumentos, a ejecutar. Una vez que el shell puede saber cuantos tokens hay, determina su sintaxis. Si existe un error en este punto, ninguno del os tokens se ejecutará y el shell nos advertirá de un posible error de sintaxis. Si la sintaxis es correcta, comienza la interpretación de los comandos. A partir de aquí el shell trata de ver si alguno de los tokens es en realidad una función del propio shell. Si existe, esta será expandida antes de ser ejecutada. Luego, se expanden los alias. Si alguno de los tokens es en realidad un alias, ya sea creado por el usuario o no, este se expandirá antes de ejecutarse. Si el alias llama a otro alias, este también se expandirá antes de ejecutarse. Una vez que se han expandido los alias y funciones el shell comenzará a evaluar las variables y las sustituirá con su valor. Al terminar esto, se expandirá cualquier comodín utilizado expandiéndolo al nombre de archivo o comando que concuerde de acuerdo a las reglas antedichas. Ahora, aunque está la mayor parte del comando evaluado, el shell tendrá todavía que ver si el primero de los tokens corresponde a un comando del shell o a un programa externo. Si esto ocurriera, se tendrá que consultar la ruta de búsqueda. Luego evaluará si existe algún tipo de redirección o canalización, tem que veremos más en detalle en el próximo capítulo, por el cual la entrada o salida de un comando este redirigida a otro lugar. Una vez que se ha podido analizar todo el comando o conjunto de comandos a su mínima expresión, el shell efectuará una copia de si mismo, a través de la llamada a sistema fork() para poder ejecutar el script. Esta copia es un hijo del shell y que depende del shell que lo originó. Luego de esto, el shell hijo, usará una llamada a sistema denominada exec() para poder ejecutar el binario correspondiente. Aunque quien lo ejecuta es en realidad el shell hijo, hay que recordar que el padre todavía se encuentra en memoria esperando la finalización del proceso hijo.

Page 14: Tutorial del shell

Puede darse el caso que se desee que quien ejecute el comando o script sea el propio shell y no un shell hijo. Esto se logra con la utilización del comando "." punto. Al anteponer un punto al comando o script y dejando un espacio entre ellos, el shell entenderá que es el mismo quién debe interpretar este comando o script.

[shrek@pantano:~]$ . myscript

Este script será interpretado sin que se genere un sub-shell hijo.

Esta es una simplificación de la ejecución de un comando tipo, no quiere ser una explicación total de lo que puede ocurrir dado la grancantidad de variantes que intervienen, pero servirá como base de entendimiento de lo que el shell realiza una vez que se ha presionado la tecla Enter.

FuncionesUno de las mayores utilidades que posee una shell es el permitirnos crear funciones para realizar tareas repetitivas fácilmente. El funcionamiento de estas funciones es parecido al que posee cualquier lenguaje de programación, en el cual se agrupan conjunto de comandos y se los llama por un nombre. El formato de las funciones es el siguiente

nombre_funcion(){ primero_a_realizar segundo_a_realizar }

Estas funciones pueden ser definidas en cualquier lugar, incluso en la misma línea de comandos. Lo que habrá que recordar que hechas de esta forma se borraran de la memoria una vez que se a salido del shell. Una forma de hacer que queden disponibles en forma permanente es incorporarla en el archivo de inicio del shell, el .bash_profile, en el cual se pondrá la función. De esta forma podremos seguir utilizándola dado que será cargada en memoria cada vez que ejecute el shell. Veamos un ejemplo de una función simple

[shrek@pantano:~]$ que_tal()> {> echo "Hola $1, como estás?"> }[shrek@pantano:~]$ que_tal shrekHola shrek, como estás?

Aquí podemos ver dos factores en la creación de funciones. Primero se nombra a la función, seguida de un par de paréntesis "( )" con lo cual se indica al shell que lo que viene a continuación deberá ser tomado como una función. Inmediatamente después de los paréntesis se abrirá una llave "{", con lo que se indica que comienzan los comandos de la función. Al terminar se cierra la llave "}".

El otro punto es el reemplazo que efectúa el shell de las variables. Aquí la variable se asigna directamente y es un número que vendrá después del signo "$". Este número indica el número del argumento de que tomara su valor y que es dado al invocar a la función. En este caso su valor pasa a ser "shrek". Podremos asignar más variables de

Page 15: Tutorial del shell

este tipo que serán tomadas de acuerdo a su valor numérico como el número del argumento.

[shrek@pantano:~]$ que_tal()> {> echo Hola $1 como estas?> echo Espero que estés $2> }[shrek@pantano:~]$ que_tal shrek bienHola shrek como estas?Espero que estés bien

Como en la programación, donde los límites entre las funciones y los procedimientos esta dada de acuerdo a la función que se esta cumpliendo, en el caso de las funciones del shell varía de acuerdo donde se encuentren guardadas. Una función está en memoria y puede ser cargada por el shell a partir de un archivo como el .bash_profile que es leído por él al iniciarse. En caso de que se creará un archivo aparte con permisos de ejecución, esta función pasaría a ser un script pero se necesitaría que se llame a la función desde dentro del mismo script. Volveremos a esto al tratar el tema de script de shell pero daremos un ejemplo para que se entienda mejor. Supongamos que creamos un archivo llamado saludo.sh y le damos permisos de ejecución con el comando chmod. El signo # representa un comentario

[shrek@pantano:~]$ cat > saludo.sh (1)que_tal() (2){echo Hola $1 como estas?echo Espero que estés $2}que_tal $1 $2 (3)[shrek@pantano:~]$ chmod +x saludo.sh (4)(1)

Con el comando cat y redirigiendo su salida se puede crear un archivo (2)

A continuación se ingresa la función (3)

Ahora la función es llamada desde dentro del script. Al finalizar se presionan las teclas Ctrl-D

(4) Le damos los permisos de ejecución solo para nosotros

Lo ejecutamos, dado que estamos parados en el mismo directorio en que lo creamos, anteponiendo un punto y la barra para que el shell sepa que nos estamos refiriendo al directorio actual. El resultado es

[shrek@pantano:~]$ ./saludo.sh shrek bienHola shrek como estas?Espero que estés bien

Características adicionalesDepuración de Script

Page 16: Tutorial del shell

Es posible depurar un script si se escribe set -x antes de ejecutarlo. De esta forma cada comando se mostrará en pantalla antes de ejecutarse con sus correspondientes argumentos. Se desactiva ingresando set +x. Si lo que se quiere es mandar la salida a un archivo se tendrá que tener en cuenta que la salida del set -x no vá hacia la salida estándar (stdout) sino hacia el error estándar stderr. Si tomamos que la entrada estándar (stdin) es el "0", la salida estándar (stdout) es el "1", entonces el tercer archivo (sterr) es el "2". Por ello si se quiere depurar el script myscript y mandar la salida a un archivo, se tendrá que ingresar lo siguient luego del set -x.

[shrek@pantano:~]$ myscript 2>archivo_salida

Esto indica que se debe mandar el descriptor de archivo 2 (stderr) al archivo archivo_salida.

Creación de directorios múltiplesSupongamos que queremos crear un subdirectorio en el directorio /home/shrek/cartas/trabajo/mensuales, pero ni el directorio /cartas ni /trabajo están creados aún. A través del modificador -p del comando mkdir de esta forma parados sobre el directorio /home/shrek

[shrek@pantano /home/shrek]$ mkdir -p /cartas/trabajo/mensuales

De esta forma primero se creará el directorio /cartas, luego /trabajo y por ultimo /mensuales.

Como en UNIX también en GNU/LinuxEn el capítulo anterior vimos el funcionamiento de la interfase de comandos bash y comenzamos viendo el poder que posee Un*x para el manejo de la información. En este capítulo trataremos temas un poco más específicos, concentrándonos en los aspectos más importantes que podremos ver en nuestro sistema operativo. El hecho de que estas terminologías empleadas en GNU/Linux, antes se hayan aplicado a Un*x, hacen que él saberlas nos abra las puertas a todo un sinfín de particularidades compartidas que hacen mucho más versátil el trabajo con cualquier entorno que sea equivalente.

Plomería en GNU/LinuxEntrada y salida estándarHablamos antes de los 3 archivos que el sistema abría en memoria al iniciarse, estos eran el stdin, el stdout y stderr. El intérprete de comandos configurará estos archivos para que apunten al teclado, en el caso del stdin, y al monitor, en el caso del stdout y stderr. Existen numerosos comandos de Un*x que utilizan la entrada estándar para tomar sus datos y la salida estándar para volcarlos a la pantalla. La configuración esta dada de este modo ya que el shell espera que se ingresen los datos por el teclado y que su resultado o algún error se reflejen en la pantalla. Un ejemplo seráa el caso del

Page 17: Tutorial del shell

comando cat. Si usáramos el comando cat, sin ningún argumento, todo lo que ingresemos se vería repetido en la pantalla.

[shrek@pantano:~]$ catHola (1)Hola (2)Que tal (3)Que tal (4)(1) (3)

Línea escrita por nosotros. (2) (4)

Línea devuelta a la salida estándar.

La entrada se termina presionando Ctrl-D que es el carácter de EOT (end of text) fin de texto.

Canalización y redirecciónExiste la posibilidad de desviar la salida o la entrada a un comando para poder realizar funciones complejas u obtener los datos que saldrían por la pantalla directamente a otro archivo. Lo primero se denomina canalización y lo segundo redirección. El símbolo que se utiliza para efectuar la canalización es el denominado pipe o símbolode canalización (|). Este símbolo permite que se pase la salida de unacomando o programa a la entrada de otro. Un ejemplo clásico de lautilización de este símbolo es cuando se requiere listar un directorioque ocupa más de una pantalla. Se podrá entonces utilizar el comandoclásico para listar ls y enviar su salida a otroprograma que lo muestre de a una página de pantalla por vez, por ejemplo el more.

[shrek@pantano:~]$ ls -l | more

Esto servirá para realizar lo antedicho ya que la salida del comando ls será canalizada para que sea la entrada del comando more y este se encargara de mostrar los datos por pantalla. Lo que se esta utilizando es la canalización de la entrada estándar y la salida estándar. La salida estándar del comando ls es redireccionada hacia la entrada estándar del comando more que es cambiada para que también apunte a la canalización. Otros dos símbolos utilizados son el < y el >. Lo que hacen es redirigir tanto la salida como la entrada estándar de o hacia un archivo. Por ejemplo, supongamos que necesitamos guardar en un archivo llamado listado la salida del comando ls.

[shrek@pantano:~]$ ls > listado

Con esto le indicamos al comando ls que redireccione la salida estándar hacia un archivo de nombre listado. En caso de que el archivo exista, será reemplazado con la nueva información. Para agregar contenido a un archivo, inmediatamente después del contenido que posea, se tendrá que poner el símbolo de redirección dos veces

[shrek@pantano:~]$ ls >> listado

El uso de < es para redireccionar el contenido de un archivo hacia la entrada estándar de un comando o programa. Supongamos que necesitamos ordenar el contenido de un archivo en orden alfabético, lo que lograremos con el comando sort. Podremos entonces

Page 18: Tutorial del shell

redireccionar el contenido de un archivo a la entrada del comando sort para que éste lo ordene.

[shrek@pantano:~]$ sort < nombres

De esta manera saldría por pantalla la lista de nombres ordenadas alfabéticamente. También se podrá redireccionar el error estándar para que no salga en pantalla. Si quisieramos realizar un listado de un directorio y, en caso de producirse un error, este fuese redirigido a un archivo, haremos lo siguiente

[shrek@pantano:~]$ ls /bin 2>/tmp/error.ls

Esta simple redirección solo tendría efecto sobre el error estándar (stderr) o como también se denomina, descriptor de archivo nº 2. Con esta redirección los posibles errores serían redirigidos al archivo /tmp/error.ls. Si quisiéramos dividir tanto la salida por pantalla como el error en dos archivos separados podemos hacerlo de esta manera

[shrek@pantano:~]$ ls /bin 1>/tmp/salida 2>/tmp/error.ls

La redirección y la canalización pueden combinarse para hacer cosas un poco más complejas o realizar tareas en un solo paso. Supongamos que necesitábamos obtener las 10 primeras líneas del listado que anteriormente guardamos del directorio /bin. Para esto podríamos usar el comando head directamente para que obtenga las 10 primeras líneas del archivo listado, pero para entender el uso combinado de la canalización y la redirección lo haremos de otra forma

[shrek@pantano:~]$ sort < listado | head

Como se puede ver, se a pasado por medio de una redirección el contenido del archivo listado al comando sort y por medio de la canalización hemos pasado la salida estándar del comando sort al comando head.

Permisos de archivos, sus dueños y gruposPara entender mejor el concepto de permisos se tendrá que tener en cuenta que cada usuario puede pertenecer a uno o más grupos. Cada usuario pertenece por lo menos a un grupo, que es establecido en el momento en que el usuario se crea. El administrador del sistema puede agregar al usuario a otros grupos. Estos grupos son necesarios para poder establecer una política de acceso más organizada dado que en cualquier momento se podría dar a un archivo el acceso a personas de un grupo determinado. Lo único que se tendría que hacer es agregar a los usuarios que se quieran dar permisos a ese grupo.

Para cada objeto (archivo) que se encuentre en el sistema, GNU/Linux guarda información administrativa en la tabla de inodos, tema que abarcaremos en mayor detalle más adelante. Entre los datos que se guardan en esta tabla se encuentran la fecha de creación del archivo, modificación del archivo y la fecha en que se cambio el inodo.

Page 19: Tutorial del shell

Pero además contiene los datos en los que se centra toda la seguridad en Un*x. Estos son

El dueño de archivo El grupo del archivo Los bits de modo o también llamados permisos de archivo

En este tramo nos centraremos en primer medida en entender los permisos y en establecer la forma en que pueden trabajar con ellos.

ConceptosAl ser Un*x y GNU/Linux sistemas operativos multiusuario, para que se puedan proteger los archivos se estableció un mecanismo por el cual se otorgan permisos a un determinado usuario y/o grupo. Esto permite, por ejemplo, que si existe un archivo creado por un usuario en particular, este será propiedad del usuario y también tendrá el grupo del usuario. Se permite que los archivos sean compartidos entre usuarios y grupos de usuarios. Por ejemplo si shrek quisiera puede prohibir los accesos a un archivo determinado que le pertenezca a todos los usuarios que no pertenezcan a su grupo de usuarios.

Los permisos están divididos en tres tipos: lectura, escritura y ejecución (rwx). Estos permisos pueden estar fijados para tres clases de usuario: el propietario del archivo, el grupo al que pertenece el archivo y para todo el resto de los usuarios. El permiso de lectura permite a un usuario leer el contenido del archivo o en el caso de que el archivo sea un directorio, la posibilidad de ver el contenido del mismo. El permiso de escritura permite al usuario modificar y escribir el archivo. En el caso de un directorio permite la crear nuevos archivos en él o borrar archivos existentes. El permiso de ejecución permite al usuario ejecutar el archivo, si tiene algo para ejecutarse. Para los directorios permite al usuario cambiarse a él con el comando cd.

Como se interpretan los permisosPara poder interpretar los permisos de archivos nada mejor que utilizar el comando ls -la. Con esto vemos un listado largo de un directorio.

[shrek@pantano:~]$ ls -latotal 13drwxr-sr-x 2 shrek user 1024 May 2 09:04 .drwxrwsr-x 4 root staff 1024 Apr 17 21:08 ..-rw------- 1 shrek user 2541 May 2 22:04 .bash_history-rw-r--r-- 1 shrek user 164 Apr 23 14:57 .bash_profile-rw-r--r-- 1 shrek user 55 Apr 23 14:44 .bashrc-rwxrwxr-x 1 shrek user 0 Apr 14 19:29 a.out-rwxrwxr-x 1 shrek user 40 Apr 30 12:14 hello.pl-r-------- 1 shrek user 64 Apr 29 14:04 hola-rwxrw-r-- 1 shrek user 337 Apr 29 13:57 lista-rw-rw-r-- 1 shrek user 40 Apr 30 12:31 listador-rw-rw-r-- 1 shrek user 0 May 2 09:04 null-rwxrwxr-x 1 shrek user 175 Apr 30 12:30 prue.pl-rwxrwxr-x 1 shrek user 56 Apr 23 15:08 que.sh

Page 20: Tutorial del shell

Como se puede apreciar en este listado, también están el directorio actual, representado por un punto . y el directorio padre representado por dos puntos .. . Ellos también poseen permisos y atributos que son mostrados. Para ir entendiendo un poco más vamos a explicar que significan los primeros 10 dígitos. Tomemos como ejemplo el siguiente archivo

-rw-r--r-- 1 shrek user 337 Apr 29 13:57 lista

Para esclarecer un poco mas que significa cada uno de estos caracteres al inicio, utilizaremos unas tablas. Primero veamos aquellos caracteres que podrían aparecer en el primer lugar, que en el ejemplo anterior es un solo guión. Esto nos indica que es un archivo común. La tabla siguiente explica el significado del primer símbolo de acuerdo al tipo de archivo.

Tabla 1. Tipos de archivo

Contenido Significado

- Archivo común

d Directorio

c Dispositivo de caracteres (tty o impresora)

b Dispositivo de Bloque (usualmente disco rígido o CD-ROM)

l Enlace simbólico

s Socket

p Pipe

Los siguientes 9 símbolos se toman en grupos de tres y cada grupo pertenece a una clase de permisos, y se muestran a continuación

Tabla 2. Tipos de permisos

Permiso Significado

r Permiso de lectura

w Permiso de escritura

Page 21: Tutorial del shell

Permiso Significado

x Permiso de ejecución

Tabla 3. Grupos de permisos

Columnas Se aplica a Significado

2,3,4 owner Establece los permisos para el dueño del archivo

5,6,7 group Establece los permisos para el grupo del archivo

8,9,10 other Establece los permisos para los usuarios que no entran en las categorías anteriores

De esta forma podremos interpretar el listado generado a partir de ls -la de mejor manera. Como ya dijimos, el primer símbolo nos esta indicando que el archivo es un archivo común. El primer grupo de tres símbolos representa los permisos para el dueño del archivo (owner) que en este caso posee permisos de lectura, escritura y ejecución. El segundo grupo de tres símbolos representa los permisos para el grupo al cual pertenece el archivo (group), que en este caso tienen permisos de lectura y escritura. El tercer grupo de tres símbolos representa los permisos para todo el resto de los usuarios (other) en este caso es solo de lectura.

El número que sigue (1) representa el número de nombres que el archivo posee. Esto indica la cantidad de enlaces que existen a este archivo y lo veremos más adelante cuando tratemos el tema de enlaces simbólicos y duros.

A continuación esta el nombre del dueño del archivo y del grupo al cual pertenece el archivo.

El "337" representa el tamaño del archivo expresado en bytes.

Lo siguiente es la fecha y hora de modificación del archivo e inmediatamente después esta el nombre del mismo.

DependenciasLos permisos de los archivos también dependen del directorio donde estén guardados. En un ejemplo común podríamos dar el caso de un archivo que posea todos los permisos, tanto para el usuario, grupo y otros pero no se podrá acceder a él si no se cuenta con permisos de lectura y ejecución en el directorio que los contiene.

Esto funciona en el caso que se quiera restringir el acceso a un directorio determinado y a todos los archivos que este contiene. En lugar de cambiar los permisos uno por uno solo tenemos que sacarle los permisos necesarios para que se prohíba el acceso mismo al directorio y con esto no podrán ingresar para usarlos. Esto también esta dado para toda la ruta del archivo. Es decir que no solo el último directorio, el cual lo contiene,

Page 22: Tutorial del shell

tiene que tener los permisos necesarios, sino que todos los directorios que lo preceden también.

Cambiando permisosEn el el capítulo de nombre Empezando con GNU/Linux vimos la utilización del comando chmod, pero en este entraremos a explicar en mejor forma su utilización. Además trataremos el tema de otro forma de representar los permisos posibles, la representación octal, que es extremadamente útil a la hora de establecer nuevos permisos.

El comando chmod se emplea utilizando símbolos como a,u,g,o que representan a todos (a "all"), al usuario (u), al grupo (g) y a todos los demás (o). Existen símbolos para agregar (+) quitar (-) o dejar invariantes los permisos (=). Además tendrán que usarse los símbolos característicos para cada tipo de permiso. Para el permiso de lectura (r), para el permiso de escritura (w) y para el permiso de ejecución (x). Solo el dueño del archivo puede cambiarlo con él; excepción del root que también lo puede hacer. Para ejemplificar un cambio de permisos usaremos el archivo lista.

[shrek@pantano:~]$ ls -l listatotal 1-rwxrw-r-- 1 shrek user 337 Apr 29 13:57 lista[shrek@pantano:~]$ chmod a-r lista[shrek@pantano:~]$ ls -l listatotal 1--wx-w---- 1 shrek user 337 Apr 29 13:57 lista

De esta forma se le ha sacado a todos los grupos y usuarios los permisos de lectura. Algunos ejemplos más

[shrek@pantano:~]$ chmod u+r lista[shrek@pantano:~]$ ls -l listatotal 1-rwx-w---- 1 shrek user 337 Apr 29 13:57 lista[shrek@pantano:~]$ chmod o+w lista[shrek@pantano:~]$ ls -l listatotal 1-rwx-w-w-- 1 shrek user 337 Apr 29 13:57 lista[shrek@pantano:~]$ chmod og-w lista[shrek@pantano:~]$ ls -l listatotal 1-rwx------ 1 shrek user 337 Apr 29 13:57 lista

Ahora bien, esta es la forma simbólica. Pero existe una forma un poco más sistemática que es la forma de representación octal. El comando chmod permite establecer los permisos de un archivo por medio de un número octal. Comúnmente nosotros usamos para contar una representación decimal (0,1,2,3,4,5,6,7,8,9) pero en una representación octal solo se usan 8 números (0,1,2,3,4,5,6,7). Para establecer el permiso habrá que sumar los dígitos octales de acuerdo a una tabla que se dará a continuación. Dado que no se realiza acarreo, la suma será trivial.

Tabla 4. Permisos en notación octal

Page 23: Tutorial del shell

Número octal

Permiso

4000 Establece el número de identificación de usuario al ejecutarse SUID [a]

2000 Establece el número de identificación de grupo al ejecutarse SGID[a]

1000 Establece el bit adhesivo[a]

0400 Lectura por parte del dueño

0200 Escritura por parte del dueño

0100 Ejecución por parte del dueño

0040 Lectura por parte del grupo

0020 Escritura por parte del grupo

0010 Ejecución por parte del grupo

0004 Lectura por parte de los otros

0002 Escritura por parte de los otros

0001 Ejecución por parte de los otros

Notas:a. Se verá al finalizar el tema

Para dar un ejemplo de la suma que se tendrá que realizar, tomemos un archivo con los permisos expresados en forma simbólica y realicemos la conversión. Para representar -rwxr-x---

  0400      Lectura por parte del dueño+ 0200      Escritura por parte del dueño+ 0100      Ejecución por parte del dueño+ 0040      Lectura por parte del grupo+ 0010      Ejecución por parte del grupo-----------------------------------------  0750      Resultado

De esta forma si lo que quisiéramos es cambiar los permisos de un archivo, solo se tendría que efectuar la suma necesaria y establecerlo con el comando chmod. Si quisiéramos cambiar los permisos para que el dueño tenga permisos de lectura y escritura y que el grupo y otros solo tengan permisos de lectura, la sintaxis es

[shrek@pantano:~]$ chmod 0644 lista[shrek@pantano:~]$ ls -l listatotal 1-rw-r--r-- 1 shrek user 337 Apr 29 13:57 lista

Con la práctica se sabrán cuales son las sumas mas utilizadas y podrán ver que es mucho más sencillo el establecer de esta forma los permisos de archivos.

Page 24: Tutorial del shell

Cambiando grupos y usuariosLo que nos queda por ver es el caso en que se quisiera cambiar el usuario o el grupo del archivo. Para esto se usa el comando chown y su sintaxis es similar a la de chmod pero con la variante que se dan los nombres del usuario y del grupo. Si quisiéramos cambiar el nombre de usuario del archivo lista tendremos

[root@pantano:/home/shrek]# ls -l listatotal 1-rw-r--r-- 1 shrek user 337 Apr 29 13:57 lista[root@pantano:/home/shrek]# chown fiona lista[root@pantano:/home/shrek]# ls -l listatotal 1-rw-r--r-- 1 fiona user 337 Apr 29 13:57 lista

Si se quisiera cambiar también el nombre del grupo, se tendría que poner un punto entre el nombre de usuario y el grupo

[root@pantano]# ls -l listatotal 1-rw-r--r-- 1 shrek user 337 Apr 29 13:57 lista[root@pantano]# chown fiona.ventas lista[root@pantano]# ls -l listatotal 1-rw-r--r-- 1 fiona ventas 337 Apr 29 13:57 lista

Por supuesto que tanto el usuario como el grupo al que se hacen referencia tendrán que existir en el sistema, sino se producirá un error. En el caso que solo se quiera cambiar el grupo y no el usuario, se tendrá que poner un punto delante del nombre del grupo, omitiendo poner el nombre del algún usuario. O si se quiere, se podrá poner el nombre de usuario que estaba anteriormente.

[root@pantano]# ls -l listatotal 1-rw-r--r-- 1 shrek user 337 Apr 29 13:57 lista[root@pantano]# chown .ventas lista[root@pantano]# ls -l listatotal 1-rw-r--r-- 1 shrek ventas 337 Apr 29 13:57 lista

Puntos adicionalesExplicaremos algunos puntos sobre permisos que son de gran utilidad para la seguridad de nuestro sistema.

umask

Esta es la abreviatura de user file-creation mode mask o máscara del modo de creación de archivos de usuario y es un número octal de cuatro dígitos que se utilizan para fijar los permisos de los archivos recién creados. Esto puede ocasionar confusión pero en realidad es una utilidad que permite el uso del sistema por múltiples usuarios sin que peligre la privacidad. En la mayoría de los Un*x los archivos que son creados por el

Page 25: Tutorial del shell

usuario, poseen permisos 0666 que dan permiso de lectura y escritura a cualquier usuario. En relación con los programas, estos se crean con 0777 donde cualquier usuario puede leer, escribir y ejecutar el programa. Normalmente el administrador del sistema aplica una máscara al usuario en el archivo .bash_profile y esta es usada para la creación de archivos haciendo una operación simple "AND" bit por bit con el complemento del valor umask bit por bit. La función umask esta integrada al intérprete de comandos. Para ejemplificar el proceso tomemos un archivo creado por el usuario.

  0666      Modo predeterminado de creación de archivos- 0022      Umask-------------------------------------------------------  0644      Modo resultante

El modo resultante es que el dueño tiene permisos de lectura y escritura y los demás y el grupo solo de lectura.

  0666      Modo predeterminado de creación de archivos- 0077      Umask-------------------------------------------------------  0600      Modo resultante

El modo resultante es que el dueño tiene permisos de lectura y escritura y los demás y el grupo no tienen ningún permiso. Una forma de darse cuenta de la forma en que funciona el umask es tener en cuenta que el valor 2 inhabilita el permiso de escritura mientras que el valor 7 inhabilita los permisos de lectura escritura y ejecución. A continuación daremos una tabla con los valores comúnmente usados para el umask.

Tabla 5. Valores usuales de la variable umask

Umask Accesos del usuario Accesos del grupo Accesos de los otros

0000 Todos Todos Todos

0002 Todos Todos Lectura y ejecución

0007 Todos Todos Ninguno

0022 Todos Lectura y ejecución Lectura y ejecución

0027 Todos Lectura y ejecución Ninguno

0077 Todos Ninguno Ninguno

SUID y SGID

Existen ocasiones que los usuarios necesitan ejecutar algún programa que requiere de privilegios. Un ejemplo de esto es el uso del programa passwd para cambiar la contraseña. Sería un error darle a los usuarios los privilegios necesarios para que puedan ejecutar esta clase de programas ya que el usuario podría cambiarse de grupo o crear una cuenta con privilegios de root. Para que esto no suceda, se implemento en Un*x, un sistema por el cual un programa que cuente con SUID o SGID puede ser ejecutado con

Page 26: Tutorial del shell

los privilegios del dueño y/o grupo del programa. Para que quede más claro se tiene que saber que cada usuario esta identificado por el sistema con un número de identificación tanto para él, como para el grupo. Este número se denomina UID (user ID) para el caso de los usuarios y GID para el caso de los grupos. Por ejemplo, un usuario podría tener un UID 100 y un GID 500. En el caso del root, este tiene UID 0 y GID 0. Más adelante sé verá esto en mayor detalle. Lo que se efectúa con el sistema SUID es una adquisición temporal de un UID o GID distinto al propio cuando se está ejecutando el programa. Cuando un programa cambia de UID se denomina SUID (set-UID: se establece UID) y cuando cambia de GID se denomina SGID (set-GID: se establece GID) Un programa puede ser SUID y SGID al mismo tiempo. Para darse cuenta si un programa es SUID o SGID basta con hacer un listado largo con el comando ls -l y se verá que donde tendría que estar una x, que asigna permisos de ejecución, va a estar una letra s.

[shrek@pantano:~]$ ls -l /usr/bin/passwd-rwsr-sr-- 1 root bin 36068 2003-06-23 20:40 /usr/bin/passwd*/usr/bin/passwd

Bit adhesivo

En los antiguos sistemas Un*x, la memoria era algo esencial y escasa dado su costo. Para poder aprovechar más esta, se empleo una tecnología que mantenía parte de programas esenciales en el área swap de memoria para que pudieran ser usados más rápidamente dado que si se tendrían que ir a buscar al disco se adhesivo o sticky bit y estos archivos así marcados eran los que valía la pena mantener ya que esas partes del programa que se guardaban en memoria también podían ser usadas por otros.

Enlaces de archivosEn ocasiones es necesario dar a un mismo archivo distintos nombres o, para mantener la integridad de los datos, se hace necesario que un mismo archivo que va a ser modificado por varias personas pueda estar representado por un nombre distinto con distintos permisos cada uno. Dada la representación que GNU/Linux le da a los archivos es posible que dos o más nombres apunten al mismo contenido en el disco rígido. Recordemos que los archivos se representan por el número de inodo en el disco y es el único identificador que el sistema tiene del archivo. Si se quiere ver el inodo que representa un archivo basta solo con agregar el modificador -i al comando ls. Existen dos tipos de enlaces: los duros y los simbólicos.

Enlaces duros o hard links

Page 27: Tutorial del shell

Para crear enlaces entre los archivos se utiliza el comando ln. Para dar un ejemplo, si se quisiera hacer un enlace del archivo hola el comando es

[shrek@pantano:~]$ ln hola saludo

Si ahora hacemos un listado mostrando los inodos

[shrek@pantano:~]$ ls -iltotal 214438 -r-------- 2 shrek user 64 Apr 29 14:04 hola14438 -r-------- 2 shrek user 64 Apr 29 14:04 saludo

Como se ve el número de nombres que los archivos tienen ahora es 2 dado que hemos creado otro nombre que es un enlace al contenido que tenía el archivo hola en el disco. Esto puede verse dado que el primer número del listado, 14438, es el número del inodo donde comienza el contenido del archivo hola. Aunque parezca que el contenido se a duplicado, esto no es así. Ambos archivos apuntan al mismo sitio. Por esto, un archivo no se borra hasta que se haya borrado el último de sus nombres. De esta forma también podemos decir que un directorio no es más que un archivo que contiene información sobre la translación enlace a inodo. También que cada directorio tiene dos enlaces duros en él: . (un enlace apuntando a si mismo) y .. (un enlace apuntando a su directorio padre). En el directorio raíz / el enlace .. siempre apunta a /.

Enlaces simbólicos o symbolic links

A diferencia con los enlaces duros, estos enlaces solo dan otro nombre a un archivo pero no hacen un enlace al nivel de inodo. Se puede hacer una comparación con los "Accesos directos" de Windows95. La orden ln -s genera un enlace simbólico.

[shrek@pantano:~]$ ln -s hola saludos[shrek@pantano:~]$ ls -iltotal 214438 -r-------- 1 shrek user 64 Apr 29 14:04 hola14446 lrwxrwxrwx 1 shrek user 4 May 7 08:33 saludos -> hola[shrek@pantano:~]$

Como se ve, el enlace nos muestra a que archivo esta apuntando. Existen diferencias entre este tipo de enlaces y los duros como que ya no están apuntando al mismo inodo. Además los bit de permisos aparecen todos encendidos dado que no son usados. Los permisos que se utilizan son los del archivo al que se esta apuntando. Si nos fijamos bien, en la primera posición de los permisos veremos una letra l. Esto nos indica que es un enlace simbólico. Otra particularidad es que se pueden crear enlaces simbólicos de archivos que no existen; pero lo mismo no es cierto para los enlaces duros. Con los enlaces simbólicos se puede saber a que archivo están apuntando, no así con los duros. Los enlaces simbólicos son ampliamente usados para las librerías compartidas.

Tareas y procesosEn este punto tendremos que empezar a determinar que es un proceso y una tarea. Anteriormente dijimos que un programa se transformaba en proceso en el momento en

Page 28: Tutorial del shell

que este se ejecutaba y estaba en memoria. Además del nombre que el proceso recibe, que es el nombre del programa que esta corriendo, recibe también un número identificativo llamado PID (process ID, o ID de proceso). Si ejecutamos el comando ps veremos los procesos que están ejecutando en este momento con nuestro UID, es decir que estamos corriendo nosotros mismos

[shrek@pantano:~]$ ps PID TTY STAT TIME COMMAND 172 p0 S 0:00 -bash 184 p0 R 0:00 ps[shrek@pantano:~]$

Se puede ver que están corriendo dos procesos, el bash (que es el intérprete de comandos) y el proceso ps que es el que estamos usando en este momento en una terminal determinada. Como se puede ver el primer número es el PID que el sistema le asigna al proceso y en la columna COMMAND se puede ver el nombre del proceso. De ninguna manera estos son todos los procesos que se están ejecutando en el sistema. Si se quisieran ver todos los procesos tendrían que poner ps -ax con lo que obtendrían un listado con todos los procesos que se estén ejecutando. Como se puede apreciar, están ambos procesos ejecutándose al mismo tiempo, pero solo uno de ellos esta activo, el comando ps. Nos podemos dar cuenta de esto ya que en la columna STAT aparece en la línea del bash la letra S de SLEEP, ya que en ese momento el intérprete de comandos esta esperando a que el proceso ps termine. Y es aquí donde esta la diferencia entre proceso y tarea. Aunque ambos son procesos, una tarea se refiere al proceso que esta corriendo. Este calificativo solo lo da el shell del sistema cuando se utilizan los controles de tareas dado que no todos los intérpretes de comandos soportan este tipo de control.

Primer y segundo planoCualquier proceso puede estar en primer o segundo plano. Lo único a tener en cuenta es que solo un proceso estará en primer plano al mismo tiempo y es con el que estemos trabajando e interactuando en ese momento. Un proceso que este en segundo plano no recibirá ninguna señal de parte nuestra, es decir que no nos podemos comunicar con él a través, por ejemplo, del teclado. La utilidad de enviar un programa a segundo plano esta dada por el hecho de que existen tareas que no requieren de nuestro control para que se ejecuten. Por ejemplo, bajar algún archivo de Internet, compilar el kernel u otro programa. Estas son tareas que pueden ser lanzadas tranquilamente en segundo plano. Para lanzar un proceso en segundo plano, tendremos que poner a continuación del comando el símbolo &. Para ejemplificar esto usaremos el comando find y dejaremos que busque todos los archivos que existen en el disco

[shrek@pantano:~]$ find / -name "*"

Esto nos mostraría una lista bastante larga de archivos por pantalla y nos quedaríamos sin el control del intérprete de comandos mientras esta ejecutándose. Podríamos usar el dispositivo null, que si recuerdan era como un agujero negro donde todo lo que se enviaba a él desaparecía, para redirigir la salida y que no saliera por pantalla

[shrek@pantano~]$ find / -name "*" > /dev/null

Page 29: Tutorial del shell

Igualmente así no contaríamos con la atención de nuestro interprete de comandos hasta que terminara el trabajo el comando find. La forma de tener la atención del shell inmediatamente después de lanzar el proceso find es enviándolo en segundo plano

[shrek@pantano:~]$ find / -name "*" > /dev/null &[1] 192[shrek@pantano:~]$

Como se aprecia, regresó de inmediato al shell, pero antes envió un mensaje a la terminal. El [1] representa a un número de trabajo que el shell asigna a cada uno de los procesos que pasa a segundo plano. Inmediatamente después vemos el número de PID del proceso. Podremos identificar al proceso por cualquiera de los dos números mientras se encuentre en segundo plano. Para ver cuantos trabajos están ejecutándose en este momento podemos usar el comando jobs.

[shrek@pantano:~]$ jobs[1]+ Running find / -name "*" >/dev/null &[shrek@pantano:~]$

Podremos eliminar un proceso que se esta ejecutando con la ayuda del comando kill seguido bien sea del número de trabajo precedido de un signo % o del número de PID. De esta forma estamos matando al proceso pero puede darse el caso de que este tarde en desaparecer dado que tiene que limpiar el entorno, por esto muchas veces parecerá que no nos a hecho caso. En realidad el proceso esta haciendo una limpieza del sistema evitando así el mal funcionamiento del mismo y/o una inconsistencia en los datos con que trabajaba. Como ejemplo usaremos otro comando muy típico, el comando yes. Este comando enviará a la salida estándar continuamente la letra y. Sirve este comando para que en caso de que se requiera contestar afirmativamente a las peticiones de un programa pudiéremos mediante una redirección contestarle con un y a cada pregunta. Si lo ejecutáramos sin redirigir la salida a /dev/null, nos llenaría la pantalla con una columna infinita de y. Por esto lo enviaremos a segundo plano redirigiendo la salida y luego lo mataremos con el comando kill.

[shrek@pantano:~]$ yes > /dev/null &[1] 201[shrek@pantano:~]$ kill %1[shrek@pantano:~]$ jobs[1]+ Terminated yes > /dev/null &[shrek@pantano:~]$

Como podrán ver, en el momento en que se mando el comando kill, no hubo ningún mensaje. Solo después de ejecutar el comando jobs se nos informo que el trabajo número 1 había finalizado (TERMINATED). Podemos también hacer lo mismo empleando el número de PID con lo que obtendremos idénticos resultados.

[shrek@pantano:~]$ kill 201

Como parar y relanzar tareasLos procesos pueden ser suspendidos temporalmente hasta que nosotros dispongamos, para así relanzarlos y que continúen ejecutando donde se habían quedado. Esto es de

Page 30: Tutorial del shell

gran utilidad. Supongamos que se esta trabajando con el editor de texto Vi y no queremos trabajar en otra consola, solo tenemos que enviar al programa Vi a dormir un rato y tendremos el intérprete de comandos a nuestra disposición. En la mayoría de los programas, se envía una señal de terminación utilizando las teclas Ctrl-C, para poder enviar un trabajo a dormir utilizaremos otra combinación de teclas Ctrl-Z. Hay que tener en cuenta que no es lo mismo un trabajo en segundo plano que uno que es enviado a dormir. Un trabajo en segundo plano sigue ejecutándose, en cambio uno que se envía a dormir queda esperando en el lugar donde estaba hasta que sea despertado. Para ejemplificar esto, enviaremos al comando yes a segundo plano y luego lo pondremos a dormir.

[shrek@pantano:~]$ yes >/dev/null &[shrek@pantano:~]$ yes >/dev/null

Ahora presionamos Ctrl-Z

[shrek@pantano:~]$ yes >/dev/null &[shrek@pantano:~]$ yes >/dev/null[2]+ Stopped yes >/dev/null[shrek@pantano:~]$ jobs[1]- Running yes >/dev/null &[2]+ Stopped yes >/dev/null

Como pueden ver, el proceso que se envió a segundo plano todavía se esta ejecutando (Running), en cambio la que se mando dormir estaparada esperando que la relancemos (Stopped). Para ponerlo en primerplano o despertarlo a cualquiera de los dos podemos usar el signo "%"seguido del número del proceso o bien el comando fg.

[shrek@pantano:~]$ %1yes >/dev/null &

Ahora presionamos Ctrl-Z

[shrek@pantano:~]$ fg %1yes >/dev/null

Podremos enviar también un comando que esta durmiendo a que ejecute en segundo plano a través del comando bg

[shrek@pantano:~]$ jobs[1]- Stopped yes >/dev/null[shrek@pantano:~]$ bg %1[1]+ yes >/dev/null &[shrek@pantano:~]$ jobs[1]+ Running yes >/dev/null &

Cabe decir que tanto fg como bg son comandos internos del intérprete de comando. Esto es así porque es el mismo intérprete quien hace el control de tareas. Puede darse el caso de que existan intérpretes de comandos que no tengan soporte para control de tareas.

Programas de seguimiento (ps y top)

Page 31: Tutorial del shell

Los sistemas GNU/Linux cuentan varios programas para efectuar el seguimiento de los procesos que se están ejecutando en el sistema. Entre los mas usados en la interfase de texto están los programas ps y top.

ps

Sin ninguna opción dará la lista de procesos que están corriendo desde la terminal donde se ejecuto el ps

[shrek@pantano:~]$ ps PID TTY TIME CMD 9648 tty2 00:00:02 bash 9659 tty2 00:00:00 ps[shrek@pantano:~]$

Las columnas que nos quedan por explicar son TTY y TIME. TTY identifica la consola donde se esta ejecutando el proceso. En este caso es una terminal local. La columna TIME nos indica la cantidad de tiempo total que el proceso se ha estado ejecutando. Como se puede ver el tiempo es de 2 segundos. Aunque este horas el sistema encendido, el bash pasa su mayor parte del tiempo esperando que se le envie algún comando para ejecutar, mientras tanto esta esperando dormido. Puede verse en la columna STAT en que estado se encuentra el programa. Por ejemplo, que vemos que el bash en el momento de ejecutarse el comando ps esta dormido (S) y que el proceso ps esta activo (R). Si añadimos la opción l tendremos un listado largo del comando ps. En algunas versiones se usa la opción -l

[shrek@pantano:~]$ ps lF UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND4 100 9648 1 9 0 4368 1400 11b1d0 S tty2 0:01 -bash4 100 9660 9648 17 0 2676 732 - R tty2 0:00 ps l

Dentro de esta información esta la columna del UID que identifica el dueño del proceso. El PID del proceso y también el PPID que es el PID del proceso padre. Podemos apreciar que el padre del comando ps l es el -bash. NI viene de nice y es un nivel que se otorga a un proceso para requerir cierto privilegio. En este caso tiene uno muy bajo por ende un proceso que tenga un valor mayor tendrá más tiempo de procesador para trabajar. SIZE es el tamaño que tiene el proceso. RSS es la tamaño del proceso que se encuentra residente en la memoria. WCHAN es el nombre de la función del kernel donde el proceso esta durmiendo. Esta expresado en forma hexadecimal.

Otra forma en la que podemos ver el padre de cada proceso es a través del modificador f.

[shrek@pantano:~]$ ps f PID TTY STAT TIME COMMAND 9648 tty2 S 0:02 -bash 9660 tty2 R 0:00 \_ps f[shrek@pantano~]$

Aquí se puede ver que el comando ps f depende del -bash.

top

Page 32: Tutorial del shell

Ahora bien, el comando ps nos muestra una radiografía de los procesos en el momento, pero no nos muestra los cambios que se van teniendo. Para esto contamos con el comando top. El mismo muestra en tiempo real la situación de los procesos que se están ejecutando en el sistema, ordenados por defecto según el porcentaje la CPU que estén usando. Al ejecutarlo se podrá ver otra información adicional, como la cantidad de usuarios que están en el sistema, cuantos procesos están corriendo y de estos cuantos estas activos, cuantos durmiendo, cuantos en proceso de terminar (ZOMBIE) y cuantos finalizados. Además se podrá ver la cantidad e memoria física total, la cantidad usada y la cantidad libre; así como también se podrá obtener la misma información de la memoria swap.

Lo más importante es que esta información de ira actualizando automáticamente cada tanto tiempo, por defecto 5 segundos, y que podremos ir alterando lo que va mostrando. Por ejemplo podemos hacer que ordene los procesos de acuerdo a la cantidad de memoria que esta usando con solo presionar la tecla M. U ordenarlos de acuerdo al tiempo que llevan corriendo. Otra utilidad es que podríamos matar algún proceso con solo presionar la tecla k y luego darle el número de PID.

El listado que nos mostrará contendrá el número de PID, el usuario que lo está ejecutando, la prioridad del proceso (PRI), el valor nice (NI), el tamaño del proceso (SIZE), el tamaño total del proceso junto con los datos que maneja (RSS), el tamaño usado por el proceso en la memoria (SHARE), el estado del proceso(STAT), el tamaño de las librerías del proceso (LIB), el porcentaje de CPU ( %CPU) y de memoria (%MEM) así como también el tiempo de ejecución (TIME) y el nombre del proceso (COMMAND).

Escritura de scripts de shellHemos llegado a un punto donde podemos realizar tareas más complejas a partir de los comandos aprendidos y es aquí donde radica el poder del intérprete de comandos bash. Como veremos a continuación, el intérprete de comandos es un poderoso lenguaje para realizar script que permitan unir varios comandos para realizar una tarea un poco más compleja (y es el este el poder principal de todo Un*x). El único requisito es tener nociones básicas de programación para poder sacar todo el provecho posible de esta característica del intérprete de comandos. En todo caso, con un poco de práctica y un buen sentido de la lógica se podrán hacer también script poderosos para desarrollar las tareas que requerimos.

Deberemos saber también que con la ayuda solamente de la conjunción de comandos no podremos hacer script verdaderamente interesantes. Por esto se incorporan las construcciones de shell. Estas son las construcciones while, for-in, if-then-fi y case-esac. Existen muchas más pero estas serán las más útiles para nosotros en estos momentos. Para mayor información sobre otro tipo de construcciones seria mejor revisar las páginas de manual del intérprete de comandos bash (man bash).

Empezaremos viendo un uso sencillo de la construcción for-in que tiene la siguiente sintaxis

for var in word1 word2

Page 33: Tutorial del shell

do commandos done

Para poder usar esto, podríamos realizar una lista de directorios que querramos nosotros de una sola vez

for dir in /bin /etc /lib do ls -R $dir done

Esto hará un listado recursivo 3 veces. La primera vez que pase por el ciclo, la variable $dir tomará el valor /bin, la segunda será /etc y la tercera /lib.

Podríamos prescindir del par do-done con el uso de llaves ({})

for dir in /bin /etc /lib { ls -R $dir }

Ya hemos visto anteriormente la idea de argumentos en la utilización de comandos y programas; pero deberemos ver como se realiza la codificación de un script para tomar estos argumentos. Como antes dijimos, los argumentos eran pasados a los programas para que estos lo utilizaran. En la construcción de script veremos lo que se llaman variables posicionales cuyo valor corresponde a la posición del argumento luego del nombre del script. Supongamos que tenemos un script que toma 3 argumentos. El primero será el nombre de un directorio, el segundo el nombre de un archivo y el tercero es una palabra a buscar. Este script buscará en todos los archivos del directorio, cuyo nombre incluya el nombre de archivo que le pasamos como argumento, la palabra que también le estamos pasando. El script se llamara miscript y estará compuesto del siguiente código

ls $1 | grep $2 | while read ARCHIVO do grep $3 ${1}/${ARCHIVO} done

La sintaxis será

miscript [directorio] [nombre_archivo] [palabra]

Aquí tenemos varias cosas para ver. Primero que nada, el uso de las variables posicionales. Como se podrá apreciar el número de la variable, que esta precedido por un signo $, indica la posición del argumento cuando el script es llamado. Solamente se podrán usar 9 variables de este tipo sin tener que emplear un pequeño truco de corrimiento que veremos luego, dado que el 0 representa al nombre del script mismo. Es decir que en este caso la variable posicional $0 valdrá "miscript". Como se puede ver se han utilizado canalizaciones para poner más de un comando junto. Al final de la construcción se esta usando una construcción while. Esta se usa para repetir un ciclo mientras una expresión sea cierta.

Page 34: Tutorial del shell

while ($VARIABLE=valor) do commandos done

En este caso esta siendo usada al final de una canalización con la instrucción read ARCHIVO. Es decir, mientras pueda leer el contenido de la variable $ARCHIVO, continuar. Esta variable $ARCHIVO contiene el resultado de lo que arrojo la canalización del listado con la salvedad de que tenia que contener la palabra que le enviamos como argumento, es así que solo se imprimirán las líneas en las que coincida la palabra a buscar de los archivos que cumplan con los requisitos.

Otra cosa a tener en cuenta es una nueva construcción en este script, ${1}/${ARCHIVO}. Al encerrar un nombre de variable dentro de llaves podemos combinarlas. En este caso forman el nombre del directorio (${1}) y añadimos una / como separador del directorio, y seguido e nombre del archivo donde se aplicara el comando grep con la palabra a buscar $3.

Podríamos hacer que este script sea un poco más documentado. Para esto podríamos asignar las variables posicionales a otras variables para que se pueda entender mejor su uso.

DIRECTORIO=$1 ARCHIVO_BUS=$2 PALABRA=$3

ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO do grep $PALABRA ${DIRECTRIO}/${ARCHIVO} done

El número de las variables posicionales que pueden usarse en un script, como antes dijimos, se encuentra restringido a 10. ¿Qué pasaría si tenemos más de 9 argumentos? Es aquí donde tenemos que usar la instrucción shift. Esta instrucción mueve los argumentos hacia abajo en la lista de parámetros posicionales. De esta manera podríamos tener una construcción con esta distribución de variables

DIRECTORIO=$1 shift ARCHIVO_BUS=$1

De esta manera podríamos asignar el valor de la primer variable posicional a la variable DIRECTORIO y luego el siguiente argumento que habíamos dado se tomara otra vez con el nombre de $1. Esto solo tiene sentido si asignamos las variables posicionales a otra variable. Si tuviéramos 10 argumentos, el décimo no estaría disponible. Sin embargo, una vez que hacemos el que las variables se corran de posición este se convertirá en el noveno y se accederá por la variable posicional $9. Existe una forma también de pasar como argumento a la instrucción shift el número de posiciones que queremos correr. Por lo cual podemos usar

shift 9

Page 35: Tutorial del shell

y así se lograra que el décimo argumento sea el parámetro posicional 1.

Lo que ocurre con los anteriores 9 argumentos es que desaparecen si no se los asigno a una variable anteriormente. Podremos cambiar usar un nuevo parámetro que podrá contener mas de un parámetro pasado al script. Este se denomina $* y contendrá el resto de los argumentos que se pasen al script luego de que se haya realizado un corrimiento determinado. Por ejemplo, si quisiera buscar una frase en lugar de una única palabra el script podría ser

DIRECTORIO=$1 ARCHIVO_BUS=$2 shift 2 PALABRAS=$*

ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO do grep "$PALABRAS" ${DIRECTRIO}/${ARCHIVO} done

Lo que aquí cambio es que luego de haber asignado a variables los parámetros posicionales 1 y 2 las variables fueron desplazadas dos veces, eliminando los dos primeros argumentos. Luego asignamos los argumentos restantes a la variable PALABRAS. Para que sea tomado como una cadena, se lo encerró entre comillas para ser pasado al comando grep, si no lo hiciéramos el bash vería nuestra entrada como argumentos individuales para pasar al grep.

Otro parámetro que es de utilidad es el $# que lleva la cuenta de la cantidad de argumentos pasados al script. De esta forma podríamos realizar un script que identificara si se le están pasando la cantidad de parámetros que realmente necesita y anunciar el error si faltaran estos. Para ello utilizaremos la construcción if-then-fi que es muy parecida a la while-do-done, en donde el par if-fi marca el final de un bloque. La diferencia entre estas construcciones es que el if solo evaluara una vez la condición. La sintaxis es la siguiente

if [ condición ] then hacer_algo fi

Las condiciones que puede usarse se encuentran en las man page test (man test). Nosotros usaremos una simple condición para contar argumentos, pero pueden ser usadas distintas condiciones como nombres de archivos, permisos, si son o no directorios, etc. Para saber si la cantidad de argumentos que se nos a pasado en el script es correcta, utilizaremos una opción aritmética que compare la cantidad de argumentos pasados ($#) con un número que nosotros estipularemos, en este caso 3. Pueden usarse diferentes opciones con el formato arg1 OP arg2, donde OP será alguno de los siguientes

  -eq     es igual  -ne     no es igual  -lt     menor que  -le     menor que o igual

Page 36: Tutorial del shell

  -gt     mayor que  -ge     mayor que o igual

Se usará en este caso el -ge (mayor o igual que) dado que si la cantidad de argumentos que siguen al segundo es mayor la tomaremos como una frase a buscar y si es igual como una palabra. Lo único que haremos en caso de que la cantidad de argumentos sea menor, será informar de esto y de la forma de usar el script.

DIRECTORIO=$1 ARCHIVO_BUS=$2 shift 2 PALABRAS=$*

if [ $# -ge 3 ] then ls $DIRECTORIO | grep $ARCHIVO_BUS | while read ARCHIVO do grep "$PALABRAS" ${DIRECTRIO}/${ARCHIVO} done else echo "Número de argumentos insuficientes" echo "Use: $0 <directorio> <archivo_a_buscar> <palabras>" fi

Otra utilidad para del if, es la posibilidad de realizar lo que se denomina if anidados. De esta forma podríamos tener varias capas de if-then-else-fi. Como ejemplo podría ser esta una construcción válida

if [ $condicion1 = "true" ] then if [ $condicion2 = "true" ] then if [ $condicion3 = "true" ] then echo "las condiciones 1, 2 y 3 son ciertas" else echo "solo son ciertas las condiciones 1 y 2" fi else echo "condición 1 es cierta, pero no la 2" fi else echo "la condición 1 no es cierta" fi

Podríamos también hacer que una sola variable tome diferente valores e interactuar con ella para ver si se cumple la condición buscada. De esta forma podríamos por ejemplo hacer un menú de usuario con distintas alternativas. Pero esta forma es útil solo para pocas condiciones. ¿Que pasaría si tuviéramos muchas condiciones mas que agregar? Se nos haría por demás de complicado seguir el esquema armado y sería demasiado código para lo que se trata de realizar. Es aquí es donde se necesita la estructura case-esac. Como se podrá ver, al igual que en el if-fi aquí el inverso de case (esac) cierra la construcción. Veamos un ejemplo de una construcción con case

read ELECCION case $ELECCION in

Page 37: Tutorial del shell

a) programa1;; b) programa2;; c) programa3;; *) echo "No eligió ninguna opción valida";; esac

Hay que tener en cuenta algunas cosas respecto a este tipo de construcción. Por ejemplo el mandato que le damos al principio read indica al bash que tiene que leer lo que se ingrese a continuación y lo guarde en una variable que se llamara ELECCION. Esto también será útil para el uso de otras construcciones ya que el read no es propiedad exclusiva de la construcción esac, sino que pertenece al mismo bash. Como se ve, se le indica que si el valor que la variable contiene es igual a alguna de las mostradas debajo se ejecute determinado programa. (case $ELECCION in). La elección se debe terminar con un paréntesis ")" para que se cierre las posibilidades. Podríamos poner más posibilidades para cada elección; lo único que hay que recordar es cerrar con un paréntesis. El punto y coma nos marca el final de un bloque, por lo que podríamos agregar otro comando y se cerrara con punto y coma doble al último. El asterisco del final nos indica que se hará en caso de que no coincida lo ingresado con ninguna de las posibilidades. Un ejemplo, sería que nuestra construcción reconozca mayúsculas y minúsculas y además ejecute más de un comando por bloque.

read ELECCION case $ELECCION in a|A) programa1 programa2 programa3;; b|B) programa4 programa5;; c|C) programa3;; *) echo "No eligió ninguna opción valida";; esac

También se podría haber incluído un rango de posibilidades

echo "Ingrese un caracter: " read ELECCION case $ELECCION in [1-9]) echo "Usted ingreso un número";; [a-z]) echo "Usted ingreso una letra minúscula";; [A-Z]) echo "Usted ingreso una letra mayúscula";; esac

Hay que recordar que todos estos script podrán estar en un archivo, pero para que se ejecuten se le deberá primero dar los permisos pertinentes. Un par de cosas a tener en cuenta para la construcción de script son la forma en que se quiere que ejecute éste y la captura de teclas. Al ejecutarse un script de shell, se estará creando un bash hijo que lo ejecutará. Dado que las variables y funciones pertenecen al intérprete de comandos que las creó, al finalizar el script el proceso hijo del bash morirá y con el todos los seteos de variables y funciones. Por esto, si se quisiera que los cambios de las variables y las funciones que se definieron permanezcan para ser utilizables una vez que el script haya

Page 38: Tutorial del shell

terminado, se deberá comenzar a ejecutar el script con un punto "." seguido por un espacio antes del nombre de éste. De esta forma el proceso del intérprete de comando actual sera quien ejecute el script con lo que se conservaran todas las variables y funciones.

[shrek@pantano:~]$ . miscript

Un script puede dejar cosas sueltas antes de terminar si éste es finalizado bruscamente enviándole una señal de finalización [1] ya sea con la combinación de teclas Ctrl-C o con un kill -15. Para esto se deberán capturar estas señales para poder hacer una limpieza, ya se de variables o archivos, antes de finalizar. La forma de hacerlo es con el uso del comando trap; de esta forma se capturará la señal que se le envíe al script y se podrá ya sea ignorar la misma o ejecutar otro comando de limpieza. Para demostrar esto haremos un pequeño script que servirá de menú. La llamada al script del menú podría estar en el archivo .profile del usuario o en el .bash_profile. Si lo que no queremos es que el usuario salga del script con usando la combinación de teclas Ctrl-C, lo que haremos es capturar la señal y hacer que se ejecute nuevamente el script que se llamará simplemente menu.

trap './menu' 2 while : do echo 'a) Listado de archivos' echo 'b) Día y hora actual' echo 'c) Mes actual' echo 'Seleccione: ' read ELECCION case $ELECCION in a|A) ls;; b|B) date;; c|C) cal;; *) echo "No eligió ninguna opción valida";; esac done

Como se ve al principio del script se utiliza el comando trap que al captura la señal 2 (SIGINT) que produce el Ctrl-C relanza el script. Al final del script se ve que se llama nuevamente dado que al ejecutarse el comando de cada elección se quiere que el menú siga funcionando. Practicar con estas construcciones será de gran ayuda para entender el proceso de construcción de script y los preparara para script más complejos usando otros interpretes como el sed, awk y el lenguaje perl. Para mayor información respecto a la construcción de script, remitirse a las páginas de manual del intérprete de comandos, en este caso man bash.

Notas

[1] Para saber el nombre y número de señales teclear kill -l

Programas de edición de consola

Page 39: Tutorial del shell

Por más que queramos convencernos de que el usar el comando cat y redirigirlo a un archivo nos va a ser suficiente para poder trabajar con texto no podremos seguir engañándonos por mucho tiempo. Si existe algo que sé a apreciado mucho en lo referente a la informática tanto en el hogar como en la oficina, es la manera más sencilla que se tiene de editar textos y trabajar con ellos de una forma eficiente, produciendo así también una retroalimentación para que estos entornos vayan mejorando. Existen conjuntos de aplicaciones como el OpenOffice.org auspiciado por de Sun o Abiword que nos permiten hacer el trabajo de edición de texto mas fácilmente. Pero también existe toda una gama de editores de textos, en línea y fuera de línea, que permiten hacer el trabajo en ocasiones cuando no se cuenta con ningún otro editor. En este capítulo trataremos de proporcionar una guía sobre las principales herramientas para manipular archivos de texto. El cómo los usemos y cual de ellos adoptemos dependerán de las circunstancias y los gustos del usuario. Los dos primeros editores son el Vi "Visual Editor" y el Emacs con los cuales podremos interactuar para hacer la edición del contenido de un archivo. Luego veremos a un editor de texto fuera de línea y también llamado editor de flujo, el Sed. Por último trataremos de ver las características de un lenguaje de programación que hace mucho mas que editar texto, el Awk.

Edición de textos en modo interactivo¿Porque es importante el uso de editores de consola?Muy bien, se cuenta ya con poderosos programas de edición como los mencionados anteriormente y uno se siente tan cómodo como cuando trabajaba en otro tipo de entorno de ventanas, pero ¿Que ocurre cuando queremos hacer funcionar ese monstruo consumidor de recursos en un 486 DX2 con 8 MB?. No puede funcionar de ninguna manera, ni siquiera el entorno XWindow podría hacerlo de un modo que nos facilite las tareas. Otro ejemplo, salimos de nuestra maquina perfectamente equipada y vamos a configurar otra máquina no tan bien equipada, no podemos dejar de hacer el trabajo porque no tiene interfaz gráfica o no tiene el OpenOffice. Por esto es importante el saber usar este tipo de editores, ya que estarán en cualquier sistema GNU/Linux, por lo menos el Vi, y que necesitan de muy pocos recursos o muchos menos que X para funcionar.

El entender este tipo de programas nos abren las puertas para poder configurar y trabajar con cualquier computadora que posea un sistema tipo Un*x ya que han sido portados a tanto Vi como Emacs a la mayoría de las plataformas dada su funcionalidad. Si se les presenta caso que alguna vez se tenga que editar algún archivo a través Internet en una máquina remota agradecerán por mucho la capacidad del editor Vi y su velocidad, dado que es poco el contenido que tendrá que pasarse por la conexión y por ende se tendrá mucha más soltura a la hora de trabajar con un archivo, amen de los bajos tiempos de respuesta que el editor tendrá. Por supuesto que se tendrá que tener en cuenta el gusto personal por cada uno de los editores que pasaremos a explicar, pero de seguro se contará con la suficiente información para poder hacer una elección de acuerdo a las conveniencias de cada usuario.

Para poder ejemplificar algunos de los puntos fuertes de cada uno de estos editores, podríamos decir que Vi es el editor de textos garantizado en todos los equipos con

Page 40: Tutorial del shell

GNU/Linux y Un*x. Aunque no es él más fácil de usar, a esta altura se tendrá la experiencia suficiente para armarse de paciencia y obtener el máximo beneficio de él.

El editor de textos Emacs es pesado pero muy poderoso. Posee hasta un dialecto del lenguaje de programación LISP además de diversas extensiones avanzadas como el Eliza, que es un programa para tareas de Inteligencia Artificial.

El editor ViAl verlo por primera vez la gente tiene recuerdos de los primeros editores de textos de DOS, toscos y faltos de muchas características, pero una vez que se a aprendido a usarlo se encuentra uno ubicado en el sector de la gente que piensa que en verdad es un programa mágico.

No es un programa muy difícil de usar, aunque parezca lo contrario en principio, es solo que el aprendizaje inicial suele costar mucho dado que no se contaran con menues descolgables o clic de mouse para ejecutar una función del programa y ni siquiera esta en colores en muchos casos. Para ir viendo algunas características que el Vi posee y a modo de que vayan entrando en el sector de gentes antes mencionado, veremos características en este editor que lo ponen como uno de los más completos. Pero tendremos que ver algunos conceptos fundamentales antes de poder hacer esto. Mientras se este usando el editor se estará en uno de tres posibles modos de operación. Estos modos son:

1. Modo Comando2. Modo de Inserción3. Modo de Ultima Línea

Vi puede ser iniciado tanto llamándolo sin argumentos, con lo que se tendrá que establecer un nombre a la hora de salir del programa, o con un nombre de archivo, con lo cual si el archivo existe lo abrirá y si no existe lo creará. La sintaxis es la siguiente [shrek@pantano:~]$ vi <archivo>Donde <archivo> es el nombre del archivo a editar o crear. En caso que no se ponga ningún archivo, se preguntara el nombre de este cuando queramos guardar o cuando salgamos del programa. Al iniciarse, lo hará en modo comando por lo que no se podrá ingresar texto directamente. Para pasar al modo de inserción, se cuenta con un comando "i" (INSERT) o "a" (ADD). En ese momento nos encontraremos con la posibilidad de escribir el contenido del archivo a crear o a editar. Para volver al modo de comandos vasta solo con oprimir la tecla ESC.

El modo última línea sirve para proporcionar al Vi ciertos comandos extendidos que aparecerán en la última línea de la pantalla, de aquí su nombre. Por ejemplo, supongamos que quisiéramos salir del archivo que estamos editando sin tener que grabar, para ello presionando dos puntos (:) y luego "q!" el Vi saldrá sin guardar ningún cambio. Por supuesto que en el modo última línea se tiene que presionar la tecla Enter después del comando.

Page 41: Tutorial del shell

Para entender un poco estos conceptos trataremos de ejemplificar un poco el proceso de edición, mostrando como se editaría un archivo nuevo. Para esto crearemos un archivo llamado prueba:

[shrek@pantano:~]$ vi prueba

Dado que el archivo no existe, este se creará, lo que se nos indica al final de la pantalla con la línea como se ve a continuación

Lo que mostrara el editor Vi al comenzar es una pantalla donde en la primera columna se verán repetidos símbolos de tilde (~). Esto indica que donde está el primero de estos tildes finaliza el archivo y que luego no hay nada más.

En estos momentos estamos en modo de comandos. Para comenzar a trabajar necesitaremos ingresar al modo de inserción para así comenzar a escribir. Esto lo realizamos con el comando i (insert). A la hora de tener que agregar contenido podrá también pasar al modo de inserción a través del comando a (add). La diferencia con el comando i es que con el comando a se comenzará a escribir después del cursor mientras que con el comando i esto se hará antes del cursor. Como en otro editores de textos se podrá seguir escribiendo líneas sucesivas solo con oprimir la tecla Enter la que generara un EOL (End of line). Si existiese un error lo podremos corregir primero borrando el carácter con error (tecla x sobre el carácter a borrar en modo comando) y luego insertando el correcto (i). Pero podremos por ejemplo reemplazar directamente el carácter con error directamente con el comando (r) (replace).

Page 42: Tutorial del shell

Pero que pasa si existiesen varios caracteres seguidos que quisiéramos corregir. Pondremos entonces el comando R (replace all) lo que nos permitirá seguir reemplazando caracteres hasta presionar la tecla Esc para volver al modo comando.

Para moverse por el texto puede hacerse directamente con las teclas de cursor que nos llevará al lugar donde está el problema.

Para reemplazar esta palabra lo que hicimos fue posicionarnos con el cursor encima de la letra "á" y en modo comando presionar la tecla i, y así insertamos la letra "í". Si lo

Page 43: Tutorial del shell

que quisiéramos es comenzar a escribir una nueva línea en blanco, lo lograremos presionando la tecla o en modo comando.

Ya dijimos que para borrar algún carácter en especial tendremos que posicionar el cursor encima de este y, en modo comando, presionar la tecla x. Pero si lo quisiéramos es borrar una palabra de 5 letras, lo que haremos es presionar x 5 veces. Esto no es del todo practico. Si queremos borrar una palabra completa bastará con posicionarnos con el cursor en ella y presionar dw (delete word) en modo comando con lo que la palabra será borrada. Si lo que queremos es borrar una línea completa tendremos que presionar dd en modo comando encima de la línea a borrar.

Page 44: Tutorial del shell

Las modificaciones que le podemos hacer al texto las vimos anteriormente con el comando R y r, pero también podremos hacer otro tipo de modificación como el cambiar el texto a mayúscula. Para esto contamos con el comando ~[1], el cual alterna entre mayúsculas y minúsculas.

Para poder mover el cursor de un lado a otro también se cuenta con 4 teclas que pueden resultar un poco más cómodas al este en modo comando. Estas son h, j, k y l que nos permitirán mover el cursor a la izquierda, abajo, arriba y a la derecha. Con la tecla w el

Page 45: Tutorial del shell

cursor se moverá al comienzo de cada palabra y con la tecla b se irá al comienzo de la palabra anterior.

Con la orden 0 nos podremos mover al comienzo de la línea actual y con el $ al final de la línea actual.

En ocasiones el texto que tenemos que editar es por demás de extenso y por ello tendremos que encontrar un método mejor para ir moviéndonos a través de este. Dado que no contamos con una barra de desplazamiento que nos permita poder movernos por el documento tendremos que usar los métodos convencionales de conjunto de comandos. Para ello tenemos que pulsando Ctrl-F se avanzara el cursor una pantalla hacia delante y con Ctrl-B lo llevaremos una pantalla hacia atrás. Si lo que queremos es llegar al final del documento tenemos el comando G y si lo que en realidad se necesitaba es el llegar a una línea determinada tendremos que anteponer al comando G el número de la línea a la que queremos ir. Por ejemplo si quisiéramos llegar a la línea 25 del documento teclearíamos, por supuesto en modo comando, 25G y el cursor parpadeara debajo de la primer letra de esa línea.

Muy bien, el trabajo esta hecho y se necesita ahora guardarlo. Para esto tendremos que darle una orden desde el modo última línea. Para ello primero ingresaremos ":" los dos puntos, que nos llevara al modo última línea y seguido esto teclearemos la letra w (write) y presionaremos Enter (:w), con esto el documento será guardado, y en caso de que no hallásemos dado un nombre todavía, es decir que hayamos arrancado el vi sin ningún nombre como parámetro, se guardara en un archivo temporal el cual nos indicara. Para darle un nombre, lo tendremos que indicar inmediatamente después de haber puesto los dos puntos y la letra w. (:w archivo), de esta forma ahora cada vez que se ingrese el comando "w" desde el modo última línea, se guardara el documento en el nombre de archivo que indicamos. Si lo que quisiéramos es guardar y salir la forma de indicárselo es a través del comando "qw" (:qw) que guardara el archivo y saldrá del

Page 46: Tutorial del shell

programa. Claro esta que si no indicamos un nombre se tendrá que proceder de igual forma que el caso anterior. Podremos hacer lo mismo desde el modo comando presionando dos veces la tecla Z. Para salir sin guardar existen dos formas de acuerdo a lo que se haya hecho. Si no se modifico el documento, bastara que desde el modo ultimo línea se presione la tecla q seguido de Enter.(:q) Si se modifico el documento, entonces deberemos forzar la salida con ayuda del símbolo ! de esta forma (:q!). Lo formidable que tiene este editor de texto en modo consola que otros no tienen, es la posibilidad de editar ficheros múltiples. Esto permite que podamos editar algún otro archivo con solo indicárselo. De esta forma será más rápido que salir del "vi" y arrancarlo con otro nombre de archivo como parámetro. Para esto bastara solo con ingresar :e seguido del nombre del archivo a editar.

Si el archivo que actualmente estamos editando no a sido guardado nos lo indicara para que no perdamos los cambios. Si queremos en realidad incluir el contenido de otro archivo, tenemos la orden :r. La forma de emplearlo es (:r archivo) y de esta forma todo el contenido de ese archivo será incluido en el documento que estamos editando actualmente.

Existe una utilidad muy interesante del vi que nos permite ejecutar comandos del bash directamente y que los resultados se incorporen al texto que estamos editando. Con la misma orden :r! y seguido el comando que queremos ejecutar, el comando será ejecutado y el resultado será incluido en el documento.

Claro esta que se puede salir del interprete de comandos y ejecutar la orden directamente y una vez finalizada volver al editor vi. Esto se logra con el símbolo "!". Por ejemplo: :! ls -l . También podremos salir temporalmente del vi regresar al interprete de comandos. Para esto deberemos indicárselo con el comando :shell. Luego una vez que terminemos de usar el interprete de comandos, podremos poner exit y regresaremos al vi.

Page 47: Tutorial del shell

Una utilidad interesante es la de repetir el último comando que se ejecutó. Para esto tenemos el comando punto "." que desde el modo comando nos permitirá repetir cualquier comando que hayamos ejecutado anteriormente. Por ejemplo si lo que hicimos antes fue el borrar una palabra con el comando "dw", si presionamos el punto "." será igual que hubiésemos tecleado "dw" otra vez. Esto funciona con la mayoría de los comando que podamos ejecutar desde el modo comando.

Si quisiéramos buscar una palabra en especial dentro del texto, bastara solo con presionar la el comando "/" lo que nos ubicará en la última línea para que ingresemos la cadena de texto a encontrar. Vi comenzara a buscar desde el punto donde se encuentre el cursor hasta el final del texto y cada vez que encuentra una coincidencia nos lo indicara poniendo el cursor debajo de esta. Si queremos seguir buscando, bastara con presionar la tecla n (next) para que encuentre la próxima coincidencia.

Muchas veces tendremos que reemplazar sucesivamente una palabra en el texto y tendremos que buscarlo una por una y reemplazarlo a mano. Vi cuenta con un método que puede ser útil usando la diagonal "/" y luego la cadena que estamos buscado. Una vez que la encontramos solo tendremos que presionar "cw" lo que nos permitirá corregir la cadena, reemplazamos la cadena que encontramos con la que queremos y luego repetimos la búsqueda presionando (ESC) que nos pondrá en modo comando y presionando la tecla "n" que nos llevara a la próxima coincidencia. En este punto en lugar de repetir lo anterior solo bastara con presionar el comando "." que repetirá el reemplazo efectuado anteriormente y así presionando "n" y "." sucesivamente podremos reemplazar todas las coincidencias.

Claro esta que no es esto muy útil si se quiere reemplazar 100 coincidencias por lo que podremos hacerlo de una sola vez indicando en cuantas líneas se podrá encontrar esta cadena. Para ello se ingresan los ":" dos puntos seguido de la primera de las líneas en la que tenemos la palabra a cambiar, seguido una coma y luego la ultima línea a cambiar. Luego pondremos el comando a usar "s" para sustituir, una diagonal, la palabra a buscar otra diagonal y la palabra con la que será reemplazada.

:200s/shrek/SHREK

Claro que esto solo cambiara la primer aparición en la línea, si existiera otra en la misma línea seria ignorada. Para que el alcance sea total se deberá agregar el comando g (global) al final del comando.

:1,200s/shrek/SHREK/g

Ahora bien si se quiere que vi nos pregunte antes de cambiar se deberá agregar el comando "c" al final, que nos pregunte si se quiere realizar el cambio antes de cada una de las coincidencias

:1,200s/shrek/SHREK/gc

Para todo esto deberemos saber cuantas líneas tiene el documento, lo que podemos hacer es indicarle que lo haga desde donde nosotros queramos hasta el final del documento con la ayuda del símbolo "$".

Page 48: Tutorial del shell

:1,$s/sebas/SEBAS/gc

Si se quiere realizar en todo el documento, podremos directamente indicarlo con el símbolo "%" que es igual a "1,$".

:%s/shrek/SHREK/gc

Por supuesto que los patrones de búsqueda que usamos podrán ser expresiones regulares, que facilitaran mucho el trabajo. Si quisiéramos que se reemplace no importa si esta escrito en mayúscula o minúscula se podrá poner algo como esto

:%s/[Ss][Hh][Rr][Ee][Kk]/fiona/gc

Este uso de las expresiones regulares también puede incluir el uso de metacaracteres como el "*" para indicar cualquier cantidad de caracteres anterior o "." para cualquier carácter individual

:%s/*[Rr].[Ss]/fiona/gc

Pero si se a hecho algo mal, no preocuparse ya que Vi cuenta con un comando de "undo" el cual por supuesto se activa con el comando "u". Existen muchísimos temas que se han dejado de ver aquí, por lo que se invita al lector a buscar en la documentación del vi que lo guiara a toda la magia que este editor tiene para brindar.

El editor emacsEn cuanto a poder se refiere, Emacs gana por varios cuerpos a sus competidores. Este desarrollo totalmente GNU ha sabido cubrir el terreno de la edición de textos de alto nivel en los sistemas UNIX por muchos años, y sigue siendo un ejemplo del poder real que se puede obtener de este tipo de sistemas. Por supuesto, es un editor más poderoso que el pequeño "vi" y por ende la curva de aprendizaje es mucho mayor. Pero si lo que se quiere es tener mas que un simple editor de textos y acercarse a lo que una suite de aplicaciones puede dar, Emacs es el lugar donde se tiene que buscar. Y es así de simple, no solo nos encontraremos con un fabuloso editor de textos, sino que tendremos una completa suite de aplicaciones de uso común, tales como edición, recepción y envió de mails, programación en C, edición de HTML y SGML, programación en de macros en lenguaje LISP, corrección ortográfica en varios idiomas y muchas características más. Existe una diferencia en la forma de trabajar con respecto a vi, en lugar de tener que cambiar de modo para poder trabajar con una u otra función, modo comando, modo última línea y demás, emacs responde de acuerdo a la función que la combinación de teclas presionada tenga. Este es el mismo comportamiento que poseen otros editores de textos como el OpenOffice o el Word y por lo tanto se tendrán que saber las combinaciones posibles para poder trabajar cómodamente.

Al arrancar emacs puede hacerlo de dos formas distintas dependiendo en el ambiente donde se este trabajando. Si se esta trabajando en modo texto, emacs arrancara con lo que se denomina entorno de pantalla completa, es decir se llena toda la pantalla.Si se ejecuta emacs en el entorno X, este lo entenderá y arrancará la versión de X en lugar de la de texto.

Page 49: Tutorial del shell

Versión X de Emacs: Por supuesto que si se quiere ejecutar la versión de texto en un entorno como X uno puede hacerlo, para ello basta con ejecutar emacs con los modificadores -nw (NO WINDOWS).

[shrek@pantano:~]$ emacs -nw

Ahora bien, si lo ejecutamos con un nombre de archivo como argumento resultara de la misma forma que con el editor vi, si el archivo existe se abrirá para ser editado, si no se creará uno nuevo. En el entorno gráfico se podrá contar con una serie de menús desplegables al igual que otros programas de X y así será más fácil llegar a las opciones, y por ello solo trataremos de ver las opciones que se tienen, no todas, para ser usadas en un entorno de texto y luego podrán ser empleadas ya conociendo su funcionamiento en cualquiera de los dos entornos.

Para poder usar los menú en modo texto, si presionamos la tecla F10 tendremos bajo la pantalla de edición los nombres de cada uno de los menús y al elegirlos y presionar Enter entraremos en su contenido y en las diversas ordenes que tienen. Con F1 entraremos al modo de ayuda donde tendremos una reseña de los comandos de Emcas Ventana de ayuda Para salir de este cuadro bastara con presionar 3 veces la tecla Esc.

Al comenzar, emacs esta en lo que se denomina modo "fundamental" que es uno de los modos en los que puede encontrarse dependiendo del tipo de trabajo que se esta haciendo, determinando esto el comportamiento básico del programa. Los otros modos sirven para efectuar las distintas tareas antes mencionadas como el leer correo, la edición de HTML y compilación de lenguaje C. La forma de saber en que modo se encuentra, es leyendo la línea de estado.

Para movernos dentro del documento tenemos as facilidades de las teclas de cursor o bien diciéndole hacia donde tiene que ir el curso mediante un comando. Por ejemplo si quisiera ir hacia adelante palabra a palabra teclearíamos Esc-f (f de forward) y nos iremos moviendo de esa manera. A modo inverso teclearemos Esc-b para ir hacia atrás. Para moverse hacia arriba y hacia abajo podremos hacerlo por medio de Ctrl-v para ir una pantalla adelante y Esc-v para ir una pantalla hacia atrás. Solo se tendrá que recordar que para ingresar un comando que comienza con la tecla Shift, antes deberemos presionar la tecla Esc. A continuación mostraremos una tabla básica de movimientos para emacs.

Tabla 1. Reseña de teclas en emacs para movimiento

Caracter Acción

Ctrl-b Se mueve atrás un caracter

Ctrl-f Se mueve adelante un caracter

Esc-b Se mueve atrás una palabra

Esc-f Se mueve adelante una palabra

Ctrl-p Se mueve a la línea anterior

Page 50: Tutorial del shell

Caracter Acción

Ctrl-n Se mueve a la línea siguiente

Ctrl-a Se mueve al inicio de la línea

Ctrl-e Se mueve al final de la línea

Ctrl-v Se mueve hacia adelante una pantalla

Esc-v Se mueve hacia atrás una pantalla

Esc-> Se mueve al final del buffer (archivo)

Esc-< Se mueve al inicia del buffer (archivo)

La edición de texto es muy completa, permitiendo marcar un fragmento del texto para copiarlo o cortarlo para pegarlo en otro lugar del documento. El texto cortado o copiado permanece en un buffer del procesador de texto y no tiene que ser único. Por ende podríamos tener varios fragmentos de texto en él y podrimos pegar cualquiera de ellos. La diferencia con otros editores de texto esta en que el proceso de pegar el contenido del portapapeles se denomina yanking (jalar). La siguiente tabla muestra los comando para edición más comunes.

Tabla 2. Reseña de teclas en emacs de edición

Caracter Acción

Ctrl-d Borra el caracter que está debajo del cursor

Del Borra el caracter anterior

Esc-Del Borra la palabra anterior

Esc-d Borra la palabra sobre la que está el cursor

Ctrl-k Borra la línea

Ctrl-w Borra la región marcada

Esc-w Copia la región marcada

Ctrl-y Inserta el texto en el buffer del portapapeles

Ctrl-@ Asigna el inicio de una región

Ctrl-Espacio Completar !!!!!!!!

Como en el procesador de textos Vi, tendremos la posibilidad de buscar un texto determinado, pero de una forma un poco mas cómoda, ya que emacs incorpora lo que se denomina búsqueda incremental (I-search). Este tipo de búsqueda se irá haciendo en tiempo real a medida que vayamos poniendo caracteres luego de presionar Ctrl-s, lo que inicia la búsqueda, buscando una concordancia. Bajo la línea inferior aparecerá una referencia de esta forma

Page 51: Tutorial del shell

I-search:

A medida que pongamos caracteres los iremos viendo luego de esa línea:

I-search: o

Y en el texto el cursor se ira desplazando a la primer palabra que comience con "o". Así a medida que se ingresen caracteres, emacs nos llevara hacia la primer palabra que concuerde. Si al terminar de escribir la palabra, todavía no se a llegado a la región donde se quería, bastara con teclear nuevamente Ctrl-s y emacs buscara la próxima ocurrencia de la palabra buscada anteriormente. Por supuesto la búsqueda es mas útil si se la puede usar para reemplazar algún texto en el documento, y esto es posible en emacs a través del comando Shift-% con lo que se pedirá primero el texto a buscar y luego el texto por el que será reemplazado. A continuación mostraremos una tabla que muestra las posibilidades de búsqueda y reemplazo que emacs posee.

Tabla 3. Teclas de emacs en modo búsqueda

Caracter Acción

Ctrl-s Busca hacia adelante en forma incremental

Ctrl-r Busca hacia atrás en forma incremental

Esc-o Termina la búsqueda

Espacio-o Reemplaza la cadena preguntando antes de hacerlo

Ctrl-g Cancela la búsqueda y regresa al inicio

Del Para borrar un caracter incorrecto en la cadena de búsqueda

Esc-% Se ingresa la cadena a buscar y el reemplazo

Shift-x Cambia todas la ocurrencias del documento

Existe muchas funciones más y queda para el lector si es de su interés el estudio del lenguaje incorporado LISP par la generación de funciones y macros que serán de mucha ayuda para usar este editor.

Notas

[1] En los teclados españoles, el símbolo de tilde (~) suele obtenerse presionando AltGr-4

Conceptos de editores fuera de líneaExisten ocasiones en las que el uso de un editor de textos como el vi o emacs puede ser demasiado o no cumplen con lo que queremos realizar. Tal vez se tengan que hacer cambios repetitivos a archivos o tener que procesar datos de una fuente y enviarlos a

Page 52: Tutorial del shell

otro archivo en un orden correcto o tal vez solo queremos una forma simple de hacer el trabajo desde un script o la línea de comandos. Es aquí donde entran a trabajar los editores fuera de línea y para nombrar solo 2 veremos el editor de flujo Sed y el lenguaje de programación Awk (por Alfred Aho,Peter Weinberg y Brian Kernighan). Lo especial de Awk es que es un lenguaje con todas las letras y muy poderoso, pero en ocasiones nos facilitará tareas tediosas de procesamiento de información y por esto lo ponemos en el rango de un editor fuera de línea. Aunque esto no quiere decir que es lo único que puede hacer. Para mayor información sobre Sed y Awk les sugiero lean "Sed & AWK" de Dale Dougherty que trata el tema con una mayor profundidad.

SedSed No es preciso detallar en demasía el uso de este editor fuera de línea dada que posee mucha similitud en su uso al editor de textos vi pero si es bueno mostrar algunas de sus funciones y usos tanto en el procesamiento desde un script o en la línea de comandos. Existen 3 casos específicos en los que se podrá usar Sed.

1. Para editar archivos muy largos para editar interactivamente.2. Para editar archivos de cualquier tamaño cuando la secuencia de comandos de

edición es muy complicada para hacer el tipeado confortable en ambiente interactivo.

3. Para usar múltiples funciones globales de edición eficientemente en un solo paso.

Existen diferentes formas de realizar una edición con el Sed. Puede hacerse desde la línea de comando o simplemente guardándolos en un archivo para poder ser usado luego. Sed lee la entrada línea a línea y realiza los cambios a estas de acuerdo a lo que se le especifique. Luego de hacer estos cambios dirige su salida hacia stdout, la cual puede ser redireccionada. Sed actúa en forma similar a filtros como el grep y sort pero con la diferencia que con Sed se podrán crear programas mas complicados y con una mayor cantidad de funciones.

Para definir una estructura de uso del Sed veremos 2 formas distintas. La primera es la utilizada en la línea de comandos a través de una canalización y que tendrá esta estructura:

primer_comando | sed <opciones> <descripción_de_la_edición>

A continuación veremos la segunda opción para su uso a partir de la línea de comandos:

sed -f script_de_edición <archivo>

Con la opción "-f" le decimos a sed que a continuación le pasaremos un archivo donde encontrara las reglas a aplicar en <archivo>. Sed tiene mucho que ver con el editor vi en el área de búsqueda y reemplazo donde la estructura es la siguiente:

[direccion1 [,direccion2]] descripción_de_la_edición [argumentos]

Las direcciones serán reglas que el sed tendrá que encontrar en el texto, si se omitieran estas sed realizara en caso de ser posible los cambios en forma global. La

Page 53: Tutorial del shell

descripción_de_la_edición indica a sed los cambios que tiene que hacer. Para esto, tema que veremos a continuación, pueden usarce varios argumentos. Es posible hacer varios cambios a una línea, sed los realiza de a uno y cuando ya no haya mas cambios a realizar en una línea dada, sed enviara el resultado a la salida estándar. Sed posee un contador interno de líneas que se va incrementando de acuerdo al número total de líneas leídas y no a las líneas del archivo. Por esto si se editan dos archivos juntos de 50 líneas cada uno, la línea número 60 de sed seria la línea 10 del segundo archivo. Esto es bueno para tener en cuenta a la hora de realizar ediciones a múltiples archivos. Como dijimos antes cada comando de sed puede tener 0, 1, ó 2 direcciones y en caso de tener 0, se aplicara a todas las líneas de ser posible:

/shrek/ s/entrada/salida/

El comando "s" indica a sed que debe hacer una sustitución de los argumentos que son pasados. Este simple comando, que puede estar en un archivo guardado para ser pasado al sed, sustituye la primera aparición de "entrada" por "salida" en las líneas que contengan "shrek". Cuando se ingresan dos direcciones, el cambio se comenzara a efectuar en la línea que concuerde la primer dirección y se ira aplicando a todas las siguientes hasta que concuerde con la segunda dirección. Las dos direcciones se separan con coma. Por ejemplo

10,30 s/entrada/salida/

hará una sustitución de "salida" por "entrada" a partir de la línea nº 10 hasta la línea nº 30. Obsérvese que no tiene que existir ningún espacio entre el comando "s" y la segunda dirección. Si las direcciones tiene al final un signo "!" (negado) el comando solo se aplicar a aquellas líneas que no concuerden con la dirección dada. Por ejemplo

10,30! s/entrada/salida/

Este comando se aplicará a todas la líneas, menos a las que estén entre la número 10 y la 30 inclusive. Como antes dijimos podremos modificar la salida del sed. Por ejemplo si quisiéramos mostrar por la salida estándar las líneas de una archivo que están entre la 20 y la 40, podremos dar a sed los argumentos necesarios:

[shrek@pantano:~]$ cat archivo | sed -n '20,40p'

El -n indica a sed que imprima solo las líneas que concuerden con los argumentos pasados, dado que evita que se impriman todos los demás. El comando "p" es para imprimir el patrón que encuentra sed. Ya estamos en condiciones de hacer un script rudimentario para imprimir líneas de archivos

[shrek@pantano:~]$ find /home/sebas/cartas/ "*" -print | while read FILE>do echo $FILE>cat $FILE | sed -n '5,15p'>done

A continuación se mostrara por la salida estándar desde la línea 5 hasta la 15 inclusive de todos los archivos del directorio /home/shrek/cartas. Existen veces que queremos tener partes de archivos que concuerden con un patrón determinado, por ejemplo, si

Page 54: Tutorial del shell

quisiéramos mandar todos los comentarios de un archivo de shell_script a otro y sabemos que las líneas que lo son comienzan con "#" podemos usar un comando en sed que haga el trabajo por nosotros de forma muy simple

[shrek@pantano:~]$ cat archivo | sed -n '/^#/w archivo2'

Debe existir un espacio exacto entre la "w" y el "archivo2" Con el -n indicamos a sed que solo procese las líneas que concuerdan con la dirección que le pasaremos. Con el símbolo "^" le decimos a sed que tiene que encontrar la dirección al principio de la línea. Y con la w le indicamos que escriba la salida al archivo2. A continuación pondremos una tabla de los comando que se usan en sed. Se recomiendan que practiquen con ellos y que observen los resultados obtenidos.

Tabla 4. Comandos del editor Sed

Caracter Acción

a añade texto al espacio patrón

b ramifica a un rotulo, se emplea de forma similar a un goto

c añade texto

d borra texto

i inserta texto

l lista el contenido del espacio patrón

n añade una nueva línea al espacio patrón

p imprime el espacio patrón

r lee un archivo

s sustituye patrones

w escribe a un archivo

AwkEL awk es un poderoso lenguaje de programación que en muchas ocasiones nos sacara de apuros a la hora de tener que hacer script complejos de tratamiento de texto. El awk al igual que el sed lee las líneas completas para realizar sus modificaciones. Uno de los aspectos mas útiles en relación al awk es que a diferencia del "sed", awk puede dividir las líneas en campos a través de un separador de campo indicado en el script o en la línea de comandos. Si no se indica ninguno se tomara como separador de campo un espacio o tabulador. Usando la opción -F de la línea de comandos o la variable FS desde un programa hecho en awk se puede especificar un nuevo separador de campo. Por ejemplo si lo que quisiéramos es ver los nombres verdaderos que aparecen en el archivo /etc/passwd primero tendríamos que saber como separar los campos. En el archivo /etc/passwd se separan por un ":". Ahora tendríamos que saber en que campo se

Page 55: Tutorial del shell

encuentra el nombre. Es en el campo numero 5, comenzando a contar como el primero de los campos. El 0 es la línea completa y ya veremos por que

[shrek@pantano:~]$ cat /etc/passwd | awk -F : '{print $5}'rootbindaemonadmlpsyncshutdownhaltmailnewsuucpoperatorgamesgopherFTPUserNobodyX Font ServerNamedPostgreSQL ServerShrek OgreFiona Ogre[shrek@pantano:~]$

Como vemos lo primero que hicimos fue indicarle al awk cual seria el separador de campo "-F :", luego entre comillas le indicamos que imprima a la salida estándar el campo nº 5, '{print $5}'. De esta forma vemos los nombres contenidos en el archivo /etc/passwd. Podríamos imprimir mas de un campo a la vez, por ejemplo si queremos mostrar también el directorio home de cada uno de los usuarios podríamos hacer lo siguiente:

[shrek@pantano:~]$ cat /etc/passwd | awk -F : '{print $5,$6}'root /rootbin /bindaemon /sbinadm /var/admlp /var/spool/lpd. . .PostgreSQL Server /var/lib/pgsqlShrek Ogre /home/shrekFiona Ogre /home/fiona[shrek@pantano:~]$

De esta simple manera podremos ir completando la línea a los requerimientos del campo que queramos ver ya que tenemos la posibilidad de hacer comparaciones a un campo de la misma manera que la haríamos a una variable en cualquier otro lenguaje. Por ejemplo si quisiéramos ver las líneas del /etc/passwd de todos aquellos usuarios que pertenecen al grupo user, representado por el nº 100 en el archivo passwd, podríamos hacer que el awk comprara el número del campo en el que esta el número GUID que nosotros buscamos. En el caso particular que cada usuario tuviese su grupo, podrimos hacer que se compararan todas las líneas que posean un número mayor o igual al número de grupo de usuarios mas bajo, por ejemplo 500 es el número que por defecto

Page 56: Tutorial del shell

pone Red Hat a al grupo del primer usuario y va incrementándose a medida que incorporamos usuarios. Tendríamos que mostrar todas las líneas que en campo donde esta el GUID, el número 4, del usuario y que sea mayor o igual a 500. Por ejemplo:

[shrek@pantano:~]$ cat /etc/passwd | awk -F :\'$4>=500 {print $0}'shrek:x:500:500:Shrek Ogre:/home/shrek:/bin/bashfiona:x:501:501:Fiona Ogre:/home/fiona:/bin/bash[shrek@pantano:~]$

Como verán se indico que mostrara solo aquellas líneas que tuviesen en el campo nº 4 un valor mayor o igual a 500, $4>=500.También se ve que mostramos la línea entera al poner como campo a imprimir el $0. Una acotación que tendríamos que notar. Lo que comparamos en esta oportunidad es un número y esto lo hace tremendamente poderoso al awk como lenguaje de programación. Si se quisieran compara cadenas, se tendrían que encerrar ente "". Como ejemplo, si hubiésemos encerrado entre "" al 500 lo que awk interpretaría es que queremos mostrar todas las líneas que en la posición 4 tengan un valor alfabéticamente mayor o igual a 500.

[shrek@pantano:~]$ cat /etc/passwd | awk -F :\'$4>="500" {print $0}'lp:x:4:7:lp:/var/spool/lpd:nobody:x:99:99:Nobody:/:shrek:x:500:500:Shrek Ogre:/home/shrek:/bin/bashfiona:x:501:501:Fiona Ogre:/home/fiona:/bin/bash[shrek@pantano:~]$

Como verán si se ordena alfabéticamente la posición 4 el 7 y el 99 son mayores que 500. Los operadores que awk puede manejar son los siguientes:

Tabla 5. Operadores de Awk

Operador Significado

< menor que

<= menor que o igual que

== igual a

!= no igual a

>= mayor que o igual que

> mayor que

Otra posibilidad es el usar expresiones regulares para efectuar la búsqueda. Pero cuidado ya que es tienen que ser ingresadas de acuerdo a sí es mayúscula o minúscula.

[shrek@pantano:~]$ cat /etc/passwd | awk -F :\'/Shrek/ {print $0}'shrek:x:500:500:Shrek Ogre:/home/shrek:/bin/bash[shrek@pantano:~]$

Page 57: Tutorial del shell

Lo único que tendremos que hacer es encerrarlo entre "/" para que se tomen como expresión regular. Ahora bien, las expresiones podrán ser tan complejas como queramos. Por ejemplo si quisiéramos mostrar todas las líneas que tuviesen la cadena "se" pero que no tengan antes la letra "U" y no les siga un espacio la orden es

[shrek@pantano:~]$ cat /etc/passwd | awk -F :\'/[^U]se[^ ]/ {print $0}'shrek:x:500:500:Shrek Ogre:/home/shrek:/bin/bash[shrek@pantano:~]$

Como ven las cadenas que tenemos que ignorar se preceden antes y después de la cadena buscada ingresando un símbolo ^ encerrado entre []. De esta manera se podrá ir usando las distintas expresiones regulares. En todos estos casos se utilizaron una única forma para imprimir en pantalla los resultados, pero es bueno saber que contamos con otra forma en la que podremos formatear el texto antes de su salida por pantalla. Para la salida formateada se utiliza el "printf". Por ejemplo si quisiéramos podrimos imprimir los datos en una forma más cómoda:

[shrek@pantano:~]$ cat /etc/passwd | awk -F :\'$4>=500 {printf"%20s %5s\n",$5,$1}'Shrek Ogre shrek Fiona Ogre fiona[shrek@pantano:~]$

Como se puede ver, pedimos que nos mostrara el nombre completo de l usuario y el nombre de usuario. Como sabemos la extensión aproximada que tendrá cada campo le damos 20 posiciones para le primer campo a mostrar, el $5, y 5 posiciones para el segundo campo a mostrar, el $1. Si lo que quisiéramos mostrar fuesen número en lugar de la "%s" (string) iría una "%d" o "%i" (decimal).Para mas información sobre el printf buscar en las páginas de manual del awk. Existen diferentes variables integradas, a parte del FS, que permiten llevar cuentas de distintos aspectos. Por ejemplo existe la variable NR que llevara la cuenta de los registros que mostremos. Por ejemplo supongamos que necesitamos obtener un listado largo de un directorio, pero solo queremos ver los permisos, el nombre del archivo y el número de registro que a pasado por el awk.

[shrek@pantano]$ ls -l | awk '{ print NR" "$1" "$9}'1 total2 -rw-rw-r-- 1467683 -rw-rw-r-- Bienvenidos4 -rw-rw-r-- Bienv5 -rw-rw-r-- authkey.file6 drwxr-xr-x Desktop7 -rw-rw-r-- LUGRo8 drwxrwxr-x Linux9 -rw-rw-r-- Listado10 -rw-rw-r-- Lo11 drwx------ Mail. . .49 -rw-rw-r-- pgaccess-report.ps50 -rw-rw-r-- sed51 -rw-rw-r-- sed.zip52 -rw-rw-r-- smtptel.htm53 -rw-rw-r-- vicky

Page 58: Tutorial del shell

Como verán, en esta ocasión la variable NR fue llevando la cuenta de los registros que fueron pasando por el awk. De esta forma se podrá decirle al awk que me muestre de los registros 5 al 10 solamente. scr Existen muchas más variables en el awk que son de extrema utilidad. Por ejemplo, en el caso anterior sabíamos que el ultimo campo estaba en la posición número 9, pero ¿que ocurre si no sabemos la posición del último campo o esta varia? Para esto esta la variable NF que lleva la cuenta de la cantidad de campos de cada registro. Por ello en lugar de la anterior forma podrimos poner:

[shrek@pantano:~]$ ls -l | awk '{ print NR" "$1" "$NF}'

y obtendríamos idénticos resultados. Pero un momento, aquí hay algo raro. La variable NR no tiene el signo $, en cambio la variable NF si lo tiene. Esto esta dado así para que no se reemplazado por el awk. Por ejemplo si hubiésemos puesto la variable NF sin signo $ el resultado seria.

[shrek@pantano:~]$ ls -l | awk '{ print NR" "$1" "NF}'1 total 22 -rw-rw-r-- 93 -rw-rw-r-- 114 -rw-rw-r-- 115 -rw-rw-r-- 116 drwxr-xr-x 9. . .

Lo que nos esta mostrando no es el último campo, sino la cantidad de campos que ese registro tiene. Al agregarle el signo $ se reemplazara con el número del último campo y ese campo el que será mostrado. Esto es así para todas las variables integradas. El awk puede ser usado no-solo en una línea. Podrimos usarlo también como cualquier otro lenguaje para realizar múltiples tareas en una línea o realizar algo antes de comenzar la lectura y otra después. Para demarcar el código se utiliza los pares BEGIN-END. Todo lo que aparece después de la palabra BEGIN, pero en el mismo renglón, se realiza antes de que comience el ciclo. Cualquier cosa que este después de END se realiza después de que se haya leído la última línea y cerrado el ciclo. Estas líneas tendrán que estar en un archivo que será utilizado por el awk para procesar en este ejemplo al archivo /etc/passwd. Un ejemplo seria el siguiente:

BEGIN { FS=":"}{ printf"Nombre Completo: %s\n",$5 }{ printf"Nombre de Usuario: %s\n",$1}{ printf"UID: %i,GUID: %i\n\n",$3,$4 }END { printf "\n\nTotal de usuarios: %d \n\n", NR}

Este pequeño programa realizado con el vi será guardado en el archivo awk.src, el nombre se lo damos nosotros, y nos servirá para mostrar algunos datos del /etc/passwd mas detalladamente. La forma de ejecutarlo es a través del modificado "-f" donde le decimos al awk que a continuación le pasaremos un archivo con el programa que tiene que usar para procesar el /etc/passwd.

[shrek@pantano:~]$ awk -f awk.src /etc/passwdNombre Completo: root Nombre de Usuario: root UID: 0,GUID: 0Nombre Completo: bin Nombre de Usuario: bin UID: 1,GUID: 1Nombre Completo: daemon Nombre de Usuario: daemon UID: 2,GUID: 2Nombre Completo: adm Nombre de Usuario: adm UID: 3,GUID: 4

Page 59: Tutorial del shell

. . .Nombre Completo: PostgreSQL Server Nombre de Usuario: postgres UID: 26,GUID: 26Nombre Completo: Shrek Ogre Nombre de Usuario: shrek UID: 500,GUID: 500Nombre Completo: Fiona Ogre Nombre de Usuario: fiona UID: 501,GUID: 501Total de usuarios: 22

Para finalizar diremos que también se podrán hacer operaciones con estas variables, es decir, sumarlas restarlas, multiplicarlas y dividirlas. Por ejemplo si quisiéramos saber en cuantos bloques de 4 líneas podríamos formar con un archivo de texto dado podríamos hacer el siguiente programa:

BEGIN {FS=":"}{ print $0 }FNR%4==0 { printf"\n" }END { printf "El archivo %s puede entrar en %i bloques enteros\ de 4 lineas\n",FILENAME,NR/4}

Existen un par de cosas nueva en el. Por ejemplo la variable "FNR" que cuenta el número de líneas. En esta ocasión le estamos diciendo que si el modulo de FNR es igual a 4 "FNR%4" imprima un salto de linea "{ printf"\n" }". Y al finalizar el ciclo se mostrara el mensaje que nos informara cuantos bloques de 4 líneas podremos tener. Para obtener el resultado se efectúa una división del numero total de registros "NR" por el número de líneas que queremos armar el bloque, "4". La variable FILENAME indica cual es el archivo sobre el cual se realizo el proceso y es tomada cuando se la pasamos al awk como argumento. El resultado es

[shrek@pantano]$ awk -f awk2.src /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:daemon:x:2:2:daemon:/sbin:adm:x:3:4:adm:/var/adm:lp:x:4:7:lp:/var/spool/lpd:sync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:news:x:9:13:news:/var/spool/news:uucp:x:10:14:uucp:/var/spool/uucp:operator:x:11:0:operator:/root:games:x:12:100:games:/usr/games:gopher:x:13:30:gopher:/usr/lib/gopher-data:ftp:x:14:50:FTP User:/home/ftp:nobody:x:99:99:Nobody:/:xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/falsenamed:x:25:25:Named:/var/named:/bin/falsegdm:x:42:42::/home/gdm:/bin/bashpostgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bashshrek:x:500:500:Shrek Ogre:/home/shrek:/bin/bashfiona:x:501:501:Fiona Ogre :/home/fiona:/bin/bash

El archivo /etc/passwd puede entrar en 5 bloques enteros de 4 lineas

Page 60: Tutorial del shell

Administración básica del sistemaEn este capítulo trataremos de ver los aspectos generales sobre la administración de nuestro sistema contemplando algunas configuraciones que se tendrán que hacer, tomando como base un sistema pequeño como el de nuestro hogar o de una empresa con pocas máquinas interconectadas.

Empezaremos reforzando el concepto de la cuenta root para comprender su alcance y que restricciones y libertades podremos dar a los demás usuarios.

Luego veremos varias maneras para poder arrancar nuestro sistema ejemplificando tres métodos: la utilización de un diskette, el uso del LILO o desde la aplicación para DOS LOADLIN.

Nuestro sistema tendrá que tener la posibilidad de imprimir y es por ello que ejemplificaremos dos métodos para imprimir. Uno en la máquina local y otro en una máquina remota.

Como todo sistema requerirá en algún punto que se instale un kernel nuevo o se actualice parte del mismo, veremos aspectos generales sobre las actualizaciones necesarias para nuestro sistema.

La cuenta root y sus implicaciones

  Si no eres root no eres nadie

En este punto sabemos que la cuenta raíz, que tiene el nombre de usuario root, es el más importante del sistema y además es quien tiene los privilegios más altos para interactuar con él. También sabemos, y esto a fuerza de malas experiencias en muchas ocasiones, que el ser root requiere responsabilidades y el estar conciente de lo que se hace con este tipo de cuentas ya que muchas veces un error cometido será irreparable.

Los usuarios del sistema están bastante restringidos en lo que pueden realizar, ya sea con los archivos de otros usuario o archivos de sistema, ya que no tienen los permisos necesarios para poder modificarlos o borrarlos e incluso en muchos casos leerlos. Todas estas limitaciones se terminan con la cuenta root ya que posee acceso a cada área del sistema pudiendo borrar, crear, modificar archivos de cualquier parte del sistema así como cambiar permisos y dueños de estos. Puede ejecutar cualquier programa y hasta incluso si se le ocurriese podría literalmente matar al sistema por completo. Esto es así ya que es necesario que exista por lo menos una persona que pueda intervenir al sistema si es necesario y que tenga los privilegios adecuados para poder forzar al sistema a realizar algo. La idea es que esta cuenta se utilice sobriamente, únicamente cuando es necesario y no en cualquier momento. Para ejemplificar un hecho que seria peligroso si e fuerce root, si un usuario normal de le ocurriese borrar los archivos que se encuentran en el directorio /boot el sistema no lo dejaría, en cambio si es el root quien lo pide, lo que este en /boot desaparecerá muchas veces, de acuerdo a la configuración de GNU/Linux que se posea, cargándose al kernel completo con ellos.

Page 61: Tutorial del shell

Para evitar cualquier accidente al utilizar la cuenta root es recomendable los siguientes pasos a seguir

1. Pensarlo dos veces antes de apretar la tecla Enter en un comando que pueda causar algún daño. Por ejemplo si se esta borrando algún archivo de configuración releer la línea del comando completo.

2. No acostumbrarse a usar root. Cuando más confortable se encuentre uno trabajando con el usuario root, más seguro que se confundirán los privilegios con los de un usuario normal.

3. Usar siempre un marcador distinto para un usuario normal y el root. Esto ya viene por defecto en la mayoría de las distribuciones pero siempre esta bien repetirlo. Un signo $ o % representara al usuario normal y un # representara al root.

4. Conectarse como usuario root solo cuando sea absolutamente necesario. Y desconectarse tan pronto como se haya terminado el trabajo. Cuando menos se use la cuenta root, menos posibilidades de cometer un error habrá.

Existen personas que son verdaderos hackers de Un*x que utilizan la cuenta root para todo, pero hay que recordar dos cosas con respecto a esto. Lo primero que no estamos a esa altura de conocimiento sobre Un*x y segundo que estas personas en algún momento han hecho algo que les a hecho perder su información.

La cuenta root es poderosa en el sistema, y ese poder es peligroso muchas veces para el resto de los usuarios del sistema. La tendencia a la destrucción de un usuario con el poder de root es perjudicial para el resto del sistema ya que en sucesivas oportunidades se a sabido de casos en los que los administradores del sistema leen correo de otro usuarios o borran archivos sin avisar a nadie jugando con el sistema informático como si fuesen niños y no como verdaderos administradores. Por ello se requiere cierto grado de madurez y responsabilidad además del conocimiento necesario para poder llegar a ser administrador de un sistema y es en nuestros sistemas que tendremos en el hogar o en la oficina con GNU/Linux donde tendremos que aprender a serlo.

Gestión de usuariosEl sistema mantiene una cierta cantidad de información acerca de cada usuario. Dicha información se resume a continuación.

nombre de usuario

El nombre de usuario es el identificador único dado a cada usuario del sistema. Ejemplos de nombres de usuario son: shrek, burro y fiona. Se pueden utilizar letras y dígitos junto a los caracteres "_" (subrayado) y el punto. Los nombres de usuario se limitan normalmente a 8 caracteres de longitud.

clave

El sistema también almacena la clave encriptada del usuario. El comando passwd se utiliza para poner y cambiar las claves de los usuarios.

user ID

Page 62: Tutorial del shell

El user ID, o UID, es un número único dado a cada usuario del sistema. El sistema normalmente mantiene la pista de la información por UID, no por nombre de usuario.

group ID

El group ID, o GID, es la identificación del grupo del usuario por defecto.

nombre completo

El nombre real o nombre completo del usuario se almacena junto con el nombre de usuario. Por ejemplo, el usuario burro puede tener el nombre "Platero Equino" en la vida real.

directorio inicial

El directorio inicial es el directorio en el que se coloca inicialmente al usuario en tiempo de conexión. Cada usuario debe tener su propio directorio inicial, normalmente situado bajo /home.

intérprete de comando

El intérprete de comando del usuario es el intérprete de comandos que es arrancado para el usuario en tiempo de conexión. Ejemplos pueden ser /bin/bash y /bin/tcsh.

El archivo /etc/passwd contiene la información anterior acerca de losusuarios. Cada línea del fichero contiene información acerca de un único usuario. El formato de cada línea es

nombre:clave_encriptada:UID:GID:nombre completo:dir_inicio:intérprete

Un ejemplo puede ser

shrek:Xv8Q981g71oKK:102:100:Shrek Ogre:/home/shrek:/bin/bash

El primer campo , "shrek", es el nombre de usuario. El siguiente campo, "Xv8Q981g71oKK", es la clave encriptada. Las claves no se almacenan en el sistema en ningún formato legible por el hombre. Las claves se encriptan utilizándose a sí mismas como clave secreta. En otras palabras, sólo si se conoce la clave, ésta puede ser desencriptada. Esta forma de encriptación es bastante segura.

Algunos sistemas utilizan "claves en sombra" (shadow) en la que la información de las claves se relega al fichero /etc/shadow. Puesto que /etc/passwd es legible por todo el mundo, /etc/shadow suministra un grado extra de seguridad, puesto que éste no lo es. Las claves en sombra suministran algunas otras funciones como puede ser la expiración de claves; no entraremos a detallar estas funciones aquí.

El tercer campo, "102", es el UID. Este debe ser único para cada usuario. El cuarto campo,"100", es el GID. Este usuario pertenece al grupo numerado 100. La información

Page 63: Tutorial del shell

de grupos, como la información de usuarios, se almacena en el fichero /etc/group. El quinto campo es el nombre completo del usuario, "Shrek Ogre". Los dos últimos campos son el directorio inicial del usuario, /home/shrek y el intérprete de conexión /bin/bash, respectivamente. No es necesario que el directorio inicial de un usuario tenga el mismo nombre que el del nombre de usuario. Sin embargo, ayuda a identificar el directorio.

Borrando usuariosAnteriormente vimos como podemos crear un usuario para empezar a utilizar el sistema, y este método puede emplearse para la creación de cualquier otro usuario. De forma parecida, borrar usuarios puede hacerse con los comandos userdel o deluser dependiendo del software instalado en el sistema.

Si se desea "deshabilitar" temporalmente un usuario para que no se conecte al sistema (sin borrar la cuenta del usuario), se puede prefijar con un asterisco ("*") el campo de la clave en /etc/passwd.Por ejemplo, cambiando la línea a

shrek:*Xv8Q981g71oKK:102:100:Shrek Ogre:/home/shrek:/bin/bash

evitará que shrek se conecte.

Después de que haya creado un usuario, puede necesitar cambiar algún atributo de dicho usuario, como puede ser el directorio inicial o la clave. La forma más simple de hacer esto es cambiar los valores directamente en /etc/passwd. Para poner clave a un usuario, utilice el comando passwd. Por ejemplo

[root@pantano:~]# passwd burro

cambiará la clave de burro. Sólo root puede cambiar la clave de otro usuario de ésta forma. Los usuarios pueden cambiar su propia clave con passwd también.

En algunos sistemas, los comandos chfn y chsh están disponibles, permitiendo a los usuarios el cambiar sus atributos de nombre completo e intérprete de conexión. Si no, deben pedir al administrador de sistemas que los cambie por ellos.

GruposComo hemos citado anteriormente, cada usuario pertenece a uno o más grupos. La única importancia real de las relaciones de grupo es la perteneciente a los permisos de ficheros, como dijimos anteriormente cada fichero tiene un "grupo propietario" y un conjunto de permisos de grupo que define de qué forma pueden acceder al fichero los usuarios del grupo. Hay varios grupos definidos en el sistema, como pueden ser bin, mail, y sys. Los usuarios no deben pertenecer a ninguno de estos grupos; se utilizan para permisos de ficheros del sistema. En su lugar, los usuarios deben pertenecer a un grupo individual, como users. Si se quiere ser detallista, se pueden mantener varios grupos de usuarios como por ejemplo estudiantes, soporte y facultad.

Page 64: Tutorial del shell

El fichero /etc/group contiene información acerca de los grupos. El formato de cada línea es

nombre de grupo:clave:GID:otros miembros

Algunos ejemplos de grupos pueden ser:

root:*:0:users:*:100:fiona,burro,shrekinvitados:*:200:otros:*:250:shrek

El primer grupo, root, es un grupo especial del sistema reservado para la cuenta root. El siguiente grupo, users, es para usuarios normales. Tiene un GID de 100. Los usuarios fiona y pedro tienen acceso a este grupo. Recuérdese que en /etc/passwd cada usuario tiene un GID por defecto. Sin embargo, los usuarios pueden pertenecer a mas de un grupo, añadiendo sus nombres de usuario a otras líneas de grupo en /etc/group. El comando groups lista a qué grupos se tiene acceso.

El tercer grupo, invitados, es para usuarios invitados, y otros es para "otros" usuarios. El usuario shrek tiene acceso a éste grupo.

Como se puede ver, el campo "clave" de /etc/group raramente se utiliza. A veces se utiliza para dar una clave para acceder a un grupo. Esto es raras veces necesario. Para evitar el que los usuarios cambien a grupos privilegiados (con el comando newgroup), se pone el campo de la clave a "*".

Se pueden usar los comandos addgroup o groupadd para añadir grupos a su sistema. Normalmente es más sencillo añadir líneas a /etc/group uno mismo, puesto que no se necesitan más configuraciones para añadir un grupo. Para borrar un grupo, sólo hay que borrar su entrada de /etc/group.

Poniendo reglas al sistemaEl SO Un*x no fue diseñado desde sus principios pensando en la seguridad entre los usarios del sistema. El pensar que usarios académicos irrumpieran en áreas que no les pertenecían no se tomaba en como algo posible para los primeros tiempos en que UNIX estaba desarrollándose. El tener una actitud mano dura con los usarios no ayudará a que estos traten de saltarse las limitaciones que le podamos haber impuesto. Puede ser que en un ambiente militar esto funcione pero no será igual en un sistema universitario o en una empresa. Lo que si tiene sentido es el escribir una serie sencillas de reglas que el usuario pueda seguir y que tienen que ir de acuerdo a las políticas del área donde se esta implementando el sistema informativo. Puede darse el caso de que existan reglas que estén en contra de las políticas o que no estén bien explicadas por lo que será difícil de cumplir.

También esta el caso de que si las reglas son por demás de restrictivas con el usuario éste tratará de saltarlas. Otro caso son los usarios que por desconocimiento de estas reglas realizan acciones prohibidas. Por ejemplo, envían mails de 20 MB por la red saturando la conexión dado que no se especifica claramente que no pueden mandarse

Page 65: Tutorial del shell

mails con adjuntos tan grandes. Si nadie se lo informa al usuario no podemos pedirle que obedezca. Los motivos por los cuales las reglas se implementan deberán estar claros, ya que los usuarios se sentirán tentados a hacer cosas que están prohibidas por naturaleza, sin ninguna otra explicación.

Iniciando el sistemaNuestro sistema GNU/Linux tiene varias formas de ser iniciado bien sea desde floppy disk o desde el disco rígido. A continuación veremos las tres formas que son indudablemante las más populares.

Utilizando un disquete de arranqueMucha gente arranca Linux utilizando un floppy disk de arranque que contiene una copia del núcleo de Linux. A este núcleo se le indica la partición raíz de Linux para que sepa donde buscar en el disco rígido el sistema de ficheros raíz. El comando rdev puede ser utilizado para poner la partición raíz en la imagen del núcleo. Por ejemplo, este es el tipo de floppy creado por Slackware durante la instalación. [1] Para crear su propio disquete de arranque, localicemos en primer lugar la imagen del núcleo en su disco duro. Debe estar en el directorio /boot o /. Algunas distribuciones utilizan el fichero /vmlinux para el núcleo.

En su lugar, puede que tenga un núcleo comprimido. Un núcleo comprimido se descomprime a sí mismo en memoria en tiempo de arranque, y utiliza mucho menos espacio en el disco duro. Si se tiene un núcleo comprimido, puede encontrarse en el fichero /boot/zImage o /zImage. Algunas distribuciones utilizan el fichero /vmlinuz para el núcleo comprimido.

Una vez que se sabe donde está el núcleo, podemos usar el comando mkbootdisk con el que podremos hacer un disco de arranque

[root#pantano:~]# mkbootdisk --device /dev/fd0 2.4.26

donde 2.4.26 es el nombre del núcleo que actualmente esta corriendo. De esta forma se creará un sistema de archivos en el floppy que contendrá la imagen del kernel y los módulos necesarios para funcionar. Con este floppy arrancaremos ahora Linux.

Utilizando LILOOtro método de arranque es utilizar LILO, un programa que reside en el sector de arranque del disco duro. Este programa se ejecuta cuando el sistema se inicia desde el disco duro, y puede arrancar automáticamente Linux desde una imagen de núcleo almacenada en el propio disco duro.

LILO puede utilizarse también como una primera etapa de carga de varios sistemas operativos, permitiendo seleccionar en tiempo de arranque qué sistema operativo (como GNU/Linux o MS-DOS) arrancar. Cuando se arranca utilizando LILO, se inicia el sistema operativo por defecto, a menos que pulse TAB durante la secuencia de

Page 66: Tutorial del shell

arranque. Si se pulsa esta tecla, se le presentará un indicador de arranque, donde debe teclear el nombre del sistema operativo a arrancar (como puede ser "linux" o "msdos").

La forma más simple de instalar LILO es editar el fichero de configuración, /etc/lilo.conf, y ejecutar el comando

[root@pantano:~]# /sbin/lilo

El fichero de configuración de LILO contiene una "estrofa" para cada sistema operativo que se pueda querer arrancar. La mejor forma de mostrarlo es con un ejemplo de un fichero de configuración LILO. El ejemplo siguiente es para un sistema que tiene una partición raíz Linux en /dev/hda2 y una partición Windows en /dev/hda1.

# Le indicamos a LILO que modifique el registro de arranque de# /dev/hda (el primer disco duro no-SCSI).# Si se quiere arrancar desde una unidad distinta de /dev/hda,# se debe cambiar la siguiente lineaboot = /dev/hdadefault=linux

# Nombre del cargador de arranque. No hay razon para cambiarlo,# a menos que se esté haciendo una modificacion seria del LILO.

install = /boot/boot.b

# Estrofa para la partición raíz de Linux en /dev/hda2.

image = /boot/2.4.26 # Ubicación del kernellabel = linux # Nombre del SO (para el menu de arranque)root = /dev/hda2 # Ubicación de la partición raízvga = ask # Indicar que pregunte por modos SVGA # en tiempo de arranque

# Estrofa para la partición Windows en /dev/hda1.other = /dev/hda1 # Ubicación de la particióntable = /dev/hda # Ubicación de la tabla de partición para # /dev/hda2label = W$ # Nombre del SO (para el menu)

La línea default indica la etiqueta del sistema operativo que arrancará LILO por defecto. Se puede seleccionar otro sistema operativo en el indicador de arranque de LILO, tal y como se indicó anteriormente. Recuerde que cada vez que actualice la imagen del núcleo en disco, se debe reejecutar /sbin/lilo para que los cambios queden reflejados en el sector de arranque de su unidad.

Utilizando LOADLINAnteriormente dijimos que el sistema de arranque que utilizaba al LILO tenia un problema. Este era que el kernel no podía estar mas allá del cilindro 1024 dado que no se cargaría. A partir de las nuevas versiones de LILO esto se está solucionando. De esta forma la única manera que nos quedaba para iniciar GNU/Linux era a través de un disquete con la subsiguiente lentitud que esto tenía. Por esto se desarrollo una aplicación que permitía que arrancáramos el núcleo del sistema desde una partición DOS. Esta aplicación se denomina LOADLIN y lo que hace es sencillo. En un directorio de la

Page 67: Tutorial del shell

partición DOS se guarda el kernel y a partir del comando loadlin se le indica el kernel que se quiere cargar y la partición donde se encuentra GNU/Linux instalado.

C:\> loadlin c:\vmlinuz root=/dev/hda2 ro

De esta forma se saldrá de DOS y se cargara el kernel en memoria.

Notas

[1] Las últimas versiones de Slackware utilizan un método diferente para arrancar desde floppy, utilizando el programa SysLinux

Acerca de impresoras:Extraído del Printer HowTo de Grant Taylor <[email protected]> y Brian McCauley <[email protected]>

Todo sistema que se precie es capaz de gestionar una o varias impresoras, con uno o varios usuarios, que les envían distintas clases de documentos, más o menos dignamente. Un*x resuelve estos problemas mediante un conjunto de programas, los servidores de impresión, que gestionan los trabajos pendientes, y los encauzan a las impresoras adecuadas, todo de manera completamente transparente al usuario. El camino más corto en Un*x (y GNU/Linux), es enviar los datos a imprimir directamente al dispositivo adecuado. El siguiente comando envía un listado del directorio a la impresora en puerto paralelo (hablando en DOS, LPT1:)

[root#pantano:~]# ls > /dev/lp1

El problema de este método es que no aprovecha las capacidades de multitarea de Linux, debido a que el tiempo que tarda el comando en completarse será el mismo que emplee la impresora en despachar el trabajo. En una impresora lenta, o en una apagada o sin papel, puede prolongarse un poco. Podríamos ejecutar el comando simplemente en segundo plano, pero no adelantaríamos mucho. Además, deberá tener privilegios de root. Un remedio mejor es crear un área de spool, es decir, guardar los datos a imprimir en un fichero temporal, y arrancar un proceso en segundo plano que envíe los datos a la impresora, y gestione las incidencias que se presenten. Esencialmente, así funciona el sistema de impresión en Linux. Para cada impresora, se define un área spool, donde cada trabajo pendiente se almacena en un fichero. Un proceso en segundo plano (llamado el demonio de impresión) analiza metódica y constantemente los ficheros spool, buscando nuevos datos a imprimir. Cuando aparece alguno, son enviados a la impresora apropiada; cuando más de un fichero está a la espera, se colocan en una cola (el primero que entra es el primero que se procesa), por lo que se habla propiamente de la "cola de impresión".

En el caso de impresión remota, los trabajos se gestionan localmente, como cualquier otro, pero el demonio de impresión lo envía a través de la red hacia el ordenador o impresora destino. La información que el demonio de impresión necesita para su trabajo

Page 68: Tutorial del shell

(el dispositivo físico, el spool de datos, la máquina e impresora remota, etc.) se almacenan en un fichero llamado /etc/printcap, que describiremos más tarde.

En lo sucesivo, el término "impresora" se referirá a una máquina lógica definida en /etc/printcap. El concepto "impresora física", define la cosa que mancha papel. Es perfectamente posible describir múltiples entradas en /etc/printcap que se refieren a una sola impresora física, pero por caminos tortuosos. No nos preocupemos, lo aclararemos al describir printcap.

Lo primero a tener en cuentaEl sistema de impresión de Linux se sustenta en cinco programas, que deberían estar donde aparecen en el siguiente listado, propiedad de root, y grupo lp (o daemon, según el sistema en concreto)

-rwxr-xr-x root lp /bin/lpr-rwxr-xr-x root lp /bin/lpq-rwxr-xr-x root lp /bin/lpc-rwxr-xr-x root lp /bin/lprm-rwxr-x--- root lp /sbin/lpd

Los cuatro primeros tienen por fin enviar, cancelar y examinar los trabajos de impresión. /sbin/lpd es el demonio de impresión. Hay páginas de manual que explican con detalle todas estas órdenes y que debería consultar para ampliar información.

Los directorios, permisos y propiedad de los ficheros pueden diferir a los de su sistema, aunque no deberían ser MUY distintos.

Es importante saber que, por defecto, lpr, lprm, lpc y lpq trabajan con una impresora llamada "lp". Si define la variable de entorno PRINTER con el nombre de una impresora, pasará a ocupar el valor por defecto. Se puede indicar sobre la marcha una impresora distinta con la opción -P impresora en la línea de órdenes.

Los directorios fundamentales.Realmente, sólo hay un directorio importante: el área de spool donde se almacenan los datos a la espera de que lpd decida qué hacer con ellos. Sin embargo, un sistema típico debería configurarse en varios directorios, uno para cada impresora, lo que facilita notablemente el mantenimiento. En la mayoría de las instalaciones, /var/spool/lpd es el directorio spool principal, y cada impresora tiene un subdirectorio particular, con el mismo nombre que la impresora. Así, si tiene una impresora llamada PJL-16 que admite PostScript y HPGL, debería crear dos directorios, por ejemplo /var/spool/lpd/PJL-16-ps y /var/spool/lpd/PJL-16-hpgl.

Los directorios temporales deberían pertenecer a root, grupo lp; user y group deben poder leer y escribir, y el resto, leer (permiso 0775). Para cada directorio de impresora, la orden adecuada es

[root#pantano:~]# chmod ug=rwx,o=rx PJL-16-ps

Page 69: Tutorial del shell

[root#pantano:~]# chgrp lp PJL-16-ps

O, en otra notación

[root#pantano:~]# chmod 775 PJL-16-ps[root#pantano:~]# chown .lp PJL-16-ps

Los destinos, permisos y propietarios aquí indicados deben considerarse como indicativos, pues pueden variar entre distintos sistemas e instalaciones.

Además de los programas ya tratados, cada directorio temporal debe contener como mínimo cuatro ficheros, .seq , errs , lock y status, y deberán tener permisos 0664. El fichero .seq contiene la secuencia de trabajos enviados. status contiene el mensaje que devuelve "lpc stat". El fichero lock impide al lpd imprimir al tiempo dos trabajos en la misma impresora, y errs guarda un registro de los fallos de la impresora. El fichero errs es actualmente potestativo, y ahora puede llamarse como le apetezca. Su nombre se especificará en /etc/printcap. Debe, sin embargo, existir un fichero que permita a lpd registrar los mensajes de error.

/etc/printcap

/etc/printcap es un fichero texto, modificable con su editor favorito. Su propietario debe ser root y debe tener permisos 0644.

Aunque a golpe de vista parezca tan comprensible como la piedra Rosetta, su estructura es muy sencilla y asequible. Parte de la mala fama se debe a que algunas distribuciones no incluyen página de manual para printcap, y el hecho de que muchos printcap están generados por programas, o por gente cuya manera de despreciar al género humano es omitir comentarios que ayuden a su comprensión. Desde aquí hacemos un llamamiento para que su fichero printcap sea tan legible como sea posible.

Cada entrada de printcap describe una impresora. Mejor aún, cada entrada de printcap provee una denominación lógica para un dispositivo físico, y describe cómo deben los datos ser enviados y manejados por él.

Por ejemplo, una entrada de printcap definirá qué puerto vamos a usar, qué directorio spool, qué proceso deben soportar los datos, qué clase de errores debemos notificar, qué volumen de datos se permiten enviar como máximo, o limitar el acceso de ciertos dispositivos.

Además, podemos definir distintos modos de procesar datos para una misma impresora. Por ejemplo, una misma impresora de HP puede manejar datos en formatos PostScript, HPGL y PCL, dependiendo de la secuencia de órdenes que le enviamos al comienzo de cada trabajo. Tendría sentido definir los tres modos de trabajo como sendas impresoras, cada una de las cuales procesará los datos dependiendo del modo de trabajo. Los programas que generan datos ps se enviarán a la impresora PS, los dibujos HPGL a la impresora HPGL, y así sucesivamente. Llamaremos "filtros" a los programas que procesan los datos a imprimir. Un filtro puede incluso no enviar ningún dato al puerto.

Un ejemplo típico de entrada en /etc/printcap podría ser

Page 70: Tutorial del shell

# Ejemplo de printcap con dos alias impresoraHP|HP850C:\# lp es el dispositivo de impresión, en este caso,# la primera impresora:lp=/dev/lp1:\# sd indica el directorio spool:sd=/var/spool/lpd/HP850C:

Como vemos, cada entrada de /etc/printcap se estructura en una serie de campos, encabezados por una etiqueta, y limitados por dos puntos, a excepción del primer campo, que describe la impresora. Los campos pueden tener tres tipos de valores: texto, lógico y numérico, en los que nos extenderemos más adelante. La primera línea de la entrada determina el nombre y alias de la impresora. La impresora por defecto debería llamarse "lp"; por ejemplo, si la impresora del ejemplo anterior es la única que tenemos, la primera línea sería

# Ejemplo para la impresora por defectolp|HP850C:\

Sólo podemos tener una impresora llamada "lp".

Podemos usar el nombre que nos apetezca como "La Picadora de papel del despacho de Gertrudis", aunque no parezca quizá muy práctico. Los siguientes campos son los más comunes, y los más importantes:

Tabla 1. Campos en /etc/printcap

Campo Tipo Descripción

lp Texto Dispositivo de impresión (ej. /dev/lp1)

sd Texto Nombre del directorio tampon de esta impresora

lf Texto Fichero que almacena el registro de errores

if Texto Nombre del filtro de entrada

rm Texto Nombre del host de impresion remota

rp Texto Nombre de la impresora remota

sh Lógico Suprime las páginas que separan los trabajos

sf Lógico Suprime las paginas en blanco al final del trabajo

mx Numérico Tamaño máximo del trabajo de impresión (en bloques)

Veamos ahora estos campos con un poco más de detalle.

lp

Apunta al puerto/dispositivo de impresión. Si especificamos /dev/null como dispositivo, el resto de los procesos se ejecutan normalmente, pero los datos de

Page 71: Tutorial del shell

salida van a parar al inodoro. No se utiliza a excepción de las pruebas de configuración del dispositivo. Cuando configure una impresora remota con los campos rm y rp , debería poner ":lp=:" en /etc/printcap, indicando que no está asignada a ningún dispositivo local.. No deje este campo en blanco a menos que use una impresora remota, o el demonio de impresión se quejará amargamente, si no especifica un dispositivo de impresión.

lf

Guarda un registro de los errores de impresión. Cualquier fichero que especifique deberá existir antes de su uso, o no se registrarán las incidencias.

if

Indica el nombre del filtro de impresión a ejecutar. Los filtros son programas que reciben datos por la entrada estándar, y los devuelven procesados por la salida estándar. Un empleo típico es detectar texto llano y convertirlo en PostScript para imprimirlo en ese tipo de trastos. Son muy útiles, por ejemplo, para eliminar el efecto escalera, o cambiar la página de códigos sin necesidad de cambiar la configuración de la impresora cada vez que la usemos entre UNIX y DOS. Cuando se especifica un filtro de entrada, el demonio de impresión no envía los datos pendientes al dispositivo especificado. En su lugar, arranca el filtro y asigna el fichero temporal a la entrada estándar, y el dispositivo de impresión como salida estándar.

rm y rp

Controlan el destino de la impresión remota. Enviar el documento a imprimir a una impresora remota es tan fácil como indicar el anfitrión en rm, la impresora correspondiente en rp, y asegurarse que lp está vacío. Fíjese en que los datos se tamponan localmente antes de ser enviados, y que le ejecutará cualquier filtro que especifique. Una entrada típica de /etc/printcap en la máquina local (pera.huerta.net) para trabajar sobre la impresora picapapel, en la estación rábano.huerta.net (remota), sería:

picapapel::lp=::rm=rábano.huerta.net::rp=picapapel:\:sd=/var/spool/lpd/picapapel:

En la máquina remota necesitará que /etc/hosts.equiv o /etc/hosts.lpd contenga la línea pera.huerta.net; Tenga cuidado con los permisos de acceso.

sh y sf

Portadillas y separadores. Salvo que haya mucha gente distinta usando su impresora, probablemente no estará interesado en las páginas separadoras de trabajos. Las páginas de fin de trabajo son particularmente molestas cuando se trabaja con procesadores de texto, que componen páginas completas, por lo que si especificamos sf, tendremos al final de cada trabajo una página en blanco. sf es muy útil, sin embargo, si usamos la impresora para listar directorios, ficheros en crudo ..., asegurándonos que el trabajo sale completo de la impresión. Se

Page 72: Tutorial del shell

puede presentar un problema si tenemos una impresora PostScript, al quedar residente el último tipo de letra utilizado. Con el campo :tr: lo evitaremos. Es preferible en estos casos dejar :sh:, y que sean los filtros quienes se encarguen de generar las portadillas.

mx

Limita el tamaño del spool de datos, señalando una cantidad en bloques de 1 K ( 1024 bits ). Si mx=0, el límite viene dado por el espacio disponible en disco. Recuerde que lo que limitamos es el tamaño del spool, no la cantidad de datos impresos. Si intentamos sobrepasar el límite, el fichero simplemente se trunca, y el usuario recibe el mensaje

lpr: fichero: copy file is too large.

mx es útil si tiene programas que accidentalmente pueden generar un volumen desproporcionado de datos a imprimir (imágenes, por ejemplo); para impresoras ps, no suele tener mucho interés, pues un volumen pequeño de datos en formato ps pueden generar una notable cantidad de papel impreso. Podemos sustituir el límite de mx escribiendo en cada directorio spool un fichero llamado minfree que contiene el espacio mínimo disponible que permita aceptar trabajos, en forma de fichero texto con el número de bloques mínimos disponibles. Normalmente, suele ser un enlace con el original en /var/spool/lpd, ya que es inusual que cada impresora deba tener un mínimo diferente.

Probemos ahora /etc/printcap con un ejemplo. El siguiente guión de shell es un filtro de entrada muy simple. Sólo encadena su entrada al final de un fichero en /tmp, tras una pancarta adecuada. Usaremos este filtro en el campo if, y enviaremos los datos a /dev/null, ahorrándonos las quejas del demonio especificando un dispositivo de impresión.

#!/bin/sh# Este filtro debera colocarse en el directorio tampon,# con el nombre filtro_entrada, propiedad de root,# grupo lp y permisos 0755#echo -------------------------------------->/tmp/testlp.outdate >> /tmp/testlp.outecho -------------------------------------->>/tmp/testlp.outcat

Y aquí tenemos nuestra flamante entrada en /etc/printcap. Vea que el formato es razonablemente inteligible, usando caracteres de continuación de línea "\" al final de cada una, excepto la última (de hecho, cada entrada en /etc/printcap es una sola línea)

impre|PLJ-H1998:\ :lp=/dev/null:\ :sd=/var/spool/lpd/PLJ-H1998:\ :lf=/var/spool/lpd/PLJ-H1998/errores:\ :if=/var/spool/lpd/PLJ-H1998/filtro_entrada:\ :mx#0:\ :sh:\ :sf:

Page 73: Tutorial del shell

No deje espacios en blanco, o no funcionará (le aparecerán impresoras sin nombre, no logrará volcar los trabajos, y se acumularán en cola generosamente)

Ahora, hagamos que esto trabaje

1. DEBE SER EL SUPERUSUARIO (root), tanto si le gusta como si no.2. Compruebe los permisos y situaciones de lpr, lprm, lpc, lpq y lpd.3. Cree el directorio spool de su impresora: (recuerde que el propietario debe ser

root, el grupo lp, y los permisos 0775 con las órdenes

mkdir /var/spool/lpd /var/spool/lpd/imprechown root.lp /var/spool/lpd /var/spool/lpd/imprechmod ug=rwx,o=rx /var/spool/lpd /var/spool/lpd/impre

4. En el directorio spool cree los ficheros necesarios, con los debidos permisos y propietarios

cd /var/spool/lpd/impretouch .seq errores status lockchown root.lp .seq errs status lockchmod ug=rw,o=r .seq errs status lock

5. Cree el script filtro de entrada en el directorio spool. Use por ahora el filtro de prueba anterior. Asegúrese que el fichero pertenece a root.lp, y es ejecutable para todos.

6. Cree el fichero /etc/printcap tal y como lo hemos descrito en el punto anterior. Su propietario será root y sus permisos 0644.

7. Compruebe que rc.local (normalmente en /etc/rc.d/) contiene la línea /sbin/lpd, y añádala si no está. Esto hace que arranque el demonio de impresión al arrancar. De todos modos puede arrancarlo a mano con la orden lpd.

8. Haga una prueba: cruce los dedos y tecleels -l | lpr -Pimpre

9. Busque en /tmp un fichero llamado testlp.out. Debería contener un listado del directorio, con un encabezado.

10. Si ha funcionado (y no dudamos que habrá sido así), edite /etc/printcap, y copie la entrada de prueba en el mismo fichero. En la primera entrada, cambie el nombre de la impresora a testlp, o el que usted prefiera, pero que no use como nombre real de impresora. En la segunda entrada (que ahora será la de su impresora real), cambie el contenido de lp=/dev/null al del puerto de impresora (normalmente será /dev/lp1) de su ordenador, salvo que vaya a utilizar una impresora remota, en cuyo caso deberá definir rm y rp. Cambie el nombre del filtro if si tiene ya uno previsto, o suprímalo si no va a utilizar ninguno.

11. Reinicie el sistema, o mate el demonio de impresión y arránquelo, ya que lpd sólo lee /etc/printcap al comenzar su trabajo.

12. Haga una prueba, y aprecie lo bien que funciona su impresora.

Para añadir nuevas impresoras, sólo tendrá que repetir la entrada de printcap, con las modificaciones pertinentes a cada dispositivo.

Impresión remota e impresión local

Page 74: Tutorial del shell

La impresión remota nos permite enviar trabajos de impresión desde una máquina, hacia otra (computadora/impresora) conectada a una red; por ejemplo, nuestro equipo funciona de servidor en una red, o si una impresora asignada a nuestra máquina debe ser accesible por otros ordenadores.

Imprimimos localmente cuando usuarios de nuestra máquina envían trabajos a una impresora conectada directamente a la misma.

Como primer paso, cualquier máquina que intente imprimir en su sistema, debe estar registrada en cualquiera de los ficheros /etc/hosts.equiv o /etc/hosts.lpd, que son simples ficheros de texto, con un nombre de maquina por línea. Es preferible el segundo, reservando el primero para proporcionar mayores permisos de acceso, lo que debería ser evitado en lo posible.

Puede restringirse el uso tanto por nombre como por grupos. Especifique los grupos autorizados con uno o varios campos :rg: en /etc/printcap. :rg=admin: sólo autorizará el acceso a la impresora a los usuarios asignados al grupo admin. Puede también limitar el acceso a aquellos usuarios con cuenta en su sistema utilizando el campo lógico :rs:.

La configuración en el sistema cliente sería la siguiente

lp|Remote printer entry:\ :lp=/dev/null\ :rm=192.168.1.1:# Aquí puede ir también el nombre del #servidor de impresión. :rp=lp:\ :sd=/var/spool/lpd/remote:\ :mx#0:\ :sh:

Actualización del sistemaUna tarea que es muy importante para el administrador es la de mantener actualizado el sistema y la instalación de nuevo software en él. Dado que el mundo de GNU/Linux se mueve muy rápidamente se tendrán que tener los recaudos necesarios para que el sistema que se esta administrando no quede pronto obsoleto. Ahora esto no hay que confundirlo con que se tenga que estar pendiente de todo lo que cambia en nuestro sistema, ya que si así lo hiciéramos nos pasaremos mas tiempo actualizándolo que usándolo.

Mucha gente siente la necesidad de actualizar el sistema cada vez que una versión nueva de la distribución que se esta usando sale, pero esto también es una perdida de tiempo ya que no todo el sistema cambia por lo que no se justifica la compra de una nueva distribución o el bajarse los 6 discos que la componen. Por esto, la mejor forma de realizar una actualización del sistema es haciéndola a mano, lo que trataremos de ver con unos puntos clave del sistema como lo son el kernel, las bibliotecas y el software esencial para el funcionamiento óptimo del sistema.

Page 75: Tutorial del shell

Actualizando el núcleoLa actualización del núcleo o kernel del sistema no es bajarse el código fuente de este y realizar una compilación. Esto permite habilitar ciertas funciones que no vienen en los kernel pre-compilados o puede desactivar otras que no son necesarias.

Los fuentes del kernel se pueden obtener de numerosos sitios de ftp. El más conocido es el de kernel.org cuya página es http://www.kernel.org y el ftp es ftp://ftp.kernel.org . Los kernel se encuentran indexados por el número de la versión (ej v2.4) donde se encontraran los sucesivos niveles de parche de cada versión (ej 2.4 parche 18 seria 2.4.18). El kenel vendrá comprimido en dos formas posibles, tar.gz y tar.bz2. Este último sistema de compactación es mucho más eficiente que gz.

El método para descomprimirlos es el habitual, se recomienda la lectura de las páginas de manual de cada uno de los métodos de compactación para efectuarlo. Se deberá realizar la descompresión en el directorio /usr/src donde se creara un directorio con el nombre de la versión del kernel y su nivel de parche. Existe un enlace que estará apuntando a los fuentes del kernel anterior denominado linux. Este enlace deberá cambiarse para que apunte al código del kernel nuevo.

[root#pantano:/usr/src]# ln -sf /usr/src/2.2.16 /usr/src/linux

Hay que tener en cuenta que para realizar la compilación del kernel se deberá contar con los compiladores necesarios. Estos son el gcc y el g++ que son los compiladores de C y C++ que deberán estar instalados en el sistema. Mas adelante veremos como podremos tener una versión reciente de estos.

Una vez que nos sesionamos que tenemos todo lo necesario se procederá a ejecutar el programa de configuración del kernel. Existen 3 formas de realizar esto: La primera y menos recomendable es el ejecutar en el directorio /usr/src/linux la sentencia "make config" que correrá un script que nos preguntaran uno a uno todos los aspectos del kernel. Esta forma es por demás de tediosa y no la veremos aquí.

Otra forma es realizarlo a través de un front-end gráfico realizando un make xconfig con lo que tendremos una vista bastante cómoda para efectuar la configuración. El problema que puede presentarse aquí es que no se cuente con los paquetes de desarrollo del lenguaje Tk que se utilizan para el programa en X por lo que posiblemente no funcione en algunos sistemas.

Una tercer forma es la de ejecutar make menuconfig que nos levantará un programa de configuración pero de consola y es la forma que funciona de forma más cómoda.

La sugerencia es que se tome como punto de partida la configuración del kernel anterior. Esta puede tomarse al haberse guardado en un archivo que podrá tener un nombre como "configuración.kernel.fecha" o el que se les ocurra. SI no lo tienen lo pueden generar a partir del programa de configuración del kernel anterior solicitándole que guarde la configuración en un archivo. Opción que aparece en la parte inferior de la ventana de configuración en el menuconfig. Ahora se puede tomar con la opción de carga de configuración del kernel nuevo, la configuración anterior y modificarla según nuestros requerimientos. Una vez realizado los cambios de configuración necesarios se

Page 76: Tutorial del shell

recomienda el guardar la configuración en un archivo, además de en el mismo kernel, para futuros cambios.

Cuando se termina de configurar, se le instará al ejecutar make dep y make clean. Al hacer make dep se prepararán las dependencias necesarias para efectuar la compilación. Cuando acabe, hay que hacer un make clean. Esto elimina ficheros objetos y demás de la versión anterior. No olvidar este paso.

Después de preparar dependencias, puede ejecutar make zImage o make zdisk (esta es la parte que tarda más tiempo). make zImage compilará el núcleo y lo dejará comprimido en arch/i386/boot/zImage junto a otros ficheros. Con make zdisk el nuevo núcleo se copiará además en el disquete que esté puesto en la disquetera /dev/fd0. Esto es interesante para probar núcleos; si explota (o simplemente no hace nada) se quita el disquete de la disquetera y se podrá arrancar el núcleo antiguo. Además sirve para arrancar si se borró accidentalmente el núcleo del disco duro.

Otra opción es efectuar la compactación del kernel con un método más eficiente dado que el LILO se pone nervioso con núcleos muy grandes. Por esto se podrá efectuar un make bzImage lo que compactara aún mas el kernel. Un núcleo comprimido se descomprime automáticamente al ser ejecutado. Una vez que se tenga un nuevo núcleo que parezca funcionar como se desea, será el momento de instalarlo. Casi todo el mundo utiliza LILO (LInux LOader) para esto. Una forma muy cómoda de llevar todo el tema del LILO, si lo tenemos instalado, y las compilaciones, etc, es añadir lo siguiente en el /etc/lilo.conf

...image=/vmlinuz label=ultimo root=/dev/hd[loquesea] read-only append = ""image=/vmlinuz.old label=anterior root=/dev/hd[loquesea] read-only append = ""

Al compilar, si lo hacemos con la secuencia de comandos

[root#pantano:/usr/src/linux]# make dep[root#pantano:/usr/src/linux]# make clean[root#pantano:/usr/src/linux]# make zlilo[root#pantano:/usr/src/linux]# make modules[root#pantano:/usr/src/linux]# make modules_install

El make zlilo renombrará la anterior imagen del kernel a /vmlinuz.old, dejando la nueva como /vmlinuz, e instalará LILO, a continuación con lo cual lo hacemos todo automáticamente.

La órdenes make modules; make modules_install compilarán los módulos que hayamos seleccionado, y los instalarán. No hay olvidar ejecutar depmod -a en cuanto hayamos arrancado con dicho núcleo. En caso de que estemos compilando por segunda vez una misma versión de núcleo, y hayamos variado el número de módulos a compilar,

Page 77: Tutorial del shell

es posible que la ejecutar make dep nos encontremos con un mensaje de error; esto se debe a que los antiguos módulos que no hayamos compilado ahora no son borrados. Pueden borrarse tranquilamente.

Actualizando las bibliotecasLa mayor parte del software de GNU/Linux esta compilado para que utilice bibliotecas compartidas, por esto muchas veces se requieren juego de bibliotecas mas recientes para un determinado programa. Las bibliotecas son compatibles en forma ascendente, es decir que un programa compilado para una versión antigua de bibliotecas funcionará igual con una versión mas reciente de las mismas pero lo contrario no se aplicará.

Las últimas versiones de las bibliotecas de GNU/Linux puede encontrarse en los servidores de ftp://ftp.suncite.unc.edu. Los archivos de "versión" que se encuentran allí deberán explicar el proceso de instalación. Se deben bajar los ficheros image-versión.tar.gz y inc-versión.tar.gz donde versión es la versión de las bibliotecas a instalar, por ejemplo 4.4.1. Son ficheros tar comprimidos con gzip; el fichero image contiene las imágenes de las bibliotecas a instalar en /lib y /usr/lib. El fichero inc contiene los ficheros de inclusión a instalar en /usr/include.

El fichero release-versión.tar.gz debe explicar el método de instalación detalladamente (las instrucciones exactas varían para cada versión). En general, se necesita instalar los ficheros de bibliotecas .a y .sa en /usr/lib. Estas son las bibliotecas utilizadas en tiempo de compilación.

Además, los ficheros imagen de las bibliotecas compartidas libc.so.version se instalan en /lib. Estas son las imágenes de las bibliotecas compartidas que son cargadas en tiempo de ejecución por los programas que utilizan las bibliotecas. Cada biblioteca tiene un enlace simbólico utilizando el número de versión mayor de la librería en /lib.

Por ejemplo, la versión 4.4.1 de la librería libc tiene un número de versión mayor de 4. El fichero que contiene la librería es libc.so.4.4.1. Existe un enlace simbólico del nombre libc.so.4 en /lib apuntando a este fichero. Por ejemplo, cuando se actualiza de libc.so.4.4 a libc.so.4.4.1, necesita cambiar el enlace simbólico para apuntar a la nueva versión.

Es muy importante que se cambie el enlace simbólico en un solo paso, como se indica más abajo. Si de alguna forma borrase el enlace simbólico libc.so.4, los programas que dependen del enlace (incluyendo utilidades básicas como ls y cat) dejarán de funcionar. Utilice el siguiente comando para actualizar el enlace simbólico libc.so.4 para que apunte al fichero libc.so.4.4.1

[root#pantano:~]# ln -sf /lib/libc.so.4.4.1 /lib/libc.so.4

Se necesita también cambiar el enlace simbólico libm.so.version de la misma forma. Si se está actualizando a una versión diferente de las bibliotecas, sustituya lo anterior con los nombres adecuados. La nota de la versión de la librería debe explicar los detalles. (Ver sección sobre enlaces simbólicos para más información).

Page 78: Tutorial del shell

Actualizando gccEl compilador de C y C++ gcc se utiliza para compilar software en su sistema, siendo el más importante el núcleo. La versión más reciente de gcc se encuentra en los servidores FTP de Linux. En sunsite.unc.edu se encuentra en el directorio /pub/Linux/GCC (junto con las bibliotecas). Debe existir un fichero release para la distribución gcc detallando qué ficheros se necesitan obtener y como instalarlos.

El sistema X-Window

Orígenes de XVamos a dar un concepto sencillo de X Window y luego lo ampliaremos. El sistema X Window es un método grafico y distribuido para trabajar. Y ahora veremos por que. El X Window System es prácticamente el estándar de los entornos gráficos para usuarios de Unix, pero no es solo eso, es un completo sistema para redes que permite ejecutar aplicaciones X desde una computadora en la otra parte del globo de donde se encuentra el servidor, a través de Internet.

Primero lo primero. El consorcio de tecnología X requiere que se usen los siguientes nombres cuando se refiere al sistema X Window

X X Window System

X Version 11

X Window System, Version 11

X11

Por lo tanto cualquiera de estos nombres es sinónimo del mismo software. X Window SystemTM es una marca registrada de X Consortium, Inc.

El X11 se desarrolló gracias a la cooperación entre DEC (Digital Equipment Corporation, luego adquirida por Compaq) y el proyecto Athena del MIT (Massachussets Institute Of Technology). La primera versión, la X11R1, salió en septiembre de 1987. Desde la versión 6 (X11R6) la X Consortium Inc y desde 1996 The Open Group continuaron con el desarrollo del X Window System.

Existe una implementación libre del sistema X para sistemas Unix y se denomina XFree86. Este se sigue desarrollando por programadores en todo el mundo, que se unieron en 1992, formando el Xfree86-Team. De esta unión surgió en 1994 la empresa The XFree86 Proyect Inc cuyo objetivo es poner Xfree86 a la disposición de un amplio público y contribuir con el desarrollo e investigaciones del sistema X Window. Es de esta manera que el sistema operativo GNU/Linux adopta esta distribución libre del sistema X para brindar un entorno gráfico mas amigable.

Page 79: Tutorial del shell

X - Puntos básicosUna sesión de X esta compuesta por lo general de varias ventanas donde cada una de ellas ejecutan un programa aislado. Al igual que los programas en cualquier otro sistema, los programas que se ejecutan en X varían en cuanto a su funcionalidad.

Algunos necesitan de la interacción con el usuario y otros solo despliegan datos en la pantalla. A la ventana de fondo se la conoce como ventana raíz (root window). Las ventanas de aplicación se despliegan encima de la ventana raíz. Al igual que los procesos en Un*x estas ventanas están agrupadas o relacionadas de acuerdo a una jerarquía. Así es que la ventana raíz es el padre de todas las demás ventanas. Ahora, para entender un poco mas este tipo de funcionamiento pasaremos a explicar en que consiste.

X esta formado de dos partes: un lado servidor y un lado cliente. La funcionalidad básica es familiar a la forma en que trabajan todos los modelos cliente-servidor, en el sentido de que el servidor X tiene determinados recursos que proporciona al cliente. Debido a que el servidor X esta integrado a las pilas TCP/IP las peticiones pueden venir de cualquier cliente y pueden ser solicitadas a cualquier servidor. Además, debido a que X, además de ser un programa específico, define además un protocolo, los clientes pueden comunicarse con servidores X en otro tipo de plataforma. El servidor actúa como una interfaz entre los programas clientes y el hardware físico.

Cuando se proporcionan datos, ya sea por medio del teclado o el mouse, el servidor acepta la entrada y es responsable de pasarla al cliente. Esta información se pasa al cliente como un evento. Una tecla apretada o el movimiento del mouse generan un evento ante el cual reaccionará el cliente.

Page 80: Tutorial del shell

Figura 1. Aspecto de algunos clientes típicos

Este evento genera una reacción en el cliente para que presente un cambio en la pantalla como podría ser el desplegado de un menú. Estos se realizan de la siguiente manera: El usuario realiza un clic de mouse en el cliente. Este solicita al servidor que muestre un menú desplegable. El servidor pasa la información al hardware, que muestra el menú desplegable en la pantalla. Como resultado de esta separación de funcionalidades, un cliente puede desplegar información en más de un servidor. Para iniciar cualquier cliente se deberá haber iniciado el servidor X en algún lugar de la red o, como es común, en la misma máquina que se están ejecutando los clientes.

Al contrario de lo que podría suponerse, ni el servidor ni los clientes son responsables de la apariencia de las ventanas en la pantalla tal como lo entendemos. Ester trabajo le corresponde a un "administrador de ventanas" (WM por window manager). La mayoría de las distribuciones actuales trae los varios WM diferentes, proporcionando interfaces que difieren entre sí y pueden configurarse y adaptarse a los gustos de los usuarios. También vienen los entornos de escritorio KDE o Gnome como estándar, los que proporcionan mayor grado de integración entre aplicaciones y trabajan de formas diferentes. El WM también es el encargado de controlar los íconos en la pantalla. A continuación se muestra el aspecto de algunos administradores de ventanas. Si se quiere una descripción más detallada acerca de los WM disponibles consultar http://xwinman.org (en inglés)

Page 81: Tutorial del shell

Figura 2. Aspecto del WM Windowmaker

Figura 3. Aspecto del WM BlackBox

Page 82: Tutorial del shell

Figura 4. Aspecto del WM xfce

Figura 5. Aspecto del WM fvwm95

Requisitos de HardwareX puede operar con 32 MB de RAM física pero de seguro que lo que menos se podrá hacer es trabajar de manera cómoda, ya que al abrir un par de ventanas notaremos como caerá notablemente el rendimiento al comenzar a intercambiar información con el disco rígido.

Por esto, la memoria RAM es un punto clave a tener en cuenta a la hora de instalar X. 64 MB de RAM harán que se pueda trabajar cómodamente en un entorno que requiera de pocos recursos como el WindowMaker.

Page 83: Tutorial del shell

En lo que respecta la placa de video, se tendrá que buscar alguna que tenga pocos problemas de configuración. Hoy día casi todas las placas de video (los chips de video, para ser más específicos) soportan el modo VESA 2.0, con lo cual se las puede hacer trabajar con el driver de esta norma a 1024x768 píxeles, en 32 bits de colores, aunque de esta manera estaríamos desperdiciando parte de la potencia de nuestro controlador de video[1]. En lo que respecta a fuerza de cómputo pura, un sistema Pentium será suficiente para un entorno poco exigente y se requerirá de un Pentium III o superior para entornos como el KDE y el Gnome que son monstruos devoradores de recurso.

Notas

[1] Lo cual en algunos casos puede ser irrelevante. Por experiencia personal, aun en este caso con una máquina nueva puedo reproducir 4 videos DivX a la vez. Solo será necesario disponer de toda la potencia de la tarjeta gráfica cuando se corran resoluciones superiores a esta o juegos con muchos requerimientos.

Configuración de Xfree86Por lo general, cuando instalemos GNU/Linux ya tendremos instalado el sistema XWindow y configurado. Sin embargo, si hemos instalado Debian o Slackware aun tendermos que configurarlo. Para esto se debe de crear el archivo de configuración /etc/X11/XF86Config o /etc/X11/XF86Config-4. Este se puede crear a mano o con alguno de los siguientes programas: xf86config o xf86cfg. Antes de correr alguno de los programas de configuración de XWindow se debe tener a la mano la siguiente información: marca, modelo y cantidad de memoria de la tarjeta de video; marca, modelo del monitor y frecuencia horizontal y vertical del monitor; datos del mouse (ratón) y teclado que utilizaremos.

Configuración mediante xf86cfgPor supuesto que lo primero que tendrán que cerciorarse es que los archivos necesarios estén instalados antes de correr este programa. Si no fuese así un mensaje les advertirá por pantalla de esto. Una vez que se ejecuta como root desde la consola el programa xf86cfg

[root@pantano:~]# xf86cfg

un cuadro de dialogo le preguntara si se quiere utilizar el archivo de configuración existente. Este archivo se instala por defecto al instalarse los archivos de XFree, pero muy pocas veces funciona sin modificaciones. Sirve para ejemplo y punto de partida para una configuración a medida.

XF86cfg intentará arrancar el sistema gráfico en modo VESA, por lo que esto funcionará en la mayoría de las máquinas modernas. Si se detectan exitosamente todas nuestras configuraciones de hardware, se podra ver una ventana similar a la que se muestra a continuación.

Page 84: Tutorial del shell

Figura 6. Aspecto de la ventana de xf86cfg

En este momento estamos configurando el Layout del servidor, es decir la disposición física de los diferentes dispositivos (Boton superior izquierdo, Configure Layout). Como podemos observar, las configuraciones más importantes se dividen en cuatro secciones representados por los botones superiores, a saber mouse, teclado, tarjeta de video y monitor. El hardware detectado se muestra en la parte inferior, en el gráfico que une las "partes" de nuestra máquina. A continuación podremos efectuar las modificaciones que querramos, haciendo click con el botón derecho sobre el dispositivo a configurar y eligiendo la opción configure.

Si por casualidad nuestro mouse fué mal detectado (caso común cuando disponemos de un mouse serie pero nuestra máquina posee además bus ps2), podremos utilizar las teclas del teclado numérico para mover el puntero en pantalla tal como se muestra a continuación.

Figura 7. Ayuda en caso de mouse mal detectado o ausente

En caso de que la detección de video sea mal detectada y no pueda arrancar el modo gráfico, aun se puede usar el programa de configuración en modo texto, con el comando xf86cfg -textmode, el cual nos abrirá el mismo programa con menúes interactivos. También podemos usar el comando xf86config, el cual nos irá preguntando una a una las opciones para cada caso.

Mouse

En esta pantalla se podrá configurar el mouse que funcione en nuestro sistema, aunque ya lo hayamos realizado en la consola. En la pantalla que vemos a continuación se

Page 85: Tutorial del shell

muestran las opciones Identifier (se puede dejar tal cual como está), y lo más importante, mouse device y mouse protocol.

Figura 8. Menú de configuración del mouse

El primero se refiere al puerto físico que está conectado el mouse. Si se trata de un mouse serie el mismo será seguramente /dev/ttyS0 o /dev/ttyS1. Si se trata de un mouse ps2 será /dev/psaux. En cuanto al protocolo, puede dejarse en Auto la mayoría de las veces. Algunos protocolos pueden activar características especiales del mouse, por ejemplo la rueda. La opción Emulate 3 buttons permite que teniendo un mouse de dos botones, apretando los dos a la vez se comporte como un tercer botón.

Teclado

Hay que configurar nuestro teclado de acuerdo a dos aspectos fundamentales: el idioma y el modelo. A continuación se muestra la pantalla de configuración del teclado.

Figura 9. Menú de configuración del teclado

Las opcion xkb rules debe ser xfree86. Los parámetros más importantes son Keyboard model, el cual en los teclados comunes con "teclas muertas" (dead keys) que usa cierto sistema operativo será Generic 105-key (Intl) PC para teclado español (104-keys para uno americano), y Keyboard layout, en nuestro caso casi siempre Spanish.

Page 86: Tutorial del shell

Las opciones siguientes permiten seleccionar aspectos más avanzados de nuestro teclado, como que hacer con las teclas muertas, administrar el comportamiento de las teclas CapsLock-Shift, etc.

Placa de Video

Este punto es crucial y por demás de complicado cuando no se tiene la documentación de la placa. Lo mejor que puede uno hacer es leer los README que vienen con X para ver si existe compatibilidad con nuestra placa de video. Si se sabe cual es el tipo de placa y esta aparece listada, es un procedimiento inmediato, pero si no se tendrá que probar con una placa genérica que supla los requerimientos de nuestra placa de video. A continuación vemos la pantalla de configuración de la placa de video.

Figura 10. Menú de configuración de la placa de video

Si nuestra placa no está listada por lo general la placa VESA es una buena opción. Si esta no funciona tambien se dispone de el controlador vga generic, el cual debería funcionar en casi cualquier hardware.

Lo que se tiene que tener en cuenta es el chipset de nuestra placa ya que será un indicativo para hallar una sustituta. La RAM que posee también tendrá que ser especificada y se recomienda leer los archivos de README para configurar placas aceleradoras.

Monitor

La configuración del monitor se basa en saber las frecuencias verticales y horizontales de trabajo del mismo, lo que se podrá obtener de la documentación provista o del sitio del fabricante.

Page 87: Tutorial del shell

Figura 11. Menú de configuración del monitor

En este punto hay que tener especial cuidado dado que en los viejos monitores un error podía ocasionar que se quemara el mismo. Los monitores nuevos en general no sufren este problema, ya que tienen protección contra estos accidentes. Elegiendo un monitor de la lista se seleccionaran automáticamente el Horizontal Sync y el Vertical Sync.

Screen

Ahora que hemos configurado nuestros dispositivos físicos pasaremos a configurar el aspecto que presentará nuestra pantalla. Para eso, con el botón superior izquierdo en la pantalla principal de xf86cfg seleccionamos Configure Screen, y el aspecto de la misma cambiará como se muestra a continuación.

Figura 12. Configuración del aspecto de pantalla (screen)

Haciendo click derecho sobre el monitor elegimos configure y podremos seleccionar la profundidad de colores y la resolución a la que querramos trabajar. Aqui vemos que se ha seleccionado 16 bits de profundidad de colores (65536 colores) y dos resoluciones, 640x480 y 800x600. Puede alternarse entre estas dos resoluciones apretando la cambinación de teclas Ctrl-Alt-+ y Ctrl-Alt--

Page 88: Tutorial del shell

Figura 13. Selección de resolución y profundidad de colores

Entornos gráficos de escritorioExisten además de los WM mostrados anteriormente entornos de escritorios, los cuales proveen un WM, utilidades varias y un framework de desarrollo que nos permitirán desarrollar aplicaciones que se integren al entorno perfectamente, compartiendo el look&feel del mismo y aprovechando servicios como arrastrar y soltar, servicio de impresión centralizado, un portapapeles común, etc. Algunos de estos entornos son KDE, Gnome, GNUStep y CDE. Hablaremos solamente de los dos primeros que son, sin lugar a dudas, los más populares. El tercero es un esfuerzo por reimplementar las especificaciones OPENStep de NeXT, y parece haber quedado estancado. El último nombrado fué durante muchos años el rey en los ambientes UNIX corporativos, pero ha quedado desfasado respecto a los dos primeros, además de no ser libre.

El entorno KDEKDE ofrece para GNU/Linux un entorno gráfico de configuración por demás de sencilla y con una apariencia homogénea entre las distintas aplicaciones. KDE es un proyecto de un grupo de programadores que se formo en 1996 y que siguen trabajando en el proyecto junto con muchos otros que fueron incorporándose. Ofrece su propio administrador de ventanas llamado kwin y además una serie de aplicaciones para hacerlo mas cómodo como el konqueror que es un administrador de ficheros que permite trabajar con ellos en una forma muy grafica a través de iconos.

Page 89: Tutorial del shell

Figura 14. Aspecto que ofrece KDE

Consta de gran cantidad de ayuda y esta totalmente realizada en HTML lo que facilita su lectura haciéndola mucho mas dinámica. Aparte las aplicaciones nuevas que se vayan instalando incorporaran también la documentación que posean a esta lista. Posee una gran variedad de aplicaciones como lo son un programa de correos, el kmail, block de notas, calculadora, y demás aplicaciones de utilidad. Posee también aplicaciones para Internet como un cliente para IRC y la posibilidad de realizar la conexión por dial-up de una forma por demás de sencilla a través del kppp.

EL KDE esta basado totalmente en URL. Esto significa que todas las ramas y referencias a archivos se procesan en un formato único por ejemplo se puede acceder a una pagina HTML, a un archivo local o a un sentido a través del mismo visualizado.

Tiene la posibilidad de realizar Drag&Drop entre las distintas aplicaciones por ejemplo arrastrando un archivo desde un lado a otro o al escritorio.

KDE esta desarrollado con las bibliotecas gráficas Qt, las cuales son parecidas en funcionamiento a otras bibliotecas muy conocidas en el mundo UNIX como lo son las Motif que facilitan la construcción de programas con base grafica, pero que son software no libre.

En un tiempo las bibliotecas Qt también fueron no libres, lo que frenó la adopción de KDE por cuestiones de licencias en algunas ditribuciones. Luego, la presión de la comunidad del software libre hicieron que estas se publicaran con una licencia dual, estando ahora bajo licencia GPL cuando se utilizan para desarrollo de software libre. Esto sin duda terminó de popularizar este desarrollo tecnicamente excelente.

La página del proyecto es http://www.kde.org donde puede encontrarse mucha información del mismo.

El entorno Gnome

Page 90: Tutorial del shell

Gnome es un acrónimo de 'GNU Network Object Model Environment', entorno de trabajo en red orientado a objetos, por lo que Gnome forma parte del más amplio proyecto GNU. Gnome es un entorno gráfico (escritorio de trabajo) amigable que permite a los usuarios usar y configurar sus ordenadores de una forma sencilla. Gnome incluye un panel (para arrancar aplicaciones y presentar el estado de funcionamiento), un escritorio ( donde se pueden situar los datos y las aplicaciones), un conjunto estándar de aplicaciones y herramientas de escritorio, y un conjunto de convenciones que facilitan la operación y consistencia de las aplicaciones entre sí.

Figura 15. Aspecto que ofrece Gnome

Los usuarios de otros sistemas operativos y entornos se sentirán como en casa cuando usen el potente entorno gráfico que proporciona Gnome. Gnome es en su totalidad código abierto (software libre), con el código fuente disponible libremente y desarrollado por cientos de programadores en todo el mundo.

Gnome tiene una serie de ventajas para los usuarios. EL mismo facilita el uso y la configuración de aplicaciones sin usar interfaces puramente textuales (console). Es altamente configurable, permitiéndole ajustar su escritorio con el aspecto que desee.

El gestor de sesiones de Gnome recuerda la configuración previa, de manera que una vez que haya configurado las cosas a su gusto, las mantendrá así. Soporta muchos idiomas, y puede añadir más sin cambiar el software. Soporta incluso varios protocolos de arrastrar y soltar para una máxima interoperabilidad con aplicaciones que no sean compatibles con Gnome.

Gnome tiene también una serie de ventajas para los programadores que indirectamente benefician también a los usuarios. Los programadores no necesitan comprar una cara licencia de software para hacer compatibles sus aplicaciones comerciales. De hecho, Gnome es independiente de cualquier compañía - ningún componente del interfaz esta controlado únicamente por una compañía o tiene restringidas la modificación o redistribución. Las aplicaciones Gnome pueden desarrollarse en una gran variedad de lenguajes de programación, por lo que el programador no se ve limitado a un solo

Page 91: Tutorial del shell

lenguaje de programación. Gnome usa la arquitectura universal de agentes de petición de objetos (CORBA) para permitir que los componentes software interactúen 'sin costuras', independientemente del lenguaje en el que estén implementados, o incluso de la máquina en la que se estén ejecutando. Finalmente, Gnome funciona en numerosos sistemas operativos de tipo Un*x, incluido GNU/Linux. El gestor de ventanas es la parte del software que controla las ventanas en el 'Entorno de ventanas X'. La posición, bordes, y estilo de cualquier ventana la maneja el gestor de ventanas. Esto es muy distinto en muchos otros sistemas operativos, y la forma en que Gnome dialoga con los gestores de ventanas es diferente de la de otros entornos de escritorio. Como se indicó anteriormente en esta guía, Gnome no depende de ningún gestor de ventanas. Esto significa que la mayor parte de su entorno de escritorio no cambiará si decide cambiar de gestor de ventanas. Gnome trabaja con el gestor de ventanas para proporcionarle el entorno de trabajo más amigable posible. Gnome no se preocupa de la colocación de las ventanas, sino que obtiene información sobre su posición del gestor de ventanas. El paginador («Pager») sólo funcionará con gestores de ventanas compatibles con Gnome, al igual que arrastrar y soltar en el escritorio.

Si quiere saber más sobre el proyecto Gnome puede visitar la página web del mismo en http://www.gnome.org

Detalle de comandos

Detalle de ComandosDetallaremos los comandos básicos que son de mayor utilidad en GNU/Linux, tratando de detallar en cada uno de ellos las opciones más utilizadas y las que necesitaremos más frecuentemente para un mejor funcionamiento de nuestro sistema. Muchos de estos comando se encontraran complicados a esta parte del curso, pero más adelante se entenderá su utilización. Por el momento tendrán que ser tomados solo como referencia y luego, al darse el tema especifico que los utiliza, se podrá consultar esta descripción para poder utilizarlo. Las opciones en su amplia mayoría se le dan al comando luego de un signo "-", por ejemplo ls -F. Además de las opciones con una sola letra, en muchas oportunidades nos encontraremos con opciones indicadas con palabras completas. Estas se expondrán seguidas de un doble signo "-", de la forma cat --number que es equivalente a cat -n. Los archivos que irán como argumento del comando se referenciaran de la forma <archivo[1]> <archivo[2]> <archivo[n]>. Para mayor información respecto a cada uno de estos comandos, se cuenta con las páginas de manual que nos mostraran todas las posibilidades. La sintaxis para leer las páginas de manual es la común

[shrek@pantano:~]$ man <comando>

alias: Este comando nos mostrará la lista de alias que existe en nuestro sistema. Los alias son nombres creados por los usuarios para ejecutar un comando o una serie de comando de manera más rápida. Estos están definidos en /etc/bashrc y tienen permiso de escritura por el usuario root. Un ejemplo de la salida del comando es el siguiente

Page 92: Tutorial del shell

alias fd='mount /dev/fd0 /mnt/floppy; cd /mnt/floppy && ls'alias l='ls -laF --color=tty'alias ldir='mount /mnt/floppy && ls /mnt/floppy && umount /mnt/floppy'alias ls='ls --color=tty'alias m='minicom -s -con -L'alias minicom='minicom -s -con -L'alias tm='tail -f /var/log/messages'alias tmm='tail -f /var/log/maillog'alias tms='tail -f /var/log/secure'alias ufd='cd /mnt && umount /floppy && ls'alias which='type -path'

awk: Es un lenguaje de programación que nos sirve para realizar búsquedas de patrones en archivos de textos. Entraremos en mayor detalle en el capítulo (reemplazar).

cal: Este comando, sin argumentos, nos mostrará el calendario del mes actual en el corriente año. Alguno de sus argumentos más usados son los que le indican el mes y el año que se quiere visualizar. Para ello solo hace falta invocarlo seguido por el número del mes y el año en cuatro dígitos.

[shrek@pantano:~]$ cal 8 2004 agosto de 2004do lu ma mi ju vi sá 1 2 3 4 5 6 7 8 9 10 11 12 13 1415 16 17 18 19 20 2122 23 24 25 26 27 2829 30 31[shrek@pantano:~]$

cat: Concatena e imprime archivos en la salida estándar. Con "cat" podremos tanto visualizar por pantalla como redireccionar hacia otro archivo, un archivo de texto común. También podríamos concatenar varios archivos para que sean visualizados todos juntos.

[shrek@pantano:~]$ cat archivo[1] archivo[2] archivo[3] ... archivo[n]

Opciones:

-b, --number-nonblank

Numera todas las líneas que contengan algún texto comenzando por 1.

-e

Es equivalente a -vE.

-n, --number

Numera todas las líneas de salida comenzando por 1.

-s, --squeeze-blank

Page 93: Tutorial del shell

Remplaza múltiples líneas en blanco con una sola línea en blanco.

-t

Es equivalente a -vT.

-u

Solo utilizado para compatibilidad con UNIX; es ignorado.

-v, --show-nonprinting

Muestra los caracteres de control.

-A, --show-all

Equivalente a -vET.

-E, --show-ends

Muestra un signo "$" inmediatamente después del final de línea.

-T, --show-tabs

Muestra los caracteres de tabulación (TAB), como '^I'.

--help

Muestra un mensaje de ayuda para el comando.

--version

Muestra la información de la versión que se esta usando del comando.

cd: (change Directory) Cambia a otro directorio. Si se invoca sin ningún argumento, nos llevara a nuestro directorio HOME. Esto lo hace ya que existe una variable de entorno cargada por el shell que indica cual es nuestro home. Esta variable se llama HOME y será estudiada más adelante al ver Variables de Entorno shell.

chmod: Cambia los permisos de acceso a los ficheros. La forma de los símbolos que podrá utilizar como argumento será [ugoa...][[+- =][rwxXstugo...]...][,...]' . Muchos de estos símbolos tendrán que ir separados por comas. La combinación de letras [ugoa...] especificará si el cambio al archivo se le esta especificando a nivel del usuario (u), grupo (g) u otros (o) o en su defecto a todos (a). El operador "+" casa que el permiso seleccionado sea añadido, en cambio el símbolo "-" significa lo opuesto. Los símbolos rwx significan permisos de lectura (r), escritura (w) y ejecución (x). Se especificaran los otros símbolos más adelante. Existe también una forma numérica de indicar los permisos de forma octal (0- 7).

clear: Limpia la pantalla si es posible.

Page 94: Tutorial del shell

date: Sin argumentos mostrara en pantalla el día, mes número de día, hora y año.

[shrek@pantano:~]$ datevie jul 2 14:45:59 ART 2004[shrek@pantano:~]$

Si agregamos un símbolo + delante del comando y un modificador, podremos obtener distintas partes de una fecha. Estos modificadores tendrán que ir antepuestos por un símbolo %.

Estos son algunos modificadores de posición

%

El literal %

n

Una nueva línea

t

Un tabulador horizontal

Modificadores de tiempo:

%H

Hora en formato 00..23

%I

Hora en formato 01..12

%k

Hora en formato 00..23

%l

Hora en formato 01..12

%M

Minutos en formato 00..59

%p

AM o PM

Page 95: Tutorial del shell

%r

Tiempo en formato de 12 horas (hh:mm:ss )

%s

Segundos a partir del 01-01-1970 a las 00:00:00.

%S

Segundos (00..59)

%T

Tiempo en formato de 24 horas.

%X

Tiempo en formato local (%H:%M:%S)

%Z

Zona de tiempo, o nada si no esta determinado.

Modificadores de Días

%a

Abreviación de días de la semana (Dom..Sab)

%A

Muestra el nombre completo del día de la semana (Domingo..Sábado)

%b

Abreviación del mes en curso (Ene..Dic)

%B

Muestra el nombre completo del mes en curso.

%c

Muestra el día y la hora en el formato "jue 06 abr 2000 23:48:01 ART"

%d

Día del mes (01..31)

Page 96: Tutorial del shell

%D

Día en formato mm/dd/aa

%h

Igual que %b

%j

Día del año (001..366)

%m

Mes del año (01..12)

%U

Número de semana del año donde el Domingo es el primer día (00..53)

%w

Número del día dentro de la semana (0..6) donde 0 corresponde al Domingo.

%W

Número de semana del año donde el Lunes es el primer día (00..53)

%x

Día en formato dd/mm/aa

%y

Muestra los dos últimos dígitos del año.

%Y

Año en formato de 4 dígitos (1970 .. )

El reloj del sistema también puede actualizar el reloj del sistema a través del modificador -d de la siguiente forma:

date -d mm/dd/yy

Cambia la fecha.

date -d hh:mm:ss

Page 97: Tutorial del shell

Cambia la hora. La opción --help muestra un mensaje de ayuda mientras que --version Muestra información de la versión.

find: Encuentra archivos recursivamente. Los archivos que coincidan con la una expresión lógica serán mostrados en pantalla. Find no sigue a los link simbólicos, sino que los muestra como archivos.

Uso de Operadores: En esta descripción el argumento n es usado para identificar a un número decimal entero donde +n es mayor que n y -n es menor que n y n es exactamente n. -fstype <tipo> Verdadero si el tipo de archivo coincide con "tipo". Típicamente 4.2 o nfs. -name <archivo> Verdadero si el archivo es igual a <archivo>. Puede usarse los modificadores del shell como comodín donde "?" representa una sola letra y "*" representa toda una cadena. -size n Verdadero si el archivo es de n bloques de largo (512 bytes por bloque) -inum n Verdadero si el archivo tiene el inodo igual a n. Veremos los inodos en el capítulo 8.5.3. -atime n Verdadero si el archivo fue accedido en n días. -mtime n Verdadero si el archivo fue modificado en n días. -ctime n Verdadero si el archivo fue cambiado en n días. -exec command Verdadero si la ejecución del "command" retorna 0. -ok command Parecido a -exec solo que el "command" es escrito en la pantalla y se pregunta si es ejecutado a lo que se tendrá que responder "Y" o "N". -print Siempre es verdadero, muestra el path donde esta buscando. -ls Siempre es verdadero, imprime además todos los datos de un "ls" normal y más: número de inodo, tamaño en kilobytes (1024 bytes), modo de protección y número de enlace duro, usuario, grupo, tamaño en bytes y tiempo de la última modificación. Si el archivo es un link simbólico, se mostrará hacia donde apunta con "->". -cpio device Siempre verdadero, escribe el archivo en un dispositivo de cinta. -newer <archivo> Verdadero si los archivos fueron modificados más recientemente que el tiempo de modificación que tiene <archivo> -xdev Siempre verdadero, no desciende a directorios que posean otro tipo de filesystem's FAST-FIND: Se trata de una base de datos alojada en /usr/lib/find que es actualizada periódicamente y es donde se van guardando las búsquedas anteriores. Se puede actualizar con el comando siendo root con el comando updatedb que se encuentra en el mismo directorio.

cp: copia el contenido del archivo1 en el archivo2 con la sintaxis siguiente

[shrek@pantano:~]$ cp <archivo1> <archivo2>... <archivo[n]> <destino>

donde archivo1, archivo2 hasta archivo[n] serán copiados a destino. Algunas opciones:

-a, --archive

Preserva la posible estructura y atributos del archivo a copiar

-b, --backup

Realiza un backup de los archivos copiados por si se renombran o son borrados

-f, --force

Borra sin avisar el archivo de destino si este existe

Page 98: Tutorial del shell

-i, --interactive

Pregunta por pantalla la confirmación de sobrescribir un archivo destino

Otra forma de utilizar el comando cp es haciendo una copia recursiva de directorio1 con subdirectorios y todo a directorio2. Si directorio2 no existe, se creará. Esto se logra con la opción -c.

echo: Simplemente envía a pantalla los argumentos pasados.

[shrek@pantano:~]$ echo "Hola mundo"Hola Mundo

finger: Por defecto muestra en pantalla todos los usuarios logeados incluyendo nombre de login, nombre completo, nombre de la terminal donde esta logeado, hora en que entro al sistema, hostname además de otros datos personales como los números de teléfono si es que existen.

[shrek@pantano:~]$ fingerLogin Name Tty Idle Login Time Office Office Phoneroot root *1 22 Apr 8 18:42sebas p0 Apr 8 18:42 (192.168.1.1)

Idle es un entero que muestra la cantidad de tiempo que el usuario esta logeado en el sistema. Opciones:

-s

Igual que ejecutar el finger común

-l

Representa la información en múltiples líneas

[shrek@pantano:~]$ finger -lLogin: shrek Name: ShrekDirectory: /home/shrek Shell: /bin/bashOn since Tue Aug 10 14:41 (ART) on tty2 6 hours 35 minutes idleNo mail.No Plan.

Si se quisiera saber los usuarios que están logeados en un sistema diferente al nuestro, y si el sistema el cual estamos explorando lo permite al tener habilitado el puerto 79 (finger), tendríamos que ejecutar el comando seguido de una "@" e inmediatamente después el nombre del host del que queremos saber quien esta logeado. [shrek@pantano:~]$ finger @farfaraway.com

grep: Imprimirá las líneas que coincidan con la expresión que coloquemos inmediatamente luego del comando. Por ejemplo, si tiráramos por pantalla el archivo /var/log/messages tal vez tendríamos demasiadas líneas para ver, pero si solo queremos ver aquellas líneas que contengan la expresión "tty1" solo tendríamos que hacer un cat al archivo y utilizando el símbolo de canalización "|" podríamos hacer que la salida del cat se procese con el comando grep para darnos la salida deseada.

Page 99: Tutorial del shell

[root@pantano:/home/shrek]# cat /var/log/messages|grep tty1Jul 25 16:53:04 pantano login[433]: ROOT LOGIN ON tty1Jul 25 18:41:40 pantano login[433]: ROOT LOGIN ON tty1Jul 25 18:42:10 pantano login[457]: ROOT LOGIN ON tty1[root@pantano:/home/shrek]#

Opciones:

-A num

Muestra las num líneas siguiente a la última línea que haya coincidido con el patrón pedido.

-B num

Muestra las num líneas anteriores a la primera línea que haya coincidido con el patrón pedido.

-c

Muestra por pantalla él número de líneas que coinciden con el patrón.

-b

Muestra antes que las líneas que coinciden, la cantidad de bytes que han pasado por el comando luego de salir cada línea.

Para mayores usos y dado que la opción anterior será la que más se utilice, se recomienda la lectura de las paginas de su manual.

kill: Por defecto envía una señal de terminación (terminate 15) al proceso que se indique por medio del numero de proceso (PID). Las señales que se le pueden enviar a un proceso se listan con la opción - l. Estas son:

1. SIGHUP2. SIGINT3. SIGQUIT4. SIGILL5. SIGTRAP6. SIGIOT7. SIGBUS8. SIGFPE9. SIGKILL10. SIGUSR111. SIGSEGV12. SIGUSR213. SIGPIPE14. SIGALRM15. SIGTERM16.17. SIGCHLD

Page 100: Tutorial del shell

18. SIGCONT19. SIGSTOP20. SIGTSTP21. SIGTTIN22. SIGTOU23. SIGURG24. SIGXCPU25. SIGXFSZ26. SIGVTALRM27. SIGPROF28. SIGWHINCH29. SIGIO30. SIGPWR

Para más información sobre las señales consultar signal(7) en las páginas de manual. De estas señales indicaremos las más utilizadas. Estas son 9, 1 y 15. Para indicar el número de señal que queremos enviar a un proceso, se le antepone el signo "-".

[root@pantano:/usr/bin]# kill -9 266

Esto provocará que el proceso muera repentinamente. La diferencia entre la señal 9 y la 15 es que al enviar al proceso una señal 15 este será marcado como un proceso terminado. En cambió la señal 9 mata el proceso inmediatamente. La señal 1 o SIGHUP reinicia el proceso al que se envía la señal, lo que también se podrá realizar con el modificador -HUP.

[root@pantano:/usr/bin]# kill -HUP 266

Se deberá tener en cuenta que el usuario solo podrá mandar señales a los procesos que le pertenecen. En cambio el usuario root podrá hacerlo a cualquier proceso que este corriendo en el sistema.

less: es un programa similar a more que permite ir viendo una salida en pantalla que ocuparía más de una. La diferencia sustancial con el more es que nos permite desplazarnos de abajo hacia arriba y de arriba hacia debajo de la salida por pantalla. Permite a su vez que se utilicen una serie de comandos. Sumario de comandos básicos del less.

h H

Muestra la ayuda.

q :q Q :Q ZZ

Salir.

e ^E j ^N CR

Adelante una línea (o N líneas).

Page 101: Tutorial del shell

y ^Y k ^K ^P

Atrás una línea (o N líneas).

f ^F ^V SPACE

Adelante una pantalla (o N líneas).

b ^B ESC-v

Atrás una pantalla (o N líneas).

ESC-SPACE

Adelante una pantalla.

/ patrón

Busca hacia adelante n's líneas en donde coincida el patrón.

logout: Sale de la terminal.

lpq: Muestra en pantalla el contenido de la cola de impresión. Si se quiere un reporte por cada usuario, el comando deberá estar seguido del nombre del usuario.

lpr: Genera un trabajo de impresión del archivo seleccionado. Si no se especifica archivo, lpr leerá los datos desde la entrada estándar. Opciones: -Pprinter Envía la salida a la impresora printer. -#copies Procede a crear "copies" copias del trabajo enviado a la cola de impresión.

[shrek@pantano:~]$ lpr -#3 index.c

También se podría realizar leyendo el archivo con el comando cat y enviarlo al comando lpr con la cantidad de copias que se requieren.

[shrek@pantano:~]$ cat index.c |lpr -#3

Existen muchos comandos más para aplicar formatos específicos a la salida impresa, los que se podrán consultar en las páginas de manual.

lprm: Remueve los trabajos de la cola de impresión. Sin argumentos, "lprm", borrara todos los trabajos activos del usuario que invoco el programa. Puede ser removido un trabajo determinado utilizando el comando lpq para saber el número de trabajo y el comando lprm para eliminarlo indicando en la impresora que se encuentra.

[shrek@pantano:~]$ lpq -Plppantano: waiting for 192.168.1.1 to come upRank Owner Job Files Total Size1st sebas 0 passwd 636 bytes2nd sebas 1 passwd 636 bytes[shrek@pantano:~]$ lprm -Plp 1

Page 102: Tutorial del shell

donde lp es el nombre de la impresora.

ls: Lista todos los archivos del directorio que indiquemos.

-a, --all

Lista todos los archivos, incluidos los archivos de punto (.archivo)

-d, --directory

Lista solo los directorios.

-c

Lista los archivos ordenados desde la fecha más próxima a la del momento en que se ejecuta el comando.

-f

No ordena los archivos, los muestra según la ubicación en el disco.

--full-time

Muestra los archivos con todos los datos de tiempo.

-i, --inode

Imprime el índice de inodos de cada archivo.

--color=yes

Indica al comando ls que muestre los resultados en colores.

Para mayor información, mirar las páginas de manual.

man: Muestra las páginas de manual del comando o programa que se le pase como argumento. mail: Es un programa sencillo para el envió de e-mails, tanto en una red como en Internet. Siendo este un comando por demás de auto explicativo y que en su mayoría solo se utilizara para realizar rápidos mensajes de email, se recomienda la lectura de las páginas de manual para poder ver todos los alcances que tiene.

mkdir: Crea directorios nuevos. Se deberá indicar luego del comando el directorio o los directorios a crear.

[shrek@pantano:~]$ mkdir cartas

Se creara el directorio cartas en el directorio sebas

more: Es un filtro que mostrara por pantalla el archivo que le enviemos o que sea redireccionado a el y parara por cada pantalla mostrada. Opciones: -c Borra la pantalla

Page 103: Tutorial del shell

antes de desplegar la información por pantalla. -d Mostrara los mensajes de error e indicara que hacer para solucionarlo.

mv: Mueve archivos y directorios. Existen tres formas para utilizar el mv y se muestran más abajo. La primera forma es cuando se quiere cambiar el nombre de un archivo. Supongamos que queremos cambiar el nombre del archivo1 a archivo2. Si archivo2 existe, este será borrado y en su lugar estarán los datos del archivo1. La opcion 2 es que lo que se quiera mover sea un directorio. Solo se podrá hacer si el nuevo nombre del directorio no existe. La tercera opción es cuando se quiere mover mas de un archivo a una ubicación particular. Existen para realizar esto las siguientes opciones:

-f

Fuerza la ejecución del comando mv aunque se trate de un proceso restringido como el borrado de un directorio.

-i

Habilita el proceso interactivo. Se podrá especificar el archivo o directorio que se quiere renombrar o mover.

passwd: Cambia o pone la clave de paso a un usuario. Solo el root podrá cambiar el password de otro usuario. El usuario podrá cambiar su propia clave con este comando.

ps: Mostrara información por pantalla de los procesos que están corriendo en ese comento. Opciones:

-a

Opción por defecto. Mostrará los procesos de los cuales el usuario es el dueño.

-x

Mostrará absolutamente todos los procesos que se estén ejecutando.

-f

Mostrará la jerarquía de los procesos mostrando los padres de cada uno y sus descendientes.

pwd: Mostrará la ruta del directorio donde estamos parados actualmente.

[shrek@pantano:~]$ cd /usr/local/bin[shrek@pantano:/usr/local/bin]$ pwd/usr/local/bin[shrek@pantano:~]$

rm: Remueve archivos y directorios. Opciones:

-i

Page 104: Tutorial del shell

Pregunta antes de borrar cada archivo.

-f

Fuerza el borrado de una archivo sin mostrar los mensajes de error.

-r

Borrado recursivo.

rmdir: Borra directorios. Las opciones anteriores también se aplican