la programación en shell

Upload: gerardodoac

Post on 05-Nov-2015

213 views

Category:

Documents


0 download

DESCRIPTION

bash shell

TRANSCRIPT

Por qu la programacin en shell?Incluso existiendo varios interfaces grficos disponibles para Linux el shell sigue siendo una herramienta muy eficiente. El shell no es slo una coleccin de comandos sino un buen lenguaje de programacin. Se pueden automatizar muchas tareas con l, el shell es muy til para tareas de administracin, puedes comprobar rpidamente si tus ideas funcionan lo que lo hace muy til cuando ests creando un prototipo y es muy til para pequeas utilidades que realizan tareas relativamente simples donde la eficiencia importa menos que la facilidad de configuracin, mantenimiento y portabilidad.Por lo tanto veamos como funciona:Creando un scriptExisten muchos shells disponibles para Linux pero habitualmente se utiliza el bash (bourne again shell) para la programacin en shell ya que est disponible libremente y es fcil de usar. Por lo tanto todos los scripts que escribamos en este artculo usarn el bash (aunque la mayora de veces tambin funcionarn con su hermano mayor, el bourne shell).Para escribir nuestros programas en shell usaremos cualquier clase de editor de texto, p.ej. nedit, kedit, emacs, vi... como con otros lenguajes de programacin.El programa debe empezar con la siguiente lnea (debe ser la primera lnea del fichero): #!/bin/sh

Lo caracteres #! indican al sistema que el primer argumento que sigue en la linea es el programa a utilizar para ejecutar este fichero. En este caso usamos el shell /bin/sh.Cuando hallas escrito y guardado tu script debes hacerlo ejecutable para poder usarlo.Para hacer el script ejecutable escribechmod +x nombre-del-ficheroDespus puedes ejecutar tu script escribiendo:./nombre-del-ficheroComentariosLos comentarios en la programacin en shell comienzan con # se prolongan hasta el final de la lnea. Te recomendamos que uses comentarios. Si tienes comentarios y no usas un cierto script durante algn tiempo inmediatamente sabrs qu hace y cmo funciona.VariablesComo en otros lenguajes de programacin no se puede vivir sin variables. En la programacin en shell todas las variables son de tipo string y no es necesario declararlas. Para asignar un valor a una variable se escribe:nombre_de_la_variable=valorPara obtener el valor de la variable simplemente hay que poner el signo del dlar delante de la variable:#!/bin/sh# asignamos un valor:a="hola mundo"# ahora mostramos el contenido de "a":echo "A es:"echo $aEscribe estas lneas en tu editor de textos y guardalo p.ej. como primero. Despus haz ejecutable el script escribiendo chmod +x primero en el shell y despus ejectalo escribiendo ./primeroEl script mostrar lo siguiente:A es:hola mundoAlgunas veces es posible confundir nombres de variables con el resto del texto:num=2echo "este es el $num"Aqu no se mostrar "este es el 2" si no "este es el " porque el shell busca una variable llamada numdo que no tiene valor. Para decirle al shell que queremos mostrar la variable num tenemos que usar llaves:num=2echo "este es el ${num}"Con esto imprimiremos lo que queremos: este es el 2

Hay una serie de variables que se establecen automaticamente. Hablaremos sobre ellas ms adelante cuando las usemos por primera vez.

Si necesitas manejar expresiones matemticas entonces necesitas usar programas como expr (ver tabla abajo).Adems de las variables de shell normales que son nicamente vlidas dentro del programa en shell hay tambin variables de entorno. Una variable precedida de la palabra clave export es una variable de entorno. No vamos a comentar nada ms sobre ellas ya que normalmente slo se utilizan en scripts de entrada al sistema.Comandos de shell y estructuras de controlHay tres categoras de comandos que pueden ser usados en scripts de shell:

1)Comandos Unix:Aunque un script de shell puede hacer uso de cualquier comando unix aqu tienes varios comandos utilizados con ms frecuencia que el resto. Estos comandos se decriben como comandos para la manipulacin de ficheros y texto.Sintaxis del comandoUtilidad

echo "texto cualquiera"escribir un texto cualquiera en tu pantalla

lslistar ficheros

wc -l ficherowc -w ficherowc -c ficherocontar las lneas de un fichero ocontar las palabras de un fichero ocontar el nmero de carcteres

