📚 Módulo 5: Organizando y escalando tareas¶
Duración estimada: 4-5 horas según tu ritmo y experiencia.
Objetivo: Organizar el código en funciones reutilizables, usar bucles avanzados (while, until), automatizar tareas con cron y personalizar el entorno con .bashrc. 🎯
Prerrequisitos: Haber completado los Módulos 1-4, saber crear scripts con variables, condicionales y bucles for.
Nota: Las funciones y los bucles avanzados marcan la transición de scripts simples a programas bien estructurados. Dedica tiempo a cada sección.
📖 Contenidos del Módulo¶
5.1. Funciones: Organiza y reutiliza tu código 🌱¶
Teoría:
Una función es un bloque de código con nombre que puedes llamar múltiples veces desde distintos puntos del script. Esto evita repetir código y hace los scripts más fáciles de leer y mantener. La sintaxis básica es:
nombre_funcion() {
# comandos
}
Las funciones pueden recibir argumentos (accesibles como $1, $2, etc. dentro de la función) y devolver un valor de estado con return.
Práctica:
- Crea un script
funciones.sh:
nano funciones.sh
- Define y llama a una función sencilla:
#!/bin/bash
saludar() {
echo "¡Hola, $1!"
}
saludar "Mundo"
saludar "Bash"
Guarda, dale permisos (chmod +x funciones.sh) y ejecútalo.
- Añade una función que reciba dos argumentos:
nano funciones.sh
#!/bin/bash
saludar() {
echo "¡Hola, $1! Tienes $2 años."
}
saludar "Ana" 28
saludar "Luis" 35
- Crea una función que realice un cálculo y guarde el resultado en una variable:
nano funciones.sh
#!/bin/bash
calcular_doble() {
resultado=$(( $1 * 2 ))
echo "$resultado"
}
doble=$(calcular_doble 7)
echo "El doble de 7 es: $doble"
- Añade una función que verifique si un archivo existe:
nano funciones.sh
#!/bin/bash
verificar_archivo() {
if [ -f "$1" ]; then
echo "El archivo '$1' existe."
else
echo "El archivo '$1' NO existe."
fi
}
verificar_archivo "texto.txt"
verificar_archivo "inexistente.txt"
Consejo: Escribe una función para cada tarea concreta. Si una función hace más de una cosa, probablemente debería dividirse en dos. 💡
5.2. Bucles while y until: Repite hasta que sea necesario 🖌️¶
Teoría:
El bucle while ejecuta un bloque mientras la condición sea verdadera. El bucle until es su opuesto: ejecuta el bloque mientras la condición sea falsa (es decir, hasta que se cumpla). Ambos son ideales para situaciones en las que no sabes de antemano cuántas iteraciones necesitas.
# while: repite MIENTRAS la condición es verdadera
while [ condición ]; do
comandos
done
# until: repite HASTA QUE la condición sea verdadera
until [ condición ]; do
comandos
done
Advertencia: Asegúrate siempre de que la condición del bucle puede llegar a ser falsa. Un
while truesin una salida explícita (break) crea un bucle infinito. 🛑
Práctica:
- Crea un script
bucle_while.sh:
nano bucle_while.sh
#!/bin/bash
contador=1
while [ "$contador" -le 5 ]; do
echo "Iteración: $contador"
contador=$(( contador + 1 ))
done
Guarda, dale permisos y ejecútalo.
- Crea un bucle que lea líneas de un archivo:
nano leer.sh
#!/bin/bash
while IFS= read -r linea; do
echo "Línea: $linea"
done < texto.txt
IFS= evita que se recorten los espacios iniciales y finales; -r evita que read interprete las barras invertidas.
- Añade entrada del usuario con límite:
nano limite.sh
#!/bin/bash
contador=1
read -p "¿Hasta qué número quieres contar? " limite
while [ "$contador" -le "$limite" ]; do
echo "Número: $contador"
contador=$(( contador + 1 ))
done
echo "¡Listo! Conté hasta $limite."
- Usa
untilpara esperar a que exista un archivo:
nano esperar.sh
#!/bin/bash
echo "Esperando a que aparezca 'señal.txt'..."
until [ -f "señal.txt" ]; do
sleep 1
done
echo "¡Archivo detectado!"
En otra terminal, crea el archivo con touch señal.txt para desbloquear el bucle.
- Usa
breakpara salir de un bucle antes de que termine:
nano buscar.sh
#!/bin/bash
contador=1
while [ "$contador" -le 10 ]; do
echo "Revisando: $contador"
if [ "$contador" -eq 5 ]; then
echo "¡Encontrado en $contador! Saliendo."
break
fi
contador=$(( contador + 1 ))
done
Consejo: Usa
whilecuando la condición de parada depende del estado del sistema (archivos, procesos, entradas del usuario). Usaforcuando iteras sobre una lista conocida. 💡
5.3. Manejo de errores y señales 🛡️¶
Teoría:
Un script robusto anticipa los fallos. Bash ofrece varias herramientas para manejar errores:
$?— contiene el código de salida del último comando (0= éxito, cualquier otro valor = error).set -e— detiene el script si cualquier comando falla.trap— captura señales y errores para ejecutar código de limpieza antes de salir.
Las señales más comunes son EXIT (al terminar), INT (Ctrl+C) y ERR (cualquier error).
Práctica:
- Comprueba el código de salida de un comando:
nano error.sh
#!/bin/bash
ls /tmp
echo "Código de salida de ls /tmp: $?"
ls /ruta/inexistente
echo "Código de salida del error: $?"
- Usa
set -epara detener el script en el primer fallo:
nano robusto.sh
#!/bin/bash
set -e
echo "Inicio"
ls /ruta/inexistente
echo "Esta línea no se ejecutará"
- Crea una función de manejo de errores:
nano manejador.sh
#!/bin/bash
manejar_error() {
echo "Error en la línea $1. Abortando."
exit 1
}
trap 'manejar_error $LINENO' ERR
echo "Inicio del script"
ls /ruta/inexistente
echo "Fin (no llegará aquí)"
- Usa
trappara limpiar archivos temporales al salir:
nano limpieza.sh
#!/bin/bash
TMPFILE=$(mktemp)
trap "rm -f $TMPFILE; echo 'Limpieza completada.'" EXIT
echo "Usando archivo temporal: $TMPFILE"
echo "datos temporales" > "$TMPFILE"
cat "$TMPFILE"
- Captura Ctrl+C con la señal
INT:
nano interrupcion.sh
#!/bin/bash
trap "echo 'Interrumpido por el usuario. Saliendo.'; exit 0" INT
echo "Ejecutando... Pulsa Ctrl+C para interrumpir."
while true; do
sleep 1
echo "Tick..."
done
Consejo: Usa
trap ... EXITen cualquier script que cree archivos temporales para garantizar que se limpian aunque el script falle. 💡
5.4. cron: Automatiza con el planificador de tareas ⏰¶
Teoría:
cron es el planificador de tareas de Unix/Linux. Permite ejecutar scripts automáticamente en momentos específicos sin intervención humana. La configuración se edita con crontab -e y cada línea sigue el formato:
minuto hora día_del_mes mes día_de_la_semana comando
Cada campo acepta un número, * (cualquier valor), rangos (1-5) o listas (1,3,5).
Práctica:
- Crea un script de log sencillo:
nano log_script.sh
Escribe el siguiente contenido y guarda:
#!/bin/bash
echo "$(date): Registro automático" >> ~/registro_cron.log
Dale permisos de ejecución:
chmod +x log_script.sh
- Verifica que el script funciona manualmente:
./log_script.sh
cat ~/registro_cron.log
- Abre el editor de crontab:
crontab -e
- Añade una entrada para ejecutar el script cada minuto (para pruebas):
* * * * * /ruta/completa/a/log_script.sh
Sustituye /ruta/completa/a/ por la ruta real. Usa pwd para obtenerla. Guarda y cierra el editor.
- Espera un par de minutos y verifica que se han creado entradas en el log:
cat ~/registro_cron.log
Cuando termines la prueba, elimina o comenta la entrada en crontab -e para no llenar el log.
Advertencia: En
cron, el script se ejecuta con un entorno mínimo (sin las variables de tu sesión). Usa siempre rutas absolutas para archivos y comandos. 🛑
5.5. Arrays: Trabaja con colecciones de datos 📊¶
Teoría:
Los arrays en Bash almacenan múltiples valores bajo un mismo nombre. Se accede a cada elemento por su índice (empezando en 0). Sintaxis básica:
mi_array=("valor1" "valor2" "valor3")
echo "${mi_array[0]}" # primer elemento
echo "${mi_array[@]}" # todos los elementos
echo "${#mi_array[@]}" # número de elementos
Práctica:
- Crea y accede a un array:
nano arrays.sh
#!/bin/bash
frutas=("manzana" "naranja" "pera" "uva")
echo "Primera fruta: ${frutas[0]}"
echo "Todas las frutas: ${frutas[@]}"
echo "Total de frutas: ${#frutas[@]}"
- Recorre el array con un
for:
nano arrays.sh
#!/bin/bash
frutas=("manzana" "naranja" "pera" "uva")
for fruta in "${frutas[@]}"; do
echo "Fruta: $fruta"
done
- Añade elementos al array:
frutas+=("mango")
echo "Ahora hay ${#frutas[@]} frutas"
- Recorre el array con sus índices:
for i in "${!frutas[@]}"; do
echo "Índice $i: ${frutas[$i]}"
done
- Crea un script que use un array para almacenar nombres de archivos y procesarlos:
nano procesar.sh
#!/bin/bash
archivos=("texto.txt" "personas.txt" "datos.csv")
for archivo in "${archivos[@]}"; do
if [ -f "$archivo" ]; then
echo "$archivo: $(wc -l < "$archivo") líneas"
else
echo "$archivo: no existe"
fi
done
Consejo: Usa siempre
"${array[@]}"con comillas dobles al iterar para que los elementos con espacios se traten correctamente. 💡
5.6. Gestión del entorno con .bashrc 🏠¶
Teoría:
El archivo ~/.bashrc es un script que Bash ejecuta automáticamente al iniciar cada sesión interactiva. Es el lugar ideal para definir:
- Alias: atajos para comandos que usas frecuentemente.
- Variables de entorno: como
PATHoEDITOR. - Funciones: utilidades personalizadas disponibles en cualquier terminal.
Los cambios en .bashrc no tienen efecto inmediato; hay que recargar el archivo con source ~/.bashrc.
Práctica:
- Visualiza el contenido actual de
.bashrc:
less ~/.bashrc
Usa las flechas para navegar y q para salir.
- Abre
.bashrcpara editarlo:
nano ~/.bashrc
- Añade un alias al final del archivo:
alias ll='ls -lh --color=auto'
alias ..='cd ..'
- Añade una variable de entorno y una función:
export EDITOR=nano
saludo_rapido() {
echo "¡Hola, $(whoami)! Son las $(date +%H:%M)."
}
- Guarda el archivo con
Ctrl+O,Enter,Ctrl+X, y recarga la configuración:
source ~/.bashrc
Ahora prueba los alias y la función en tu terminal:
ll
saludo_rapido
Advertencia: Edita
.bashrccon cuidado. Un error de sintaxis puede impedir que la terminal funcione correctamente. Si eso ocurre, abre.bashrcconnano ~/.bashrcdesde otra sesión y corrige el error. 🛑
🛠️ Ejercicios prácticos¶
- Función: Crea una función
crear_directorioque reciba un nombre, cree la carpeta y muestre un mensaje de confirmación. - While: Crea un script que pida al usuario un número y repita la solicitud mientras no sea mayor que 10.
- Cron: Configura una tarea en
cronque ejecutedate >> ~/fecha_log.txtcada 5 minutos. - Arrays: Crea un array con 5 ciudades y usa un bucle para mostrar cada una con su índice.
- Desafío: Crea un script que use una función para procesar cada línea de un archivo CSV, muestre los datos formateados y guarde el resultado en un informe.
📝 Evaluación¶
Cuestionario (5 preguntas):
- ¿Cuál es la diferencia entre
whileyuntil? - ¿Cómo defines una función que acepte argumentos en Bash?
- ¿Qué hace
trap 'comando' EXIT? - ¿Cómo accedes a todos los elementos de un array en Bash?
- ¿Por qué hay que usar rutas absolutas en las entradas de
cron?
Tarea práctica:
Crea un script gestor.sh que:
- Defina una función registrar que añada una línea con fecha y mensaje a un archivo gestor.log.
- Use un bucle while para mostrar un menú de opciones al usuario (registrar, ver log, salir).
- Maneje la opción de salida limpiamente con trap.
Entrega: El script y el archivo gestor.log generado tras probar el menú.
🎬 Vídeo con la solución de la evaluación: Próximamente.
🎉 Recursos adicionales¶
- Documentación:
man bash(sección "Functions"),man crontab. - Editor de cron online: Crontab.guru — traduce expresiones cron a lenguaje natural.
- Referencia de arrays: Bash Arrays (tldp.org).
Tip: Crontab.guru es indispensable para construir expresiones cron correctas sin memorizar la sintaxis. 💡
🚀 Siguientes pasos¶
¡Felicidades por completar el Módulo 5! En el Módulo 6 aprenderás a conectar tu terminal al mundo real: ssh, curl, jq y monitoreo del sistema. ¡La red te espera! ✍️