Volver al índice

Módulo 5: Programación y Scripts

Shell scripting, control de flujo, funciones y buenas prácticas

Introducción a Shell Scripts

#!/bin/bash # hola_mundo.sh - Mi primer script # ------------------------------------------------- echo "¡Hola, mundo!" echo "Fecha: $(date)" echo "Usuario: $USER" echo "Directorio actual: $(pwd)"

Para ejecutar un script:

chmod +x hola_mundo.sh
./hola_mundo.sh
bash hola_mundo.sh
# Variables NOMBRE="Juan" EDAD=25 RESULTADO=$(ls -la) # Guardar salida de comando
echo "Hola, $NOMBRE" # Hola, Juan echo "Tienes $EDAD años" # Tienes 25 años

Argumentos y Control de Flujo

# Argumentos del script # $0: Nombre del script # $1, $2, ...: Argumentos # $#: Número de argumentos # $@: Todos los argumentos # $?: Código de salida del último comando
# Ejemplo: procesador_argumentos.sh #!/bin/bash
echo "Script: $0" echo "Primer argumento: $1" echo "Segundo argumento: $2" echo "Total argumentos: $#" echo "Todos: $@"
# Condicionales if/else if [ $# -eq 0 ]; then echo "Error: No hay argumentos" exit 1 elif [ $1 = "start" ]; then echo "Iniciando..." elif [ $1 = "stop" ]; then echo "Deteniendo..." else echo "Comando no reconocido" fi

Bucles y Arrays

# Bucle for for i in 1 2 3 4 5; do echo "Número: $i" done
for i in {1..10}; do echo "Número: $i" done
for archivo in *.txt; do echo "Procesando: $archivo" done
# Bucle while contador=1 while [ $contador -le 5 ]; do echo "Contador: $contador" contador=$((contador + 1)) done
# Arrays frutas=("manzana" "pera" "naranja") echo "Primera fruta: ${frutas[0]}" # manzana
# Recorrer array for fruta in "${frutas[@]}"; do echo "Fruta: $fruta" done
# Arrays asociativos (bash 4+) declare -A persona persona[nombre]="Juan" persona[edad]=25 echo "Nombre: ${persona[nombre]}"

Funciones y Depuración

# Definir función saludar() { local nombre=$1 echo "¡Hola, $nombre!" return 0 }
# Llamar función saludar "Juan" saludar "María"
# Función con valor de retorno sumar() { local resultado=$(( $1 + $2 )) echo $resultado }
total=$(sumar 5 3) echo "Total: $total" # Total: 8
# Depuración de scripts # Ejecutar con opciones de depuración: bash -x script.sh # Muestra cada comando antes de ejecutar
# O dentro del script: set -e # Termina en el primer error set -u # Error si usa variable no definida set -x # Modo depuración set -o pipefail # Considera error si falla algún comando en pipeline

Entrada/Salida y Procesamiento

# Leer entrada del usuario read -p "Introduce tu nombre: " nombre echo "Hola, $nombre"
# Contraseña (sin eco) read -s -p "Contraseña: " password echo
# Redirección de entrada/salida comando > archivo.txt # Sobrescribir comando >> archivo.txt # Añadir al final comando 2> errores.log # Solo errores comando &> todo.log # Salida y errores
# Procesamiento de texto # cut - extraer columnas echo "uno:dos:tres" | cut -d: -f2 # dos
# sed - editor de flujo echo "hola mundo" | sed 's/mundo/linux/' # hola linux
# awk - procesamiento avanzado awk '{print $1}' archivo.txt # Primera columna awk -F: '{print $1}' /etc/passwd # Nombres de usuario

Buenas Prácticas

Consejos para scripts profesionales:

  1. Usar #!/usr/bin/env bash en lugar de #!/bin/bash
  2. Configurar opciones seguras: set -euo pipefail
  3. Validar argumentos y entradas
  4. Usar variables en mayúsculas para constantes
  5. Documentar con comentarios claros
  6. Manejar errores adecuadamente
  7. Implementar logging
# Ejemplo de script bien estructurado #!/usr/bin/env bash # ================================================ # backup_sistema.sh - Script de backup profesional # Autor: Tu Nombre # Versión: 1.0 # ================================================
# Configuración set -euo pipefail IFS=$'\n\t'
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly LOG_FILE="/var/log/backup_sistema.log" readonly BACKUP_DIR="/backup"
# Funciones log() { local level="$1" local message="$2" echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" | tee -a "$LOG_FILE" }
error_handler() { log "ERROR" "Fallo en línea $LINENO" exit 1 }
trap 'error_handler' ERR
# Main main() { log "INFO" "Iniciando backup" # Código principal aquí log "INFO" "Backup completado" }
# Ejecutar solo si es llamado directamente if [[ "${BASH_SOURCE[0]}" = "${0}" ]]; then main "$@" fi