cp fichero_origen fichero_destinocopiar el fichero_origen al fichero_destino

mv nombre_antiguo nuevo_nombrerenombrar o mover un fichero

rm ficheroborrar un fichero

grep 'patrn' ficherobuscar cadenas en un ficheroEjemplo: grep 'cadena-a-buscar' fichero.txt

cut -b num_de_columna ficherosacar datos de columnas de texto de ancho definidoEjemplo: sacar los caracteres de la posicin 5 a la 9cut -b5-9 fichero.txtNo confundais este comando con "cat" que es algo totalmente diferente

cat fichero.txtmostrar un fichero.txt por stdout (tu pantalla)

file un_ficherodescribir qu tipo de fichero es un_fichero

read varesperar a que el usuario introduzca algo y guardarlo en la variable (var)

sort fichero.txtordenar las lneas del fichero fichero.txt

uniqborrar las lneas duplicadas, usado en combinacin con sort ya que uniq slo borra las lneas duplicadas consecutivasEjemplo: sort fichero.txt | uniq

exprhacer operaciones matemticas en el shellEjemplo: sumar 2 y 3expr 2 "+" 3

findbuscar ficherosEjemplo: buscar por nombre:find . -name nombre_del_fichero -printEste comando tiene muchas posibilidades y opciones diferentes. Desafortunadamente son demasiadas para explicarlas todas en este artculo.

teeescribir datos por stdout (tu pantalla) y a un ficheroNormalmente se usa as:un-comando | tee fichero-de-salidaEscribe la salida de un-comando por la pantalla y a el fichero de salida

basename ficherodevolver el nombre del fichero dado un nombre y quitarle la ruta al directorioEjemplo: basename /bin/tuxdevuelve slo tux

dirname ficherodevolver el nombre del directorio dado un nombre y quitndole el nombre del ficheroEjemplo: dirname /bin/tuxdevuelve /bin

head ficheromostrar algunas lneas del principio de un fichero

tail ficheromostrar algunas lneas del final de un fichero

sedsed es bsicamente un programa para buscar y reemplazar. Lee el texto de la entrada estndar (p.ej. una tubera) y escribe el resultado por stdout (normalmente la pantalla). El patrn de bsqueda es una expresin regular (ver referencias). Este patrn de bsqueda de se debe confundir con la sintaxis de comodines (wildcard) del shell. Para reemplazar la cadena linuxfocus con LinuxFocus es un fichero de texto usa:cat texto.fichero | sed 's/linuxfocus/LinuxFocus/' > nuevotexto.ficheroEsto reemplaza la primera aparicin de la cadena linuxfocus en cada lnea por LinuxFocus. Si hay lneas en que linuxfocus aparece varias veces y quieres reemplazarlas todas usa:cat texto.fichero | sed 's/linuxfocus/LinuxFocus/g' > nuevotexto.fichero

awkLa mayora de las veces awk se utiliza para extraer campos de una lnea de un texto. El campo separador por defecto es un espacio. Para especificar uno diferente se usa la opcin -F. cat fichero.txt | awk -F, '{print $1 "," $3 }'

Aqu hemos usado la coma (,) como separador de campos e imprimimos la columna primero y tercera ($1 $3). Si fichero.txt tiene lneas como:Adam Bor, 34, IndiaKerry Miller, 22, USA

estonces mostrara lo siguiente:Adam Bor, IndiaKerry Miller, USA

Se pueden hacer muchas ms cosas con awk pero este es su uso ms comn.

2) Conceptos: Tuberas (pipes), redirecciones y comillas simples invertidasRealmente no son comando pero son conceptos muy importantes.

tuberas (pipes)(|) envian la salida (stdout) de un programa a la entrada (stdin) de otro. grep "hola" fichero.txt | wc -lencuentra las lneas con la cadena hola en fichero.txt y despus cuenta el nmero de lneas.La salida del comando grep se usa como entrada del comando wc. De esta manera se pueden contatenar tantos comandos como se quiera (dentro de unos lmites razonables).

redirecciones: escribe la salida de un comando a un fichero o aade datos a un fichero> escribe la salida a un fichero y sobreescribe el fichero antiguo en caso de existir>> aade datos a un fichero (o crea uno nuevo si no exista previamente pero nunca sobreescribe nada).

