INSTITUTO TECNOLÓGICO Y DE ESTUDIOS SUPERIORES DE MONTERREY Laboratorio de Redes 1 Práctica 4 - Introducción a Shell Script Una de las principales ventajas de GNU/Linux sobre otros sistemas operativos es la capacidad de crear scripts hechos a la medida que ejecuten cualquier función que se pueda realizar en la consola. Es decir, si el usuario manualmente consulta un directorio o ejecuta ciertos programas, con un script el usuario puede automatizar el proceso a la medida que necesita. Un Script (o guion) para BASH es un archivo de texto que contiene una sucesión de comans de Shell que pueden ejecutar diversas tareas de acuer al conteni del texto del guión. De esta forma pueden automatizarse muchas acciones para alguna necesidad particular o para la administración de sistemas. El guión debe escribirse en un orden lógico pues Bash ejecutará el guión en el orden en que se escriben las lineas, de la misma forma que cuan se realiza una tarea cualquiera por una persona, por ejemplo; primero hay que poner la escalera y luego subirse. (Wiki Doc.Ubuntu) En palabras sencillas, si hay algo que puedas hacer en la consola, lo puedes poner en un Script. Estos scripts, no son propiamente lenguajes de programación y se ejecutan línea por línea hasta hallar un error o terminar de forma exitosa. Al poder ejecutar cualquier coman de consola nos permite incluso ejecutar dentro de un script programas y comans hechos en diferentes lenguajes de programación para un resulta en particular. Por último, Los scripts aceptan ciertos estatutos como ciclos de repetición (For, While) y de condición (IF, ELSE) además de cierto nivel de declaración de variables. A lo largo de esta práctica, se dará una introducción extremadamente básica para el manejo de scripts en Ubuntu. 1 - Tipo de Shells Durante la práctica de introducción a sistemas GNU/Linux el alumno ya habrá utiliza SHELL. Ya que se trata de la línea de comans o consola (SHELL). En un entorno Linux (moderno) Existen una gran variedad de Shells cuyas diferencias radican en la sintaxis pero no es objetivo de esta práctica profundizar en ellos. Usualmente, el Shell que 1
se halla por defecto es BASH y será para este Shell los scripts que se creen durante este laboratorio. Actividad de laboratorio: Realizaremos una búsqueda de cuántos tipo de shells soporta el Sistema Operativo GNU/Linux que este manejan. Para ello ejecute el siguiente coman: cat /etc/shells Y anote a continuación los shells que aparezcan: 2- Diseño de un script Para empezar a crear un script, lo primero que se necesita es indicar que tipo de sintaxis se utilizara, de lo contrario se corre el riesgo de ejecutar un script con un Shell distinto provocan errores de sintaxis que elimine su ejecución. Para la denición del script, la primera línea del mismo es dicha denición. Para el laboratorio, to script que se realice debe empezar con la siguiente línea: #!/bin/bash El uso de #! es un caso especial que solo debe aparecer una vez. Después de su primera aparición, si volviera a aparecer causaría conflictos en el script. El uso de # (sin el signo de admiración) sirve para identicar que se trata de una línea de comentario. Una vez el script este diseña según las necesidades que se requiera, se necesita que el mismo sea ejecutable. To archivo en Linux se considera un archivo de texto por defecto pero no son ejecutables. Para volverlo ejecutable, utilizaremos el coman chmod. 2
Actividad de laboratorio: 2.1 - Crear el archivo Cree un archivo de texto de nombre: Ejemplo.sh cuyo conteni sea el siguiente: #! /bin/bash Cat /etc/passwd grep redes Como recordara de la práctica pasada, el coman cat /etc/passwd grep redes fue utiliza para desplegar to los usuarios que contuvieran redes. En este primer ejemplo, pondremos dichos comans en un script. NOTA: la extensión.sh no es necesario, se ha utiliza para facilitar que el usuario diferencie con relativa facilidad un archivo cualquiera de uno de script. 2.2 - Hacer ejecutable el archivo Utilizaremos el siguiente coman Chmod u+x Ejemplo.sh U Indica User y el +x hace que se active la opción de ejecutable para el usuario. Es decir, los demás permisos (R, W) no se ven afectas y G(rupos), O(tros) no son alteras. Existen distintos mos de usar el coman chmod, pero este es el mo más seguro al solo modicar una propiedad (la que necesitamos) de un solo miembro de UGO. 2.3- Ejecutar el script To archivo ejecutable, se puede realizar anexan el prejo./ a su nombre. De hecho, sin esta indicación Linux no intentara ejecutar el script. Ejecute el coman:./ejemplo.sh El resulta es distinto a la práctica pasada? Por qué? 3
2.4 Variables Como se ha menciona, un script puede manejar variables, entre las más usuales están las que servirían como argumentos (Entradas obligatoria u opcionales de un programa) además de las variables internas del programa. Las variables que se obtengan de los argumentos del script tienen la siguiente nomenclatura: $0 Generalmente, es el nombre del script Shell ejecuta. $1 Primer argumento del script $2 Segun argumento del script $3 $4 $# Total de argumentos que el script recibió. $@ Un string contenien to los argumentos que introdujo el usuario. Generalmente se utiliza $# para garantizar que el programa fue utiliza con sucientes argumentos antes de seguir con la ejecución del mismo y los demás para ir accedien a las distintas variables que el usuario introdujo. Una característica importante de las variables es que estas pueden contener to tipo de valores, a diferencia de la mayoría de los lenguajes de alto nivel que denen el tipo de variable. Eso signica que un desarrollar de Bash Script tiene que tener cuida a la hora de manipular las variables de que su conteni es el espera. No es objetivo de este laboratorio profundizar más en el uso de las variables. 3- Observaciones de los scripts Probablemente, todavía no le quede claro al alumno las capacidades de un script, pero estos son extremadamente poderosos ya que permite una gran gama de ejecuciones y de fácil personalización permitien que el usuario cree sus propias herramientas de uso diario. Generalmente, al crear un script s elementos deben de tenerse en cuenta: 1. Las entradas y salidas no deberían verse alteradas. Es decir, todavía debería de recibir una entrada estándar y salida estándar, de tal forma el mismo usuario pudiese manipularlas como lo haría con cualquier otra función predenida. 2. Un script debe ser flexible en los parámetros de entrada pero estricto en los de salida. Es decir, un script podría recibir parámetros basura (Respecto a lo que necesita) y no debe de generar una salida. Pero por ningún motivo debe de generar basura en la 4
salida. Un excelente ejemplo puede ser la manipulación de archivos con texto nde se dese dar un nuevo formato a la información o incluso desplegar solo ciertos datos. Sobre to hoy en día que la mayoría de los diferentes tipos de archivos de texto manejan XML. Esto se debe a las herramientas de ltra como GREP y AWK (la primera en menor medida). Un segun ejemplo, es cuan se requiere ejecutar ciertas secuencias de monta de dispositivos, re-compilación de códigos y programas con cierta regularización. 4- Scripts de ejemplo El objetivo de este inciso será la lectura del script y su ejecución para ir acostumbra al alumno respecto al funcionamiento de los mismos. Los ejemplos mostras a continuación fueron tomas del trabajo de Paul Lutus Ejemplo 1: Un mo de creación de un menú PS3="Eliga (1-5):" echo "Eliga del menu de abajo." select name in rojo verde azul amarillo magenta break echo "Su eleccion fue: $name." Ejemplo 2: Selección de un número aleatorio secretnumber=$(( ((`date +%N` / 1000) % 100) +1 )) guess=-1 while [ "$guess"!= "$secretnumber" ]; echo -n "I am thinking of a number between 1 and 100. Enter your guess:" read guess if [ "$guess" = "" ]; echo "Please enter a number." elif [ "$guess" = "$secretnumber" ]; echo -e "\ayes! $guess is the correct answer!" elif [ "$secretnumber" -gt "$guess" ]; echo "The secret number is larger than your guess. Try again." else echo "The secret number is smaller than your guess. Try again." Ejemplo 3: Validar si una serie de hosts están disponible en la red. La secuencia de pings son de la 10.17.117.1 a la 10.17.117.20 es decir, se revisan 20 dispositivos en la 5
red interna del campus. #!/bin/bash is_alive_ping() { ping -c 1 $1 > /dev/null [ $? -eq 0 ] && echo Node with IP: $i is up. } for i in 10.17.117.{1..20} is_alive_ping $i & disown Ejemplo 4: Arreglos Considere los arreglos como valores guardas en una lista pre-existente array=(red green blue yellow magenta) len=${#array[*]} echo "The array has $len members. They are:" i=0 while [ $i -lt $len ]; echo "$i: ${array[$i]}" let i++ 5- Ejercicios: Ejercicio 1 Utilice el script del ejemplo 3 para crear un script que haga una serie de pings predenis a las máquinas de sus compañeros (y solo a ellas). Puede basarse en el ejemplo 1 sustituyen el menú de colores por direcciones IP. Ejercicio 2 Cree un script que permita crear las siguientes carpetas de forma automatizada: ~/Sesion3 ~/Sesion3/Alumno1 ~/Sesion3/Alumno1/Califas ~/Sesion3/Alumno3 ~/Sesion3/Alumno4 6
Ejercicio 3 Cree un script similar al ejercicio 2, pero que te pida el nombre las de carpetas y que pueda ser ejecuta desde cualquier directorio. Curiosidades Los siguientes scripts son una recopilación del a red con el único propósito de mostrar algunos usos posibles a los Scripts en Linux. 7
Crear un rombo de caracteres #!/bin/bash # # Linux Shell Scripting Tutorial 1.05r3, Summer-2002 # # Written by Vivek G. Gite <vivek@nixcraft.com> # # Latest version can be found at http://www.nixcraft.com/ # MAX_NO=0 echo -n "Enter Number between (5 to 9) : " read MAX_NO if! [ $MAX_NO -ge 5 -a $MAX_NO -le 9 ] ; echo "I ask to enter number between 5 and 9, Okay" exit 1 clear for (( i=1; i<=max_no; i++ )) for (( s=max_no; s>=i; s-- )) echo -n " " for (( j=1; j<=i; j++ )) echo -n "." echo "" ###### Second stage ###################### ## ## for (( i=max_no; i>=1; i-- )) for (( s=i; s<=max_no; s++ )) echo -n " " for (( j=1; j<=i; j++ )) echo -n "." echo "" echo -e "\n\n\t\t\ti hope you like it my stupidity (?)" # #./ch.sh: vivek-tech.com to nixcraft.com referance converted using this tool # See the tool at http://www.nixcraft.com/uniqlinuxfeatures/tools/ # 8
Canal IRC Este script permite la conexión a un canal IRC #!/bin/bash # # conguration nick="`basename $0`$$" # nickname name="$0 $*" # real name chan="#sh #bash" # channels to join mode="+i" # irc mode # end of conguration # use our login name if there's no nickname nick="${nick:-$user}" # see if we can nd a realname for our nickname name="${name:-`grep $nick /etc/passwd cut -d : -f 5`}" host="$1" port="$2" # redirect error messages to le `irc-errors' exec 3<> irc-errors 2>&3- if [! "$2" ]; echo "usage: `basename $0` [hostname] [port]" exit 1 # try to connect if! exec 3<> /dev/tcp/$host/$port; echo "`basename $0`: unable to connect to $host:$port" exit 1 # duplicate standard input and output with the newly created socket exec 0<&3 1>&3- # register to the server echo "USER $nick ${mode:-+iw} $nick :$name" echo "NICK $nick" # join channels for c in $chan; echo "JOIN $c"; while read; set -- ${REPLY//$'\r'/} # answer the critical ping request # otherwise the server will disconnect us [ "$1" == "PING" ] && echo "PONG $2" # your code should go here exec 1<&- 2<&- 9
Ejecutar un coman en cada directorio 10
########################################################################## # Title : global - execute command in every subdirectory # Author : Heiner Steven <heiner.steven@odn.de> # Date : 1994-09-29 # Requires : # Category : File Utilities # SCCS-Id. : @(#) global 1.3 03/12/19 ########################################################################## # Description # ########################################################################## PN=`basename "$0"` VER='1.3' # program name usage () { echo >&2 "$PN - execute command in subdirectories, $VER (stv '94) usage: $PN [-v] command [argument...] -v verbose, print current path The given command is executed in every subdirectory of the current directory, depth rst. At last it is executed in the current directory, too. If the command contains embedded blanks, it must be enclosed in quotation marks \"...\" or '...'." exit 1 } err () { for i echo "$PN: $i" >&2 } fatal () { err "$@"; exit 1; } msg () { [ "$silent" = no ] && err "$@"; } MyPath=$0 # Export "silent" to subshells, because parameters to the # invoking shells are not passed to the subshells : ${silent:=yes} # yes/no, may be set from calling shell export silent while [ $# -gt 0 ] case "$1" in -v) silent=no;; --) shift; break;; # End of parameter list esac shift -h) usage;; -*) usage;; *) break;; # Command [ $# -lt 1 ] && usage for i in * [ -d "$i" ] continue cd "$i" "$MyPath" "$@" cd.. msg "`pwd`" eval "$@" # recurse into subdirectories 11
Crear un lista de correos 12
#!/bin/bash #Version: 1.0.1 ( 28/01/11 ) #Objetivo: Enseñar la forma de leer ORIGENs y manejo de strings # Elementos clave: "Un shell debe ser flexible en los parametros de entrada pero estricto en los de salida # Entrada: Una lista de matriculas (alfa numerico), salida: A0#######@itesm.mx # LA parte dinamica es de 9 caracteres, la parte estatica es de 9 # en total cada linea del ORIGEN resultante debera tener 18 caracteres ARGS=1 #Max de argumentos que puede recibir ORIGEN="entrada.txt" ; DESTINO="matriculas.txt" #Entrada y Salida no estandar del bash Match="" #Variable usada para hacer busqeudas con grep Line=$@ EXPREG1="^A0[0-9]*" #ER utilizadas para buscar los posibles formatos EXPREG2="^[0-9]*" # de las matriculas escritas por los alumnos. EXPREG3="^A[0-9]?@itesm.mx" LeerORIGEN(){ #echo "" > "$DESTINO" #Un archivo temporal es crea para ir guardan lo exitoso #El for avanzara en cada Palabra hallada en lo que regrese cat $ORIGEN for WORD in `cat $ORIGEN` #Aqui es nde buscaremos WORD, en teoria puede ser Alfa numerico o solo numerico #Iremos descartan, primero A0####### Match=`echo "$WORD" grep -xwi "$EXPREG1"` if [ "$Match" = "" ] #echo "No es el primer formato " #Puede estar ya bien en el formato denitivo Match=`echo "$WORD" grep -xwi "$EXPREG3"` if [ "$Match"!= "" ] #La longitud es necesaria de checar if [ "${#Match}" -eq 18 ] #Un correo en el formato y longitud debi #echo "Un correo halla" "$EXPREG3" ": " $Match echo "$Match" #>> "$DESTINO" else #Puede ser meramente numero (Sin A0) Match=`echo "$WORD" grep -xwi "$EXPREG2"` if [ "$Match"!= "" ] #LA longitud es un problema... A-00787620, A0-1787620 y A00-787620 son # validas, por lo tanto ifelse if [ "${#Match}" -eq 8 ] #echo "Una matricula escrita informalmente""$expreg2" ": " $Match echo "A""$Match""@itesm.mx" #>> "$DESTINO" elif [ "${#Match}" -eq 7 ] 13
#echo "Una matricula escrita informalmente""$expreg2" ": " $Match echo "A0""$Match""@itesm.mx" #>> "$DESTINO" elif [ "${#Match}" -eq 6 ] #echo "Una matricula escrita informalmente" "$EXPREG2" ": " $Match echo "A00""$Match""@itesm.mx" #>> "$DESTINO" else #OJO: Espacios en blanco todavia pasan y longigutdes largas tambien # Debemos garantizar que solo se registren longitud de 9 caracteres # ${#Match} es uno de las tantas opciones para obtener longitud de strings if [ "${#Match}" -eq 9 ] #echo "Una matricula hallada" "$EXPREG1" ": " $Match echo "$Match""@itesm.mx" #>> "$DESTINO" } ########################################################### ####### Equivalente a un MAIN ###################### ########################################################### #echo $# #echo $@ #echo $1 #echo "BASH para convertir matriculas a cuentas de @itesm.mx" #Validamos argumentos de entradas #Para 1.0 se ocupa un argumento a fuerzas if [ $# -eq "$ARGS" ] ORIGEN=$1 #echo "Archivo de origen: " "$ORIGEN" else echo "$0" " Error : Falta el archivo de entrada " exit 1 # Checamos meramente si existe el ORIGEN con el que se desea trabajar s if!( test -e $ORIGEN ) echo "$0" " Error : No hay ORIGEN de entrada disponible" exit 1 14
else #echo "Leyen el ORIGEN " $ORIGEN LeerORIGEN $# $1 exit 0 15
Trabajos citas LinuxCong. (2010, November 9). Bash Script for scan and monitoring network. Retrieved Agosto 2011, from LinuxCong.org: http://linuxcong.org/bash-scripts-to-scan-and-monitor-network Lutus, P. (2006). Bash Shell Programming in Linux. Retrieved Agosto 2011, from arachnoid.com: http://www.arachnoid.com/linux/shell_programming.html Wiki Doc.Ubuntu. (n.d.). Script. Retrieved Agosto 2011, from c.ubuntu-es: http://c.ubuntues.org/script 16