Tabla de contenidos
¿Qué es un script?
La programación de scripts en Linux es fundamental para cualquier administrador del sistema operativo. Básicamente, es un lenguaje de programación interno del sistema operativo para realizar y automatizar todas aquellas tareas de administración que necesitemos.
En el mundo profesional, un administrador de sistemas podría administrar más de 500 servidores el sólo, por lo que la automatización mediante scripts es muy importante para agilizar el proceso.
Personalmente, suelo programar con Bash (Bourne Shell). Antes utilizaba más Korn Shell o ksh, cuando administraba los servidores HP-UX. Ahora me dedico más a RedHat y bash es el que viene por defecto (aunque se pueden utilizar otras shells).
Si ya sabéis programar en otros lenguajes de programación, no tendréis mucho problema para aprender Bash. Básicamente, se basa en variables, bucles de repeticiones (while y for), condiciones (if then)… pero orientado a la gestión del sistema operativo.
Uso de variables
Como podemos ver en el siguiente ejemplo, si ejecutamos el script con un punto, un espacio y el nombre del script, imprimiremos por pantalla el valor de la variable $NOMBRE. A esto se le llaman «variables de entorno».
#!/bin/sh
NOMBRE=David
APELLIDO=$1
echo $NOMBRE $APELLIDO
COMANDO=$(grep David nombres.txt)
echo En el fichero nombres.txt se encuenta el nombre $COMANDO
[[email protected] scripts]#
[[email protected] scripts]# ./variables.sh Martinez
David Martinez
En el fichero nombres.txt se encuenta el nombre David
[[email protected] scripts]#
Las variables de entorno se utilizan mucho en los inicios de sesión de los usuarios ($HOME/.profile).
En el ejemplo anterior también hemos visto que el nombre de una variable se asigna como «Nombre_Variable=valor» e imprimiremos su valor poniendo el símbolo del dólar delante ($Nombre_Variable).
Variables especiales
# Guarda el número de parámetros asociados a la ejecución del script.
* Guarda la cadena de caracteres de los argumentos.
? Guarda el código de error devuelto por la última orden del script (0 = sin errores).
@ Guarda la cadena de parámetros entera pero como una lista de cadenas y no como una sola.
$0 En realidad no es una variable reservada, sino que representa al primer campo de la línea de argumentos, que es el nombre del script.
Esto significa que en un script podemos imprimir en pantalla la variable «@», por ejemplo, con «echo [email protected]».
Ejemplo:
# cat parametros.sh #!/bin/bash
PARAMETRO1=$1
PARAMETRO2=$2
PARAMETRO3=$3
[email protected] HORA=$(date)
echo El valor del parametro1 es: $PARAMETRO1 echo El valor del parametro2 es: $PARAMETRO2 echo El valor del parametro3 es: $PARAMETRO3 echo El código de error devuelto por el último comando del script ha sido: $?
echo El número de parámetros asociados a este script son: $# echo Los parámetros que se han pasado son: $*
echo Asignamos un comando a una variable, que nos da la hora actual:
$HORA
# ./parametros.sh param1 param2 param3
El valor del parametro1 es: param1
El valor del parametro2 es: param2
El valor del parametro3 es: param3
El código de error devuelto por el último comando del script ha sido: 0
El número de parámetros asociados a este script son: 3
Los parámetros que se han pasado son: param1 param2 param3
Asignamos un comando a una variable, que nos da la hora actual: lun dic 1 16:22:54 CET 2008
Leer el valor de una variable
Un ejemplo sencillo:
[[email protected] scripts]# cat escribe_nombre.sh
#!/bin/sh
echo Escribe tu nombre:
read Nombre
echo Escribe tu apellido:
read Apellido1
echo Tu nombre completo es: $Nombre $Apellido1
[[email protected] scripts]#
[[email protected] scripts]# ./escribe_nombre.sh
Escribe tu nombre:
David
Escribe tu apellido:
Martinez
Tu nombre completo es: David Martinez
[[email protected] scripts]#
Operaciones aritméticas
Con el comando expr podremos sumar, restar multiplicar o dividir.
Operadores aritméticos | |
+ | Suma |
– | Resta |
* | Multiplicación |
Nota: este símbolo también corresponde con una variables especial para la shell, por lo que si lo queremos usar como multiplicación, lo tendremos que escribir como “\*”. | |
/ | División |
% | Resto de la división |
Operadores relacionales | |
= | Igual |
!= | Diferente |
> | Mayor que |
>= | Mayor o igual que |
< | Menor que |
<= | Menor o igual que |
Operadores lógicos | |
| (pipe) | Operación “O” |
& | Operación y “AND” |
Ejemplo:
[[email protected] scripts]# cat aritmeticas.sh
#!/bin/sh
SUMA=`expr 15 + 30`
echo $SUMA
RESTA=`expr 30 - 20`
echo $RESTA
MULTIPLICA=`expr 2 \* 5`
echo $MULTIPLICA
DIVIDE=`expr 10 / 2`
echo $DIVIDE
RESTO=`expr 13 / 3`
echo $RESTO
[[email protected] scripts]# ./aritmeticas.sh
45
10
10
5
4
[[email protected] scripts]#
Evaluar expresiones con el comando test
- Parámetros relacionados con los archivos:
-f → Devuelve 0 si el archivo existe y no es ni un directorio ni un dispositivo.
-s → Devuelve 0 si el archivo existe y tiene un tamaño mayor que 0.
-r → Devuelve 0 si el archivo existe y tiene permiso de lectura.
-w → Devuelve 0 si el archivo existe y tiene permiso de escritura.
-d → Devuelve 0 si la búsqueda pertenece a un directorio.
- Parámetros relacionados con las cadenas de texto:
-z → Devuelve 0 si el número de caracteres de una cadena es igual 0.
-n → Igual que el parámetro anterior con la diferencia de que comprueba que el tamaño de la cadena sea mayor que 0.
- Parámetros relacionados con números:
-lt → Menor que
-le → Menor o igual que
-gt → Mayor que
-ge → Mayor o igual que
-eq → Igual a
-ne → Diferente a
Ejemplo:
[[email protected] scripts]# cat testsc.sh
#!/bin/bash
echo -n "Vamos a comprobar que existe el archivo testsc.sh: "
test -f "testsc.sh"
echo $?
CADENA="Soy una cadena de texto"
echo -n "Vamos a comprobar si una cadena de texto está vacía: "
test -z "$CADENA"
echo $?
NUM1=10
NUM2=20
echo -n "Vamos a comprobar si NUM1 es mayor que NUM2: "
test $NUM1 -gt $NUM2
echo $?
[[email protected] scripts]#
[[email protected] scripts]# ./testsc.sh
Vamos a comprobar que existe el archivo testsc.sh: 0
Vamos a comprobar si una cadena de texto está vacía: 1
Vamos a comprobar si NUM1 es mayor que NUM2: 1
[[email protected] scripts]#
Bucle if then
Se utiliza para ejecutar una función si se cumple una condición.
Ejemplo:
[[email protected] scripts]# cat ifsc.sh
#!/bin/bash
# Comprobamos si está escuchando el puerto 80, típico de un Webserver
WS=`netstat -an |grep " 80 " |grep LISTEN`
# Si la cadena de texto está vacía
if [[ -z $WS ]]
then
echo No tenemos ningún servicio arrancado y escuchando por el puerto 80.
# De lo contrario else echo Tenemos un Webserver arrancado
else
echo El Webserver si esta arrancado por el puerto 80
fi
[[email protected] scripts]#
[[email protected] scripts]# ./ifsc.sh
No tenemos ningún servicio arrancado y escuchando por el puerto 80.
[[email protected] scripts]#
Bucle case esac
Compara el valor de una variable con cada uno de sus condicionantes.
Ejemplo:
# cat casesc.sh
#!/bin/bash
echo Escribe un número del 1 al 3:
read NUM
case $NUM in
1) echo Has escrito el número 1;;
2) echo Has escrito el número 2;;
3) echo has escrito el número 3;;
*) echo El número o la palabra escrita no coincide con el rango solicitado;;
esac
#
# ./casesc.sh Escribe un número del 1 al 3:
2
Has escrito el número 2
[[email protected] scripts]$ ./casesc.sh Escribe un número del 1 al 3:
5
El número o la palabra escrita no coincide con el rango solicitado
#
Bucle while
Se ejecutan una serie de instrucciones mientras se cumple una condición.
Ejemplo:
[[email protected] scripts]# cat whilesc.sh
#!/bin/sh
while read line
do
echo $line
done < nombres.txt
[[email protected] scripts]#
[[email protected] scripts]# ./whilesc.sh
David
Javi
Laura
Jordi
[[email protected] scripts]#
Bucle for
Se ejecutan una serie de instrucciones hasta que finalice el recorrido de una lista.
[[email protected] scripts]# cat forsc.sh
#!/bin/bash
for i in `seq 1 10`; do
echo el valor de la variable 'i' es: $i
done
[[email protected] scripts]#
[[email protected] scripts]# ./forsc.sh
el valor de la variable i es: 1
el valor de la variable i es: 2
el valor de la variable i es: 3
el valor de la variable i es: 4
el valor de la variable i es: 5
el valor de la variable i es: 6
el valor de la variable i es: 7
el valor de la variable i es: 8
el valor de la variable i es: 9
el valor de la variable i es: 10
[[email protected] scripts]#
Salir de un bucle while o for
Para salir de un bucle while o for antes de que finalice, utilizaremos las siguientes instrucciones dentro del bucle:
- break: Salimos completamente del bucle y continuamos con la ejecución del script.
- continue: Salimos de la ejecución actual del bucle pero continuamos con la siguiente repetición.
- exit n: Detiene la ejecución del script y se asigna a n el código de error.
Uso de arrays o conjuntos
Un array es un conjunto de variables agrupadas en una sola pero que podemos apuntar a cada uno de sus valores de manera individual.
[[email protected] scripts]# cat array.sh
#!/bin/bash
miarray=(rojo verde azul)
echo Valor de la primera posición del array: ${miarray[0]}
echo Valor de la segunda posición del array: ${miarray[1]}
echo Valor de la tercera posición del array: ${miarray[2]}
[[email protected] scripts]#
[[email protected] scripts]# ./array.sh
Valor de la primera posición del array: rojo
Valor de la segunda posición del array: verde
Valor de la tercera posición del array: azul
[[email protected] scripts]#
Funciones creadas por nosotros mismos
Con el objetivo de ahorrar código, podemos escribir una función y llamar al código de esa función cada vez que lo necesitemos.
Ejemplo:
Fichero con la definición de funciones
# cat linux_system.lib
#!/bin/ksh
linux_system_halt ()
{
echo Stopping the system
cd /
/sbin/shutdown -h 0
}
linux_system_reboot ()
{
echo Rebooting the system
cd /
/sbin/shutdown -r 0
}
cpu_usage ()
{
echo "%CPU PID USER COMMAND"
ps -eo pcpu,pid,user,args | sort -rnk1 | head -10
}
memory_usage ()
{
echo Los 20 procesos que mas memoria estan consumiendo:
echo
ps -e -o vsz=Kbytes -o ruser -o pid,args=Command-Line | sort -rnk1 | head -20
}
get_num_processors ()
{
NUMPROCESSORS=`cat /proc/cpuinfo |grep MHz |wc -l`
echo "Este servidor tiene $NUMPROCESSORS CPUs".
}
get_memory_assigned ()
{
/usr/bin/free |head -2
}
#
Script que hace llamadas a las funciones definidas previamente
# cat linux_system.sh
#!/bin/ksh
# Library load
LPATH=/usr/local/bin/sh_expl/LIB
. $LPATH/linux_system.lib
#########################
ACTION=$1
case $ACTION in
reboot_linux) linux_system_reboot ;;
halt_linux) linux_system_halt ;;
cpu_usage) cpu_usage ;;
memory_usage) memory_usage;;
num_processors) get_num_processors;;
get_memory_assigned) get_memory_assigned;;
*) Option not implemented ;;
esac
#
Lo que he explicado en este artículo es muy básico pero ya sirve para comenzar a crear nuestros primeros scripts.