Comillas simples invertidas (o tilde invertida)La salida de un comando se puede usar como argumento de lnea de comandos (no stdin como anteriormente, los argumentos de lnea de comando son cadenas que se especifican destrs de un comando como con los nombres de ficheros y opciones) para otro comando. Tambin se pueden usar para asignar la salida de un comando a una variable.El comandofind . -mtime -1 -type f -printencuetra todos los ficheros que han sido modificados en las ltimas 24 horas (-mtime -2 seran 48 horas). Si quisieramos empaquetar estos fichero en un archivo tar (fichero.tar) la sintaxis sera:tar xvf fichero.tar fichero1 fichero2 ...En vez de escribirlo todo se pueden combinar los dos comandos (find y tar) usando comillas simples invertidas. Entonces tar empaquetar todos los ficheros que muestre find:#!/bin/sh# Las comillas son comillas simples invertidas (`) no comillas normales ('):tar -zcvf ultimodific.tar.gz `find . -mtime -1 -type f -print`

3) Estructuras de controlLasentencia "if"comprueba si una condicin es verdadera (con salida de estado 0, correcto). Si es correcto entonces se ejecuta la parte "then":if ....; then ....elif ....; then ....else ....fiLa mayora de las veces se utiliza un comando muy especial dentro de las sentencias if. Se puede usar para comparar cadena o comprobar si un fichero existe, tiene permiso de lectura etc...El comando "test" se escribe como corchetes " [ ] ". Aqu los espacios son muy importantes: Asegrate que siempre hay un espacio entre corchetes. Ejemplos:[ -f "un-fichero" ] : Comprueba si un-fichero es un fichero.[ -x "/bin/ls" ] : Comprueba si /bin/ls existe y es ejecutable.[ -n "$var" ] : Comprueba si la variable $var contiene algo[ "$a" = "$b" ] : Comprueba si las variables "$a" y "$b" son igualesEjecuta el comando "man test" y obtendrs una larga lista con todo tipo de operadores test para comparaciones y ficheros.Usarlo en scripts de shell es bastante directo:#!/bin/shif [ "$SHELL" = "/bin/bash" ]; then echo "tu shell es el bash (bourne again shell)"else echo "tu shell no es bash sino $SHELL"fiLa variable $SHELL contiene el nombre de la shell donde ests y esto es lo que estamos comprobando aqu comparandola con la cadena "/bin/bash"

Operadores cortosA aquellos que conozcan C les gustar la siguiente expresin:[ -f "/etc/shadow" ] && echo "Este ordenador usa shadow passwors"Los && se pueden usar como una pequea sentencia if. Lo de la derecha se ejecuta si lo de la izquierda es verdadero. Podemos interpretarlo como un Y (AND). Por lo tanto el ejemplo quedara: "El fichero /etc/shadow existe Y (AND) se ejecuta el comando echo". Tambin est disponible el operador O (OR) (||). Un ejemplo:#!/bin/shmailfolder=/var/spool/mail/james[ -r "$mailfolder" ] || { echo "No se ha podido leer $mailfolder" ; exit 1; }echo "$mailfolder tiene mensajes de:"grep "^From " $mailfolderEl script comprueba primero si puede leer un buzn de correo. Si puede entonces imprime las lneas "From" del buzn. Si no puede leer el fichero $mailfolder entonces se activa el operador O. Sencillamente este cdigo lo leeramos como "Mailfolder legible o salir del programa". Aqu el problema es que debemos tener exactamente un comando detrs de O pero en este caso necesitamos dos:-mostrar un mensaje de error-salir del programaPara manejar ambos como un solo comando podemos agruparlos en una funcin annima usando llaves. Las funciones en general se explican con ms profundidad ms abajo.Puedes hacerlo todo sin O e Ys usando simplemente sentencias if pero algunas veces los operadores O e Y son mucho ms convenientes.

La sentenciacasese puede usar para comparar (usando comodines del shell como * y ?) una cadena dada con varias posibilidades.case ... in...) hacer algo aqu;;esacVeamos un ejemplo. El comando file comprueba que tipo de fichero es el fichero que le pasamos:file lf.gz

devuelve:

