Shell scripting
SHELL SCRIPTING
Pese a que lenguajes como PHP, python o perl son mas poderosos que el shell scripting, no siempre se encuentran disponibles para la ejecución. P. e. cuando inicia el sistema, init.d, necesita ejecutar procesos que se ejecutan como un script de shell. Nadie pensaria en ese momento correr un programa en perl, php, o python.
Llamaremos al script pruebas.sh y le daremos permisos de ejecucion (chmod +x)
script que preguntara al usuario su nombre, y lo mostrara por pantalla:
#!/bin/bash
echo “ingrese su nombre”
read nombre # nombre, es una variable.
echo “hola $nombre”
Variables de Entorno: Son las que forman parte del sistema operativo, y pueden ser modificadas por el usuario, mediante el comando export y pueden ser visualizadas con el comando set.
Variables Incorporadas: Son las que no pueden ser manipuladas por el usuario
E. de variables incorporadas son:
$# —->Numero de parámetros que utilizara el script
$X —–>Numero del parámetro empezando desde 0 que es el nombre del script.
$* —–>Todos los parámetros entregados al script.
Variables definidas: Son las que definiremos en el scripts. NOTA.- en el momento de la definición, se hace como VARIABLE=valor, y luego al usarla, se tiene que anteponer el signo $. E.:
#!/bin/bash
#Este es una prueba
#Nombre : script-demo.sh
echo “el numero de parametros que se pasan es : ” $#
echo “el nombre del programa es : ” $0
echo “Los parametros son : ” $*
al ejecutar el script:
#./script-demo.sh viva la republica
el numero de parámetros que se pasan es : 3
el nombre del programa es: script-demo.sh
Los parámetros son : viva la republica
La funcion de las comillas dobles es resolver las variables.
#!/bin/bash
#Nombre : comillas-dobles.sh
variable=”Prueba de Shell”
nueva=”el valor de variable es $variable”
echo $nueva
Al ejecutar el programa, la salida es: el valor de variable es Prueba de Shell
Las comillas simples no resolverán las variables.
#!/bin/bash
#Nombre: comillas-simples.sh
variable=’Prueba de shell’
nueva=’el valor de variables es: $variable’
echo $nueva
La salida sera: el valor de variable es: $variable
El bloque básico de decisión, esta dado por la sentencia if. La sinapsis:
if <condicion>
then
<sentencias>
else
<sentencias>
fi
Para la comparación entre cadenas se usara los siguientes simbolos:
= Realiza la comparación entre cadenas si son iguales
!= Decide si son distintas
-n Informa si la cadena tiene longitud mayor a cero
-z Informa si la cadena tiene longitud igual a cero
Ejemplos:
#!/bin/bash
#Nombre Programa: Comparar cadenas
cadena1=”abc”
cadena2=”bbc”
if [ $cadena1 = $cadena2 ]
then
echo “las cadenas son iguales”
else
echo “las cadenas son distintas”
fi
Veamos utilizando el signo de desigualdad
#!/bin/bash
#Nombre Programa: Comparar cadenas
cadena1=”abc”
cadena2=”bbc”
if [ $cadena1 != $cadena2 ]
then
echo “las cadenas son distintas”
fi
En este script veremos si cadena2 tiene una longitud cero:
if [ -z $cadena2 ]
then
echo “la cadena2 tiene longitud cero”
else
echo “la longitud de la cadena2 es mayor a cero”
fi
Manejo de archivos:
Con if, también podemos ver si un archivo o un directorio existe o no, y en caso negativo crearlo.
#!/bin/bash
#Nombre Programa: directorios.sh
if [ -d /tmp/cambios ]
then
echo “directorio existe”
else
echo “directorio no existe, se crea!”
mkdir /tmp/cambios
fi
La expresión [ -d /tmp/cambios ] evalúa si el directorio /tmp/cambios existe. En caso de existir, no se hace nada, si no existe se genera.
#!/bin/bash
#Nombre Programa: archivos.sh
if [ -f /tmp/demo.txt ]
then
echo “archivo existe”
else
echo “archivo no existe, se crea!”
touch /tmp/demo.txt
fi
La expresión [ -f /tmp/demo.txt ] evalua si el archivo /tmp/demo.txt existe. En caso de existir no se sabe nada, si no existe se lo genera.
ahora lo que nos interesa es pasarle un parámetro, para consultar el archivo. Por ejemplo, si al programa archivos.sh, le pasamos un parámetro, para consultar si existe
#!/bin/bash
if [ -f $1 ]
then
echo “Archivo existe”
else
echo “Archivo no existe”
fi
Aunque este programa sigue teniendo un problema. Si ejecutamos el script sin parámetros, igualmente se ejecuta. Deberíamos correr el script con parámetros, y para eso vimos anteriormente como calcular el numero de parámetros pasados.
#!/bin/bash
if [ $# -eq 0 ]
then
echo “no paso parametros”
exit
else
if [ -f $1 ]
then
echo “archivo existe”
else
echo “archivo no existe”
fi
fi
Shell scripting, nos permite, saber si un archivo, existe, tiene permisos de ejecución, de escritura, o de lectura, con los siguientes flags:
-x Permisos de ejecución
-w Permisos de escritura
-r Permisos de Lectura
-f Archivo Existe
-d directorio Existe
Ejemplos:
#!/bin/bash
#NombrePrograma: existe.sh
ARCHIVO=$1
if [ -f $ARCHIVO ]
then
echo “$ARCHIVO” Existe
else
echo “$ARCHIVO NO EXISTE”
fi
$ ./existe /etc/passwd
nos retornara que el archivo existe.
#!/bin/bash
#NombrePrograma: ejecuta.sh
ARCHIVO=$1
if [ -x $ARCHIVO ]
then
echo “$ARCHIVO Tiene Permisos de Ejecucion”
else
echo “$ARCHIVO NO Tiene Permiso de Ejecucion”
fi
$ ./existe /etc/passwd
nos retornara que el archivo no tiene permiso de ejecución (Siempre y cuando, el archivo exista, por lo cual, sera una muy buena idea, ver que el archivo exista antes de ver que tenga permisos de ejecución).
Podemos usar for de varias maneras:
#!/bin/bash
#Nombre Programa: for.sh
for i in 1 2 3 4 5 6
do
echo $i
done
Al ejecutar el programa, vemos como se repiten los números, del 1 al 6.
E. de bucles anidados para realizar las tablas de multiplicar.
#!/bin/bash
for i in 0 1 2 3 4 5 6 7 8 9
do
echo “tabla del $i”
for j in 0 1 2 3 4 5 6 7 8 9
do
echo -n “$i x $j = “
echo `expr $i \* $j`
done
done
Las `, se utilizan para evaluar una condición que puede entregar la salida a una variable, de algún comando de sistema. La aritmética en shell scripting se interpreta mediante el comando expr. La \ antes de el comando de multiplicación, que es el * desactiva los comandos de shell que en este caso seria un comodin.
Breve explicación de expr.
expr 1 + 3
expr 2 – 1
expr 10 / 2
expr 20 % 3
imaginemos, que tenemos un listado, que diga, juan, pedro, pepe, alejandro, luis, llamado, usuarios.txt
juan
pedro
pepe
alejandro
luis
Queremos generar, con ese listado, usuarios de sistema. Podríamos hacer
#!/bin/bash
for i in `cat usuarios.txt`
do
useradd -m $i
echo “$i:$i”|chpasswd
done
Nos generara , desde una lista de usuarios, los usuarios, con el mismo password.
Para tareas repetitivas, se recomienda el uso de funciones. Para definir una función en shell scripting, lo que se debe hacer, es lo siguiente
function nombre_funcion()
E. podemos definir una funcion, que se llame, demostración:
function demostracion()
{
<comandos a ejecutar>
}
P. e., podemos hacer el siguiente programa, para ilustrar el uso de funciones
#!/bin/bash
#NombrePrograma: funciones.sh
function demo()
{
echo “Solo para demostrar el uso de la funcion”
}
demo
El programa hace la llamada a la función, en la linea que dice demo
Si queremos hacer una función, que realice el paso de parámetros, lo haremos:
#!/bin/bash
#NombrePrograma: pasado.sh
function pasado()
{
PARAMETRO=$1
echo “Se paso $PARAMETRO”
}
pasado “coco”
con lo que vemos, que luego de pasado, entre comillas, pasamos los parámetros, que los tomara como $1, $2, etc.
awk, es un comando, que entre otras cosas, se usa para el parseo de archivos. Es muy útil cuando queremos mostrar columnas, de un archivo, que tienen un delimitador. P. e., en el /etc/passwd, podríamos imprimir, el nombre de los usuarios, que corresponde al primer campo. P. e. una linea del /etc/passwd, seria así.
pepe:x:1003:1003:,,,:/home/pepe:/bin/bash
Los campos están delimitados por :.Si queremos sacar todos los nombres de usuarios y mandarlos a un archivo usuarios.txt
awk -F “:” ‘{print $1}’ /etc/passwd
Como ejemplo haremos un script, que nos imprima los usuarios de sistema, con uid mayor a 500.
#!/bin/bash
#NombrePrograma: uid.sh
for i in `awk -F “:” ‘{print $3}’ /etc/passwd`
do
if [ $i -gt 500 ]
then
USUARIO=`grep $i /etc/passwd`
echo $USUARIO
fi
done
Unix permite enlazar dos o mas comandos usando un pipe. El pipe toma la entrada standard de la salida estandard de otro comando. La | (barra vertical) se usa para representar la conexión de los comandos. E. :
who | wc -l
342
Este comando dice cuantos usuarios están conectados al sistema.
who saca por la salida standard una lista de usuarios conectados al sistema
wc -l cuenta el numero de líneas de la entrada standard y lista el resultado.
ps -aux|grep joe|sort +5 -6|less
El primer comando ps -aux saca información sobre los procesos que corren
actualmente. Esta información entra a la entrada del comando grep joe que
busca una línea que contenga el usuario “joe”. La salida de este comando se
clasifica por el sexto campo de cada línea y esta salida se displaya en el
less.
Ejemplo de if con un pipe:
if who | grep -s keith >/dev/null
then
echo keith está conectado
else
echo keith no está conectado
fi
La lista de who se pasa a grep para buscar al usuario keith, la opción -s
consigue que grep trabaje silenciosamente y cualquier mensaje de error es
direccionado al fichero /dev/null.
Dependiendo de que keith se encuentre o no en la lista de usuarios se
saca un mensaje u otro.
La instrucción while tiene la forma general :
while lista-de-comandos1
do
lista-de-comandos2
done
Los comandos de lista-de-comandos1 se ejecutan, y si el status del último comando de la lista es 0, se ejecutan los comandos de lista-de-comandos2. La sequencia se repite mientras el status de lista-de-comandos1 es 0.
La instrucción until tiene la forma general :
until lista-de-comandos1
do
lista-de-comandos2
done
Su función es idéntica a while excepto en que el bucle se ejecuta mientras en status de lista-de-comandos1 no es 0.
Ejemplos :
#!/bin/sh
while who |grep -s $1 >/dev/null
do
sleep 60
done
echo “$1 está desconectado?
El script verifica si el usuario que se pasa como argumento está conectado,
mientras lo está el script espera 60 segundos antes de hacer una nueva
verificación.
#!/bin/sh
until test -f $FILE
do
sleep 60
done
echo “$FILE now exists”
Verifica cada 60 segundos si existe el fichero representado por la variable
$FILE.
La instrucción break termina la ejecución del bucle mas interior causando la ejecución de la instrucción done mas cercana.
Para salir del nivel n, usa : break n, esto causa la ejecución de la instrucción done n.
El comando continue causa la ejecución de la instrucción while, until o for en la cual comienza el bucle que contiene el comando continue.
Ejemplo :
#!/bin/sh
while echo “Por favor introduce un comando”
read respuesta
do
case “$respuesta” in ‘fin’)
break # no mas comandos
;;
“”)
continue # comando nulo
;;
*)
eval $respuesta # ejecuta el comando
;;
esac
done
Mientras el usuario introduzca un comando o un string
nulo el script continua funcionando. Para pararlo el
usuario debe teclear ?fin?.
Se puede incluir texto en un shell usando el símbolo << el cual se usa para indicar que el texto debe ser leído hasta una marca dada, por ejemplo :
#!/bin/sh
# Este script muestra el mensaje dado, antes de ejecutarse
cat << EOF
Este shell script esta actualmente en desarrollo, por favor
reporte cualquier problema a Daniel. Gracias.
EOF
exec /usr/local/test/bin/test_version
La función eval toma los argumentos de la línea de comandos y los ejecuta como comandos. Por ejemplo :
#!bin/sh
echo ?enter a command:?
read command
eval $command
Exec ejecuta un comando sin crear un nuevo proceso. Una vez terminada la ejecución el shell continúa.
exec zmail -visual
Ejecuta zmail y cuando termina continúa el shell.
Para finalizar un shell script se utiliza el comando exit.
Depuración de Shell scripts
Para ver donde se produce un error en un script:
sh -x script argument
La opción -x lista los comandos y los argumentos que son ejecutados permitiendo ver qué partes del script se han ejecutado cuando ocurre el error.
La opción -n hace que no se ejecute ningún comando, solo chequea la sintaxis.
La opción -e en modo no interactivo, hace que si un comando falla se termine inmediatamente el script.
La opción -v imprime las líneas de entrada según son leídas
8 Octubre, 2008 a las 2:47 am |
El ejercicio de ver si el usuario está logueado me lo pidieron en una guia de la facultad…jajaja los de mi Facu andan buscando ejercicios en paginas!!!:P….son unos chantas!!
8 Octubre, 2008 a las 2:48 am |
Me olvideeee, gracias! está buena la página, y tiene muchos ejercicios de muestra, abrazoooo
27 Septiembre, 2009 a las 4:35 pm |
Saludos amigo, felicitaciones esta muy buena tu pagina disculpa pero tengo dos dudillas:
1- en shell script es posible usar el lengt para conocer la longitud de un parametro pasado como cadena
2-como se podria hacer de forma optima reconocer si un parametro pasado es un numero (incluyendo si es negativo) o una cadena existe algun comando o hay que recorrer toda la cadena comparando cada caracter con [Aa-zZ] gracias de antemano.