Shell Scripting
¿Qué es la Shell?
La Shell no es más ni menos que un intérprete de comandos, el cual le permite al usuario interactuar con el Sistema Operativo. Existen varios tipos de Shell:
Bourne Shell = sh
Bourne-Again Shell = bash
Korn Shell = ksh
C SHell = csh
Para identificar las Shells que tenemos disponibles, debemos ver el contenido del archive /etc/shells.
# cat /etc/shells
¿Qué es un Script?
Es un archivo de texto ejecutable, que contiene una serie de comandos pre-definidos. Sirve para automatizar tareas, ya que se pueden configurar secuencias que ejecuten diversas tareas sin la intervención del usuario, más que para ejecutar el Script. El único requisito es que el archivo posea privilegios de ejecución. Microsoftianamente es como crear un .bat pero mucho más potente y versátil.
Todos los comandos escritos en el archivo serán ejecutados en el mismo orden en el cual fueron plasmados.
Recuerden que en Linux la ejecución de comandos no depende de la extensión sino de los permisos, por lo que no es necesario agregar la misma, pero por un tema organizativo, se le suele agregar la extensión “.sh”.
Lo primero que vamos a ver antes de comenzar a trabajar con la Shell son una serie de comandos los cuales utilizaremos para hablarle al Sistema Operativo.
#: Todo lenguaje de programación ofrece la posibilidad de colocar comentarios para que las personas que abran el código entiendan de forma más rápida lo que el programador quiso plasmar.
echo: Es un comando que sirve para imprimir en pantalla. Esto implica que si queremos que se muestre el mensaje “Hola Mundo” deberemos escribir: echo “Hola Mundo”.
chmod: Comando que sirve para cambiar la máscara de permisos de un archivo, osea, quienes queremos que puedan ejecutarlo, leerlo o escribirlo.
who: Sirve para ver quien está conectado en ese momento quien está en el sistema.
date: Muestra el día.
Hay muchos comandos más y todos pueden ser utilizados por un Script.
¿Qué otras cosas podemos integrar al Script?
Comprendiendo lo que son las VARIABLES. La información puede ser almacenada en la RAM. La memoria RAM está dividida en pequeños sectores y cada sector tiene un número único llamado Dirección de Memoria que es utilizado para guardar nuestra información. El lenguaje de programación, permite asignarle un nombre, (alfanumérico), a esa dirección en memoria llamada “VARIABLE”.
Para hacer esto debemos definirla de la siguiente manera:
VARIABLE=variable
Y para que el Shell llame a dicha variable, debemos colocar el símbolo $ delante del nombre de la variable creada, en este caso sería “$VARIABLE”.
EJ:
edad=23
#!/bin/sh
echo “Que edad tengo?”
echo $edad (Esto mostrará en pantalla el número 23)
En Linux existen dos tipos de variables:
Locales: Pueden ser accedidas solo por la Shell que ejecutó el Script.
Exportada: Puede ser accedida por ambas Shell y cualquier proceso hijo que sea iniciado por esa Shell.
Los comandos set, (lista todas las variables) y env, (muestra solo las variables exportadas) sirven para listar las variables definidas.
Si queremos hacer que una VARIABLE creada por nosotros sea global, debemos ejecutar el comando export. Por ejemplo si tenemos la variable $nombre, podemos ejecutar “export nombre”. Podemos verificar que se haya integrado correctamente ejecutando “env | grep nombre”.
Varibables pre-definidas | Significado |
DISPLAY | Utilizado por X para identificar donde correr una aplicación cliente |
HISTFILE | Ruta al historial de bash de los Usuarios |
HOME | Ruta al directorio personal del Usuario |
LOGNAME | El nombre utilizado para iniciar sesión |
PATH | Lista los directorios donde se encuentran los ejecutables utilizados por la Shell |
PWD | Directorio de trabajo en el cual se encuentra parado el Usuario |
SHELL | La Shell utilizada |
TERM
BASH BASH_VERSION |
La emulación de Terminal actual
Nombre del Shel l utilizado Versión del Shell utilizado |
También podemos encontrar Variables Especiales:
Variables Especiales | Significado |
$! | Contiene el Número de Proceso(PID) del último Proceso |
$$ | Contiene el Número de Proceso (PID) de la Shell |
$? | Contiene el valor que regresó la última orden ejecutada. (0=Exitosa, 1=Falló) |
Pasaje de Argumentos:
Los Scripts pueden recibir parámetros en la línea de comandos. Los parámetros recibidos se guardan en una serie de variables que el Script puede consultar. Estas Variables tienen los siguientes nombres:
Variable | Significado |
$0 | Contiene el nombre con el que se ha invocado el Script |
$1 – $20 | Contiene los valores de los parámetros/argumentos recibidos con la invocación |
$* | Contiene todos los parámetros juntos en una única cadena |
$# | Contiene e número de parámetro que ha recibido el Script |
$? | Devuelve 0 si la ejecución fue correcta |
Además de todas estas utilidades, tenemos la posibilidad de insertar en la ejecución de un Script, lo que un usuario tipea en la línea de comandos. Dicha opción se llama READ. Lo que hace es leer una línea de entrada del usuario y la asigna a una o más variables de la Shell. Detiene el Script y hasta que por línea de comandos no sea ingresado ningún valor por el usuario, el programa estará detenido.
Ejemplo:
#!/bin/sh
echo “Cuál es su nombre?”
read nombre
clear
echo “Su nombre es $nombre”
También puede aceptar más de una a la vez.
Ejemplo:
#!/bin/sh
echo “Cuál es tu nombre y edad?”
read nombre edad
echo “Tu nombre es $nombre y tienes $edad años!”
Input (Entrada), Output (Salida), Redirection (Redireccionar):
Los sistemas basados en UNIX generalmente abren tres archivos descriptivos básicos, para permitirle a un proceso la entrada (stdin) y salida (stdout).
stdout redirection: La información va de izquierda a derecha. Osea, toma el resultado que sale del comando ejecutado en primera instancia y lo plasma en un archivo. EJ: “# fdisk –l > particiones.txt”
El operador “>>” añade al final del archivo el contenido de la salida del comando.
stdin redirection: En este caso la información va de derecha a izquierda. El operador “<” solo puede ser utilizado en stdin. EJ: “fdisk /dva/hda < instructions”. Si instructions posee alguna de las letras p, m, y q, fdisk mostrará la tabla de particiones de /dev/hda.
stderr redirection: stdin, stout y stderr están representados por 0, 1 y 2 respectivamente. EJ: “comando 2> /dev/null”
Pipes: Son un mecanismo por el cual la salida de un programa se puede enviar como la entrada de otro. Cada programa individual, puede ser encadenado para convertirse en herramientas más potentes. Las pipes están representadas por el símbolo “|”.
EJ:
# comando1 | comando2
# cat /etc/passwd | less (Cat muestra el contenido del archivo, y al sr enviado a less, nos permite navegar por todo el contenido).
Pero… ¿Para qué conformarnos solo con esto? Como todo buen lenguaje de programación la Shell posee estructuras de control (if, then, else, case, etc) y ciclos (for, while , etc)
Comando IF:
If en la Shell solo puede evaluar comandos por lo que no podríamos evaluar los valores de las variables, sin el comando test, el cual también pertenece a la Shell. El mismo devuelve 0 de ser verdadero o 1 si es falso.
Ejemplifiquemos:
#!/bin/sh
echo “Ingresa un número”
read numero
if test $numero = 1 (Siempre la expresión debe estar separada por espacios sino da error)
then
echo “El número ingresado es correcto” (Se ejecuta solo si test devuelve como resultado 0)
else
echo “El número ingresado es incorrecto” (Se ejecuta solo si test da como resultado 1)
fi (Se utiliza para terminar if)
Otra forma de escribir test es colocando entre corchetes la condición a evaluar y si quisiéramos poner en la misma línea el then, deberemos colocar luego de la expresión test punto y coma “;”.
Ejemplo:
#!/bin/sh
echo “Ingresa un número”
read numero
if [ $numero = 1 ]; then
echo “El número ingresado es correcto”
else
echo “El número ingresado es incorrecto”
fi
Efectuando comprobaciones:
Comprobaciones de cadena:
Parámetro | Significado |
-z cadena | Verdadero si la longitud de la cadena es 0 |
-n cadena | Verdadero si la longitud de la cadena no es 0. Es decir, si existe cadena |
cadena1 = cadena2 | Verdadero si cadena1 y cadena2 son idénticas |
cadena1 ¡= cadena2 | Verdadero si cadena1 y cadena2 no son idénticos |
cadena1 | Verdadero si cadena1 no es una cadena nula |
Comprobaciones de enteros:
Parámetro | Significado |
n1 –eq n2 | Verdadero si n1 y n2 son iguales |
n1 –ne n2 | Verdadero si n1 y n2 no son iguales |
n1 –gt n2 | Verdadero si n1 es mayor a n2 |
n1 –ge n2 | Verdadero si n1 es mayor o igual que n2 |
n1 –lt n2 | Verdadero si n1 es menor a n2 |
n1 –le n2 | Verdadero si n1 es menor o igual que n2 |
Ejemplo:
#!/bin/bash
clear
numero1=4
echo n “Ingrese un número : ”
read numero2
if [ $numero2 ge $numero1 ]; then
echo “El numero $numero2 es mayor o igual a $numero1”
else
echo “El numero $numero1 es mayor o igual a $numero2”
fi
Ejemplo 2 (operaciones):
#!/bin/bash
echo n ” Ingrese el primer número : ”
read numero1
echo n ” Ingrese el segundo número : ”
read numero2
numero3=$[ $numero1 * $numero2 ]
echo “Resultado :$numero3”
Comprobaciones de archivos:
Parámetro | Significado |
-a | Verdadero si existe el archivo |
-r | Verdadero si existe el archivo y puede leerse |
-w | Verdadero si existe el archivo y puede escribirse |
-x | Verdadero si existe el archivo y es ejecutable |
-f | Verdadero si existe el archivo y es un archivo regular |
-d | Verdadero si existe el archivo y es un directorio |
-h | Verdadero si existe el archivo y es un enlace simbólico |
-c | Verdadero si existe el archivo y es un archivo de caracteres especiales |
Ejempllo:
#!/bin/bash
echo –n “Escriba el archivo que desea verificar : “
read archivo
if [ a $archivo ]; then
echo “Existe el archivo.”
if [ r $archivo ]; then
echo “el archivo puede leerse”
fi
if [ w $archivo ]; then
echo “El archivo se puede escribir”
fi
if [ x $archivo ]; then
echo “El archivo se puede ejecutar”
fi
if [ d $archivo ]; then
echo “El archivo es un directorio”
fi
else
echo “Archivo inexistente : $archivo”
fi
La sentencia case:
Se utiliza cuando tenemos que hacer varios if para hacer una misma comprobación. Siempre se inicia con case y se termina con el comando esac.
Ejemplo:
#!/bin/bash
echo ” Ingrese alguna opcion ”
echo ” 1 Borrar Pantalla”
echo ” 2 donde estoy ”
echo ” 3 Salir ”
echo n ” opcion: ”
read opcion
case $opcion in
1) clear;;
2) pwd;;
3) exit;;
*) echo “ Opcion Incorrecta “
esacecho ” toque una tecla para continuar”
read
La sentencia for:
Toma una lista de cadenas y las asigna a una variable.
La sintaxis del comando es:
For [nombre de la variable] in [lista de opciones]; do
done
Ejemplo1:
#!/bin/bash
for i in `ls *.sh`; do # “`” son las comillas simples de ejecución.
if [ x $i ]; then
echo “el fichero $i es ejecutable.”
fi
done
Ejemplo2:
if [ $# -eq 0 ]
then
echo "Error - Number missing form command line argument"
echo "Syntax : $0 number"
echo "Use to print multiplication table for given number"
exit 1
fi
n=$1
for i in 1 2 3 4 5 6 7 8 9 10
do
echo "$n * $i = `expr $i \* $n`"
done
La sentencia while:
El bucle while se ejecutará siempre que la condición que evaluamos sea verdadera. Se puede usar la palabra clave break para abandonar el bucle en cualquier punto de la ejecución. Con la palabra clave continue el bucle continúa con la siguiente interacción y se salta el resto del cuerpo del bucle.
while [ condicion ]
do
comandos
done
Ejemplo con script variable.sh:
#!/bin/sh
clear
i=0
var1=4
echo -n “Ingrese una variable : ”
read var2
while [ $var2 -ge $var1 ]; do
echo $var2
i=`expr $i + 1`
if [ $i -eq 4 ]; then
break
fi
done
Bueno con esto ya tenemos todo lo necesario para armar los scripts más potentes y automatizar tareas tediosas. Espero que la guía sea de su agrado.
Web: http://www.nicolasventre.com/
Twitter: http://twitter.com/#!/nicolasventre
Facebook: http://www.facebook.com/profile.php?id=1159047781
Linkedin: http://ar.linkedin.com/in/nicolasventre
Si quieren descargar el contenido en formato PDF que se ve más lindo les dejo el link:
Un saludo!