lf.gz: gzip compressed data, deflated, original filename,last modified: Mon Aug 27 23:09:18 2001, os: UnixAhora vamos a usar esto para escribir un script llamadosmartzipque puede descomprimir ficheros comprimidos con bzip2, gzip y zip automaticamente :#!/bin/shtipofichero=`file "$1"`case "$tipofichero" in"$1: Zip archive"*) unzip "$1" ;;"$1: gzip compressed"*) gunzip "$1" ;;"$1: bzip2 compressed"*) bunzip2 "$1" ;;*) error "El fichero $1 no se puede descomprimir con smartzip";;esac

Te habrs fijado que hemos usado una nueva variable especial llamada $1. Esta variable contiene el primer argumento pasado a un programa. Digamos que ejecutamossmartzip articles.zipentonces $1 contendra la cadena articles.zip

La sentenciaselectes una extensin especfica del bash y es muy til para usos interactivos. El usuario puede escoger una opcin de una lista de difirentes valores:select var in ... ; do breakdone.... ahora podemos usar $var ....Un ejemplo:#!/bin/shecho "Cul es tu sistema operativo favorito?"select var in "Linux" "Gnu Hurd" "Free BSD" "Otros"; do breakdoneecho "Has seleccionado $var"Aqu tienes lo que hara el programa:Cul es tu sistema operativo favorito?1) Linux2) Gnu Hurd3) Free BSD4) Otros#? 1Has seleccionado LinuxEn el shell tenemos estn disponibles las siguientessentencias de bucle:while ...; do ....doneElbucle whilese ejecutar mientras la expresin que comprobamos sea verdadera. Se puede usar la palabra clave "break" para abandonar el bucle en cualquier punto de la ejecucin. Con la palabra clave "continue" el bucle continua con la siguiente iteracin y se salta el resto del cuerpo del bucle.

Elbucle fortoma una lista de cadenas (separadas por espacios) y las asigna a una variable:for var in ....; do ....doneEl siguente ejemplo muestra por pantalla de la letra A a la C:#!/bin/shfor var in A B C ; do echo "var es $var"doneUn script de ejemplo ms til es este, llamado showrpm, que muestra un resumen del contenido de una serie de paquetes RPM:#!/bin/sh# listar un resumen del contenido de una serie de paquetes RPM# USO: showrpm ficherorpm1 ficherorpm2 ...# EJEMPLO: showrpm /cdrom/RedHat/RPMS/*.rpmfor rpmpackage in $*; do if [ -r "$rpmpackage" ];then echo "=============== $rpmpackage ==============" rpm -qi -p $rpmpackage else echo "ERROR: no se pudo leer el fichero $rpmpackage" fidoneComo se puede ver hemos usado la siguente variable especial, $* que contiene todos los argumentos de la lnea de comandos. Si ejecutasshowrpm openssh.rpm w3m.rpm webgrep.rpmentonces $* contiene las tres cadenas openssh.rpm, w3m.rpm y webgrep.rpm.

El bash GNU tambin entiende bucles until pero en general con los bucles while y for es suficiente.

ComillasAntes de pasarle cualquier argumento a un programa el shell intenta expandir los comodines y variables. Expandir significa que el comodn (p.ej. *) se reemplaza por los nombres de fichero apropiados o que una variable se reemplaza por su valor. Para modificar este comportamiento se pueden usar las comillas: Pongamos que tenemos varios ficheros en el directorio actual. Dos de ellos son ficheros jpg, correo.jpg y tux.jpg.#!/bin/shecho *.jpgImprimir "correo.jpg tux.jpg".Usar comillas (simples y dobles) evitar esta expansin de comodines:#!/bin/shecho "*.jpg"echo '*.jpg'Esto mostrar "*.jpg" dos veces.Las comillas simples son las ms estrictas. Evitan incluso la expansin de variables. Las comillas dobles evitarn la exprasin de comodines pero no as la de variables:#!/bin/shecho $SHELLecho "$SHELL"echo '$SHELL'Esto mostrar:/bin/bash/bin/bash$SHELLFinalmente existe la posibilidad de eliminar el significado especial de un nico caracter anteponiendole una barra invertida:echo \*.jpgecho \$SHELLEsto mostrar:*.jpg$SHELLDocumentacin aquDocumentacin aqu es una forma muy elegante de enviar varias lneas de texto a un comando. Es bastante til para escribir un texto de ayuda en un script sin tener que poner echo delante de cada lnea. Un "Documentacin aqu" comienza por