Proyecto Final: Sistema Automatizado

Crea un sistema completo de gestión automatizada:

#!/bin/bash # gestion_sistema.sh - Sistema completo de administración # ==========================================================
set -euo pipefail IFS=$'\n\t'
# Configuración readonly LOG_FILE="/var/log/gestion_sistema.log" readonly BACKUP_DIR="/backup" readonly MONITOR_DIR="/monitor"
# Colores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color
# Funciones principales backup_sistema() { local fecha=$(date +%Y%m%d_%H%M%S) echo -e "${GREEN}[+]${NC} Iniciando backup del sistema..." # Backup de configuraciones tar -czf "$BACKUP_DIR/etc_$fecha.tar.gz" /etc 2>/dev/null || true # Backup de logs importantes tar -czf "$BACKUP_DIR/logs_$fecha.tar.gz" /var/log 2>/dev/null || true echo -e "${GREEN}[+]${NC} Backup completado: $BACKUP_DIR" }
monitor_recursos() { echo -e "${YELLOW}[*]${NC} Monitoreando recursos del sistema..." # CPU local cpu_uso=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}') echo "CPU: ${cpu_uso}% usado" > "$MONITOR_DIR/recursos.txt" # Memoria local mem_libre=$(free -m | awk 'NR==2{printf "%.2f%%", $4*100/$2}') echo "Memoria libre: $mem_libre" >> "$MONITOR_DIR/recursos.txt" # Disco local disco_uso=$(df -h / | awk 'NR==2 {print $5}') echo "Disco usado: $disco_uso" >> "$MONITOR_DIR/recursos.txt" }
limpiar_sistema() { echo -e "${YELLOW}[*]${NC} Limpiando sistema..." # Limpiar caché de paquetes sudo apt autoclean -y 2>/dev/null || true sudo apt autoremove -y 2>/dev/null || true # Limpiar temporales find /tmp -type f -atime +7 -delete 2>/dev/null || true find /var/tmp -type f -atime +7 -delete 2>/dev/null || true echo -e "${GREEN}[+]${NC} Limpieza completada" }
generar_reporte() { local fecha=$(date '+%Y-%m-%d %H:%M:%S') local reporte="/tmp/reporte_sistema_$(date +%Y%m%d).txt" echo "=== REPORTE DEL SISTEMA ===" > "$reporte" echo "Fecha: $fecha" >> "$reporte" echo "Hostname: $(hostname)" >> "$reporte" echo "Usuario: $(whoami)" >> "$reporte" echo "" >> "$reporte" echo "--- Estado del Sistema ---" >> "$reporte" uptime >> "$reporte" echo "" >> "$reporte" echo "--- Espacio en Disco ---" >> "$reporte" df -h >> "$reporte" echo "" >> "$reporte" echo "--- Memoria ---" >> "$reporte" free -h >> "$reporte" echo -e "${GREEN}[+]${NC} Reporte generado: $reporte" }
# Menú principal mostrar_menu() { clear echo "========================================" echo " SISTEMA DE GESTIÓN LINUX" echo "========================================" echo "1. Backup del sistema" echo "2. Monitorear recursos" echo "3. Limpiar sistema" echo "4. Generar reporte" echo "5. Salir" echo "========================================" }
# Función principal main() { while true; do mostrar_menu read -p "Selecciona una opción [1-5]: " opcion case $opcion in 1) backup_sistema ;; 2) monitor_recursos ;; 3) limpiar_sistema ;; 4) generar_reporte ;; 5) echo -e "${GREEN}[+]${NC} Saliendo del sistema..." exit 0 ;; *) echo -e "${RED}[!]${NC} Opción no válida" sleep 2 ;; esac read -p "Presiona Enter para continuar..." done }
# Punto de entrada if [[ "${BASH_SOURCE[0]}" = "${0}" ]]; then main "$@" fi

Instrucciones para el proyecto:

  1. Guarda el código como gestion_sistema.sh
  2. Da permisos de ejecución: chmod +x gestion_sistema.sh
  3. Crea los directorios necesarios: sudo mkdir -p /backup /monitor
  4. Ejecuta: sudo ./gestion_sistema.sh
  5. Prueba todas las funcionalidades
  6. Modifica y mejora según tus necesidades

¡Felicidades!

Has completado el curso completo de Linux desde Cero. Ahora tienes las habilidades para:

  • Administrar sistemas Linux eficientemente
  • Automatizar tareas con scripts y cron
  • Configurar redes y seguridad básica
  • Crear y mantener copias de seguridad
  • Desarrollar scripts profesionales
  • Resolver problemas del sistema

Recuerda: La práctica constante es clave. Continúa experimentando, crea tus propios proyectos y únete a la comunidad de Linux para seguir aprendiendo.