¿Qué son las Funciones?
Las funciones en Bash son bloques de código reutilizable que encapsulan una tarea específica. Permiten organizar el código en unidades lógicas, evitar la repetición y crear scripts más mantenibles y legibles.
Una función es como una mini-programa dentro de tu script que puede recibir parámetros, procesar información y devolver resultados. Una vez definida, puedes llamarla tantas veces como necesites.
Reutilización
Escribe una vez, usa muchas veces. Las funciones eliminan la duplicación de código.
Modularidad
Divide problemas complejos en partes más pequeñas y manejables.
Mantenimiento
Cambios en una función se reflejan automáticamente en todos los lugares donde se usa.
Legibilidad
El código se vuelve más fácil de leer y entender cuando está bien organizado.
Sintaxis de Declaración
Bash ofrece dos sintaxis principales para declarar funciones. Ambas son equivalentes en funcionalidad:
Sintaxis de Funciones
Sintaxis Tradicional
nombre_funcion() {
# código de la función
echo "Hola desde la función"
return 0 # opcional
}
Sintaxis con Palabra Clave
function nombre_funcion {
# código de la función
echo "Hola desde la función"
return 0 # opcional
}
Recomendación
Usa la sintaxis tradicional con paréntesis nombre_funcion() { } ya que es más portable y ampliamente reconocida en la comunidad Bash.
Anatomía de una Función
Componentes de una Función
#!/bin/bash
# Función que saluda con información del sistema
saludar_sistema() { # ← 1. Nombre de función
echo "¡Hola desde el sistema!" # ← 4. Cuerpo de la función
echo "Usuario actual: $(whoami)"
echo "Fecha: $(date)"
echo "Directorio: $(pwd)"
return 0 # ← 5. Código de retorno
} # ← 3. Llave de cierre
Llamada de Funciones
Para usar una función, simplemente escribe su nombre. La función debe estar definida antes de ser llamada.
#!/bin/bash
# 1. Definir la función
mostrar_menu() {
echo "================================"
echo " MENÚ PRINCIPAL"
echo "================================"
echo "1. Ver archivos"
echo "2. Ver procesos"
echo "3. Ver información del sistema"
echo "4. Salir"
echo "================================"
}
# 2. Llamar la función
echo "Bienvenido al sistema"
mostrar_menu
echo ""
echo "Función llamada exitosamente"
$ ./mi_script.sh
Bienvenido al sistema
================================
MENÚ PRINCIPAL
================================
1. Ver archivos
2. Ver procesos
3. Ver información del sistema
4. Salir
================================
Función llamada exitosamente
Valores de Retorno
Las funciones en Bash pueden devolver un código de estado (0-255) usando return. También pueden "devolver" datos imprimiendo al stdout, que luego puedes capturar.
1. Códigos de Retorno
#!/bin/bash
# Función que verifica si un archivo existe
verificar_archivo() {
local archivo="$1"
if [ -f "$archivo" ]; then
echo "El archivo $archivo existe"
return 0 # Éxito
else
echo "El archivo $archivo NO existe"
return 1 # Error
fi
}
# Usar la función y verificar el resultado
verificar_archivo "/etc/passwd"
if [ $? -eq 0 ]; then
echo "✓ Verificación exitosa"
else
echo "✗ Error en la verificación"
fi
echo ""
verificar_archivo "/archivo/inexistente.txt"
if [ $? -eq 0 ]; then
echo "✓ Verificación exitosa"
else
echo "✗ Error en la verificación"
fi
2. Devolver Datos via Stdout
#!/bin/bash
# Función que calcula el cuadrado de un número
calcular_cuadrado() {
local numero=$1
local resultado=$((numero * numero))
echo $resultado # "Devolver" el resultado
}
# Función que obtiene información del sistema
obtener_info_sistema() {
echo "$(uname -s)|$(whoami)|$(date +%Y-%m-%d)"
}
# Capturar los resultados
echo "Calculando cuadrados:"
cuadrado_5=$(calcular_cuadrado 5)
cuadrado_12=$(calcular_cuadrado 12)
echo "5² = $cuadrado_5"
echo "12² = $cuadrado_12"
echo ""
echo "Información del sistema:"
info=$(obtener_info_sistema)
IFS='|' read -r sistema usuario fecha <<< "$info"
echo "Sistema: $sistema"
echo "Usuario: $usuario"
echo "Fecha: $fecha"
$ ./calcular.sh
Calculando cuadrados:
5² = 25
12² = 144
Información del sistema:
Sistema: Linux
Usuario: usuario
Fecha: 2024-01-15
Importante sobre Return
El comando return solo puede devolver números entre 0 y 255. Para devolver texto o datos complejos, usa echo y captura la salida con $().
Ejemplos Prácticos
Utilidades de Archivos
#!/bin/bash
# Función para crear backup de un archivo
crear_backup() {
local archivo="$1"
local fecha=$(date +%Y%m%d_%H%M%S)
local backup="${archivo}.backup_${fecha}"
if [ -f "$archivo" ]; then
cp "$archivo" "$backup"
echo "Backup creado: $backup"
return 0
else
echo "Error: Archivo $archivo no existe"
return 1
fi
}
# Función para obtener el tamaño de un archivo en formato legible
obtener_tamaño() {
local archivo="$1"
if [ -f "$archivo" ]; then
if command -v du &> /dev/null; then
du -h "$archivo" | cut -f1
else
ls -lh "$archivo" | awk '{print $5}'
fi
else
echo "N/A"
fi
}
# Función para limpiar archivos temporales
limpiar_temporales() {
local directorio="${1:-.}"
local archivos_eliminados=0
for archivo in "$directorio"/*.tmp "$directorio"/*.temp
do
if [ -f "$archivo" ]; then
rm "$archivo"
echo "Eliminado: $(basename $archivo)"
((archivos_eliminados++))
fi
done
echo "Total archivos eliminados: $archivos_eliminados"
return 0
}
# Ejemplo de uso
echo "=== Utilidades de Archivos ==="
crear_backup "/etc/hosts"
echo "Tamaño de /etc/passwd: $(obtener_tamaño /etc/passwd)"
limpiar_temporales /tmp
Utilidades de Sistema
#!/bin/bash
# Función para verificar si un servicio está corriendo
verificar_servicio() {
local servicio="$1"
if systemctl is-active --quiet "$servicio"; then
echo "✓ $servicio está corriendo"
return 0
else
echo "✗ $servicio no está corriendo"
return 1
fi
}
# Función para obtener uso de memoria
obtener_memoria() {
local tipo="${1:-porcentaje}"
case $tipo in
"porcentaje")
free | grep Mem | awk '{printf("%.1f%%\n", ($3/$2)*100)}'
;;
"usado")
free -h | grep Mem | awk '{print $3}'
;;
"total")
free -h | grep Mem | awk '{print $2}'
;;
*)
echo "Opciones: porcentaje, usado, total"
return 1
;;
esac
}
# Función para verificar espacio en disco
verificar_espacio() {
local punto_montaje="${1:-/}"
local umbral="${2:-90}"
local uso=$(df "$punto_montaje" | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$uso" -gt "$umbral" ]; then
echo "⚠️ ALERTA: Espacio en disco al $uso% en $punto_montaje"
return 1
else
echo "✓ Espacio en disco OK: $uso% en $punto_montaje"
return 0
fi
}
# Ejemplo de uso
echo "=== Monitor de Sistema ==="
verificar_servicio "ssh"
echo "Memoria usada: $(obtener_memoria usado) de $(obtener_memoria total)"
echo "Uso de memoria: $(obtener_memoria porcentaje)"
verificar_espacio "/" 80
Ejercicios Prácticos
Ejercicio 1: Calculadora de Funciones
Crea un conjunto de funciones matemáticas básicas:
#!/bin/bash
# Calculadora básica con funciones
# Función para sumar
sumar() {
local a=$1
local b=$2
echo $((a + b))
}
# Función para restar
restar() {
local a=$1
local b=$2
echo $((a - b))
}
# Función para multiplicar
multiplicar() {
local a=$1
local b=$2
echo $((a * b))
}
# Función para dividir
dividir() {
local a=$1
local b=$2
if [ "$b" -eq 0 ]; then
echo "Error: División por cero"
return 1
fi
# Usar bc para división con decimales si está disponible
if command -v bc &> /dev/null; then
echo "scale=2; $a / $b" | bc
else
echo $((a / b))
fi
}
# Función para calcular potencia
potencia() {
local base=$1
local exponente=$2
local resultado=1
for ((i=1; i<=exponente; i++)); do
resultado=$((resultado * base))
done
echo $resultado
}
# Función principal del menú
mostrar_menu() {
echo "================================="
echo " CALCULADORA BASH"
echo "================================="
echo "1. Sumar"
echo "2. Restar"
echo "3. Multiplicar"
echo "4. Dividir"
echo "5. Potencia"
echo "6. Salir"
echo "================================="
}
# Programa principal
while true; do
mostrar_menu
read -p "Selecciona una opción: " opcion
case $opcion in
1|2|3|4|5)
read -p "Ingresa el primer número: " num1
read -p "Ingresa el segundo número: " num2
case $opcion in
1) echo "Resultado: $(sumar $num1 $num2)" ;;
2) echo "Resultado: $(restar $num1 $num2)" ;;
3) echo "Resultado: $(multiplicar $num1 $num2)" ;;
4) dividir $num1 $num2 ;;
5) echo "Resultado: $(potencia $num1 $num2)" ;;
esac
;;
6)
echo "¡Hasta luego!"
exit 0
;;
*)
echo "Opción no válida"
;;
esac
echo ""
read -p "Presiona Enter para continuar..."
clear
done
Ejercicio 2: Gestor de Logs
Crea un sistema de funciones para manejar archivos de log:
#!/bin/bash
# Gestor de logs con funciones
LOG_DIR="/var/log"
LOG_FILE="aplicacion.log"
# Función para escribir entrada de log
escribir_log() {
local nivel="$1"
local mensaje="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$nivel] $mensaje" >> "$LOG_FILE"
}
# Funciones específicas para cada nivel
log_info() {
escribir_log "INFO" "$1"
echo "ℹ️ INFO: $1"
}
log_warning() {
escribir_log "WARNING" "$1"
echo "⚠️ WARNING: $1"
}
log_error() {
escribir_log "ERROR" "$1"
echo "❌ ERROR: $1"
}
log_debug() {
escribir_log "DEBUG" "$1"
echo "🐛 DEBUG: $1"
}
# Función para rotar logs
rotar_logs() {
if [ -f "$LOG_FILE" ]; then
local backup="${LOG_FILE}.$(date +%Y%m%d_%H%M%S)"
mv "$LOG_FILE" "$backup"
echo "Log rotado a: $backup"
touch "$LOG_FILE"
else
echo "No hay archivo de log para rotar"
fi
}
# Función para leer últimas entradas
leer_ultimos_logs() {
local cantidad="${1:-10}"
if [ -f "$LOG_FILE" ]; then
echo "Últimas $cantidad entradas del log:"
echo "=================================="
tail -n "$cantidad" "$LOG_FILE"
else
echo "No existe el archivo de log: $LOG_FILE"
fi
}
# Función para buscar en logs
buscar_en_logs() {
local patron="$1"
if [ -f "$LOG_FILE" ]; then
echo "Buscando '$patron' en los logs:"
echo "================================"
grep -n "$patron" "$LOG_FILE"
else
echo "No existe el archivo de log: $LOG_FILE"
fi
}
# Función para estadísticas de logs
estadisticas_logs() {
if [ -f "$LOG_FILE" ]; then
echo "Estadísticas del log:"
echo "===================="
echo "Total de líneas: $(wc -l < "$LOG_FILE")"
echo "Entradas INFO: $(grep -c "INFO" "$LOG_FILE")"
echo "Entradas WARNING: $(grep -c "WARNING" "$LOG_FILE")"
echo "Entradas ERROR: $(grep -c "ERROR" "$LOG_FILE")"
echo "Entradas DEBUG: $(grep -c "DEBUG" "$LOG_FILE")"
else
echo "No existe el archivo de log: $LOG_FILE"
fi
}
# Ejemplos de uso
echo "=== Gestor de Logs ==="
# Escribir algunos logs de ejemplo
log_info "Aplicación iniciada"
log_info "Conectando a la base de datos"
log_warning "Conexión lenta detectada"
log_error "Error al conectar con el servidor"
log_debug "Variable DEBUG_MODE=true"
echo ""
estadisticas_logs
echo ""
leer_ultimos_logs 3