LPIC-1 Tema 105.2: Modificar o escribir scripts sencillos
Siguiente artículo sobre las certificaciones LPIC-1, con la introducción al tema 105.2. Es decir, lo referente a personalizar y escribir pequeños scripts muy simples. Por supuesto, el shell que abarcan estas certificaciones LPI es Bash, por lo que las preguntas irán orientadas a scripts para este sh.
Para ello, los candidatos a administradores de sistemas GNU/Linux deberán demostrar sus habilidades sobre esta temática, haciendo uso de una sintaxis correcta (loops, tests,…), saber evaluar los valores retornados por el script, así como los errores que pueda dar, conocer el shebang adecuado, etc.
¿Qué es un script?
Un script o guión es un código escrito en un lenguaje de programación o con una serie de comandos u órdenes relativamente simples. Se diferencian de los códigos fuente de los lenguajes de programación compilados en que no necesitan ser compilados. Será un intérprete el que ejecute las órdenes escrita en este script, de ahí que los lenguajes de programación de este tipo se conozcan como lenguajes interpretados (Ruby, Python, AWK, Java, Perl, PHP,…).
En el caso que nos toca, el intérprete será el propio shell, es decir, Bash será el encargado de interpretar y ejecutar las órdenes que contiene el script.
Como podrás comprobar, los scripts se componen de comandos que usas en el shell tradicionalmente. El objetivo de introducirlos dentro de un script es automatizar ciertas tareas o ejecutarlos en «lotes» para ahorrar trabajo al administrador de sistemas, especialmente para tareas de mantenimiento. Verás que son super prácticos…
Shebang, extensión y ejecución
Antes de comenzar a ver algunos scripts de ejemplo y ciertas funciones que debes conocer, tienes que conocer bien estos conceptos:
- Extensión: este tipo de scripts suele tener la extensión .sh. Puedes usar cualquier editor de texto para escribir las órdenes y guardar el fichero con el nombre que prefieras seguido de .sh para que luego el shell Bash pueda interpretarlo. Por supuesto, debe tener permisos de ejecución…
- Syscall exec(): en Linux esta será la llamada al sistema que se encargará de comprobar si el fichero es de texto, un binario, o si contiene órdenes sin compilar. En caso de ser un script le pasa el contenido al intérprete adecuado para que lo ejecute. Una de las cosas necesarias para identificar al intérprete es el shebang.
- Shebang: se necesita poner una especie de cabecera que identifica al intérprete, es decir, a Bash en este caso. Siempre comienza por #! seguido de la ruta del binario donde se aloja el intérprete en el sistema. Si no la conoces podrías usar el comando which bash para localizarlo. Por ejemplo, para Bash sería:
#El shebang por defecto es: #!/bin/bash #Podría ser también el enlace simbólico hacia el shell por defecto #!/bin/sh #E incluso este otro si el binario no está en una ruta absoluta conocida: #!/usr/bin/env bash
- Ejecución: para ejecutar el script en Bash, puedes usar varias formas. Por ejemplo, si tienes que ejecutar un script llamado ejemplo.sh, podrías con algunas de estas opciones (podrías usar sudo o ejecutarlos como root si es necesario):
#Opción básica ./ejemplo.sh #Ejemplo con sh y usando la ruta completa (si se encuentra en otro directorio o no está en $PATH) ssh ~/ejemplo.sh #Ejemplo con sh con la opción -x para que muestre los comandos en ejecución sh -x ejemplo.sh #Ejemplo con source source ejemplo.sh #Exec permite que el proceso a ejecutar sustituya al proceso anterior y tome su PID: exec ejemplo.sh
- #: para los comentarios dentro de un script se puede preceder el mensaje de este símbolo para que el intérprete ingore esa línea. Por ejemplo:
#Esto es un comentario
Sintaxis e introducción al shell scripting
Más información – Shell scripting y variables de entorno
Para crear un script, es muy sencillo. Por ejemplo, para crear un Hola mundo podrías hacer lo siguiente:
nano hola.sh
Dentro del editor puedes escribir las órdenes, en este caso un simple echo para mostrar el mensaje Hola mundo:
#!/bin/bash echo Hola mundo
Podrías sustituir lo anterior para escribirlo en forma de función en vez de tipo lista. Por ejemplo (por cierto, no cambies el orden de la llamada a la función antes de la propia declaración de la función o dará error):
#!/bin/bash funcionprueba(){ echo "Hola mundo" } funcionprueba
También podrías seguir agregando más comandos, y no solo el echo. Por ejemplo:
#!/bin/bash funcionprueba(){ echo "Hola mundo" echo "Fin" clear } funcionprueba
Sea como sea, guarda el contenido y ahora le das permisos de ejecución y lo puedes ejecutar para ver el resultado:
chmod +x hola.sh ./hola.sh
Por último, deberías saber que puedes usar todos los comandos conocidos para ejecutarlos dentro del script. Además de ellos, puedes usar estas otras funciones o comandos muy prácticos:
- for: bucle para incrementar o disminuir los contadores. Por ejemplo, en este script lo único que se irá mostrando la cuenta atrás, pero podrías usarlo para ejecutar otras órdenes…
#!/bing/bash for (( contador=10; contador>0; contador-- )) do echo -n "$contador " done
- while: otra forma de usar bucles, esta vez para que se mantenga mientras que se cumpla, contador, o se verifica alguna condición. Por ejemplo, para que muestre una serie de números del 0 al 10:
#!/bing/bash contador=0 terminar=10 while [ $terminar -ge $contador ] do echo $contador let contador=$contador+1 done
- until: ciclo o bucle que ejecutará el bloque de instrucciones que contiene mientras no se cumpla una condición dada. Es decir, la diferencia con while es que verifica si la condición es falsa, y si lo es ejecuta las instrucciones entre do y done. Si fuese verdadera no lo haría. Por ejemplo:
#!/bing/bash contador=0 terminar=10 until [ $terminar -ge $contador ] do echo $contador let contador=$contador+1 done
- if – then – else: condición. Por ejemplo, imagina que quieres detectar si un servidor está conectado o no. Para ello, puedes usar el comando ping con la IP del servidor que quieres comprobar y si se cumple la condición de que ping falle, entonces muestra el primer mensaje, en otro caso (si ping obtiene conexión) muestra el mensaje tras else:
#!/bing/bash ping -c 1 216.58.198.195 if [ $? -ne 0 ]; then echo "Servidor desconectado" else echo "Servidor conectado" fi
- test: es un comando que evalúa expresiones y resulta práctico para las condiciones. Por ejemplo, se puede combinar con until de esta forma para contar de 3 en 3 hasta 75:
#!/bin/bash x=2 until test $x –eq 75 do x=`expr $x +3` echo $x done
- read: permite leer valores introducidos, por lo que es práctico para evaluar estos datos y tomar decisiones en función de ello. Por ejemplo, en este script se seguiría ejecutando el bucle hasta que no introduzcas el número que se te pide (el 735):
#!/bin/bash numero=735 echo “Introduce un número:” while true; do read valor if [ $numero = $valor ]; then echo “Acertaste” break else echo “Mala suerte...Inténtalo de nuevo” fi done
- select: se puede usar para crear menús interactivos para tu script. Es una estructura de control que mostrará los ítems y se iniciará la variable correspondiente al valor introducido por el usuario. Por ejemplo:
#!/bin/bash clear PS3=”¿Qué desea hacer?:” select opcion in “1.Crear directorio” “2.Borrar” “3.Salir” do case $opcion in 1) mkdir /home/directorio ;; 2) rm /home/directorio ;; 3) exit ;; *) echo “No es un ítem válido del menú” ;; esac done
- break y continue: comandos que pueden combinarse con los anteriores para romper los bucles o comprobar nuevamente la condición del bucle respectivamente. Por ejemplo, puedes crear un script para que si detecta una q salga o si detecta una c siga:
#!/bin/bash while [ $# -gt 0] do if [ $1 = “q” ] then break fi echo El parámetro es: $1 shift done
#!/bin/bash while [ $# -gt 0] do if [ $1 = “c” ] then shift continue fi echo El parámetro es: $1 shift done
- sleep y wait: esperan algo, en el primer caso pausará durante un tiempo especificado y en el segundo caso espera a que un proceso termine. Por ejemplo:
#!/bin/bash echo “Espera 5 segundos” sleep 5 echo “¡Listo!”
#!/bin/bash echo "Esperando un proceso" & process_id=$! wait $process_id echo "Finalizado con estatus $?"
- Agregar parámetros (interactividad): se puede usar $1, $2, $3,… para leer parámetros que introduzcas tras el comando de ejecución como opciones. Por ejemplo, podrías crear un script para hacer cópias de seguridad usando la orden ./nombre_script.sh /ruta/de/entrada /ruta/de/salida. Es decir, especificar la ruta donde se encuentre lo que quieres copiar y la ruta donde se guarde la copia. Para eso, deberías usar algo así:
#/bin/bash echo "¿Quieres copiar $1 a $2 ? - Pulsa Ctrl+C para salir si no es lo que quieres." sleep 3 echo "Copiando..." tar -cvpzf $2.tar.gz $1 echo "La copia de seguridad de $1 se completó con éxito." notify-send -t 8000 "Copia $1 realizada" exit
- seq: puede generar una secuencia de números. Por ejemplo, puedes eliminar los ficheros de que se llamen nombre1 a nombre4 de un directorio:
#!/bin/bash for n in ‘seq 4’ do rm fichero$n done
- También puedes usar las salidas de otros comandos, tuberías, redirecciones, etc., dentro de tu script. Por ejemplo, en el siguiente caso se puede usar date para obtener la fecha actual y usar dicha fecha para nombrar una supuesta cópia de seguriad:
#!/bin/bash fecha=`date "+%d-%m-%y_%H-%M-%S"` nombre="respaldo_$fecha.tgz" destino="~/Backups" respaldo="copiaSeguridad" #Creará el directorio destino y empaqueta "copiaSeguridad" en un tarball mkdir -p "$destino" tar cfvz "$destino/$nombre" "$respaldo"
- ||, &&, ;, …: representan operadores. Por ejemplo, || es el operador lógico OR, mientras que && es el operador lógico AND. Aquí tienes algunos ejemplos de usos:
#En este caso mostrará la palabra hola, puesto que false no se cumple nunca y por tanto ejecuta echo false || echo "hola" #En este caso no mostrará nada porque true siempre se cumple true || echo "hola" #Muestra el resultado porque lo anterior se cumple true && echo "hola" #No se muestra el resultado de echo porque lo anterior no tiene éxito (false) false && echo "hola" #Se muestra el mensaje en ambos, ya que ; da igual lo que ocurra antes false ; echo "hola" true ; echo "hola"
Existen otras funciones, operadores, etc., pero estos son los más básicos para ir comenzando.
En un futuro publicaré más scripts prácticos, por ahora cierro con este último ejemplo de algo más práctico para no seguir alargando este artículo…
Recuerda que puedes también automatizar la ejecución de estos scripts con cron, crontab, agregarlos para que se ejecuten durante el arranque o durante el apagado del sistema, etc.