Volver
Módulo 8 - Administración del Sistema AVANZADO

Monitoreo de Recursos

Implementa sistemas de monitoreo proactivo para optimizar el rendimiento del servidor

El monitoreo de recursos es fundamental para mantener sistemas estables y eficientes. Con Bash podemos crear herramientas de monitoreo personalizadas que se adapten a nuestras necesidades específicas y proporcionen alertas tempranas ante problemas potenciales.

Métricas Básicas del Sistema

Recurso Comando Descripción Umbral Típico
CPU top, vmstat, mpstat Uso de procesador < 80% sostenido
Memoria free, /proc/meminfo Uso de RAM < 85%
Disco df, du, iostat Espacio y I/O de disco < 90% espacio
Red ss, netstat, iftop Conexiones y tráfico Depende del uso
Load Average uptime, /proc/loadavg Carga del sistema < número de CPUs
Procesos ps, pstree Procesos activos Depende del sistema

Monitor Básico del Sistema

Monitor básico - system_monitor.sh
bash
#!/bin/bash

# Monitor básico del sistema
# Recopila métricas fundamentales del sistema

# Configuración
HOSTNAME=$(hostname)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Función para obtener uso de CPU
get_cpu_usage() {
    # Método 1: usando vmstat
    local cpu_idle=$(vmstat 1 2 | tail -1 | awk '{print $15}')
    local cpu_usage=$((100 - cpu_idle))
    echo "$cpu_usage"
}

# Función para obtener uso de memoria
get_memory_usage() {
    local mem_total=$(free -m | awk '/^Mem:/ {print $2}')
    local mem_used=$(free -m | awk '/^Mem:/ {print $3}')
    local mem_percent=$((mem_used * 100 / mem_total))
    
    echo "$mem_percent|$mem_used|$mem_total"
}

# Función para obtener uso de disco
get_disk_usage() {
    local disk_info=$(df -h / | tail -1)
    local disk_percent=$(echo "$disk_info" | awk '{print $5}' | sed 's/%//')
    local disk_used=$(echo "$disk_info" | awk '{print $3}')
    local disk_total=$(echo "$disk_info" | awk '{print $2}')
    
    echo "$disk_percent|$disk_used|$disk_total"
}

# Función para obtener load average
get_load_average() {
    local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
    echo "$load"
}

# Función para obtener número de procesos
get_process_count() {
    local total_processes=$(ps aux | wc -l)
    local running_processes=$(ps aux | awk '$8 ~ /^R/ {count++} END {print count+0}')
    local zombie_processes=$(ps aux | awk '$8 ~ /^Z/ {count++} END {print count+0}')
    
    echo "$total_processes|$running_processes|$zombie_processes"
}

# Función para obtener información de red
get_network_info() {
    local connections=$(ss -tun | wc -l)
    local established=$(ss -tun | grep ESTAB | wc -l)
    
    echo "$connections|$established"
}

# Función para obtener uptime
get_uptime() {
    local uptime_seconds=$(awk '{print int($1)}' /proc/uptime)
    local days=$((uptime_seconds / 86400))
    local hours=$(( (uptime_seconds % 86400) / 3600 ))
    local minutes=$(( (uptime_seconds % 3600) / 60 ))
    
    echo "${days}d ${hours}h ${minutes}m"
}

# Función para obtener temperatura (si está disponible)
get_temperature() {
    if [ -f /sys/class/thermal/thermal_zone0/temp ]; then
        local temp_millic=$(cat /sys/class/thermal/thermal_zone0/temp)
        local temp_c=$((temp_millic / 1000))
        echo "$temp_c°C"
    else
        echo "N/A"
    fi
}

# Función principal para mostrar todas las métricas
show_system_metrics() {
    clear
    echo "╔══════════════════════════════════════════════════════════════╗"
    echo "║                    MONITOR DEL SISTEMA                      ║"
    echo "╠══════════════════════════════════════════════════════════════╣"
    echo "║ Servidor: $HOSTNAME"
    echo "║ Fecha: $TIMESTAMP"
    echo "╠══════════════════════════════════════════════════════════════╣"
    
    # CPU
    local cpu_usage
    cpu_usage=$(get_cpu_usage)
    printf "║ CPU:      %3d%% " "$cpu_usage"
    if [ "$cpu_usage" -gt 80 ]; then
        echo "🔴 ALTO"
    elif [ "$cpu_usage" -gt 60 ]; then
        echo "🟡 MEDIO"
    else
        echo "🟢 NORMAL"
    fi
    
    # Memoria
    IFS='|' read -ra MEM_DATA <<< "$(get_memory_usage)"
    local mem_percent="${MEM_DATA[0]}"
    local mem_used="${MEM_DATA[1]}"
    local mem_total="${MEM_DATA[2]}"
    
    printf "║ Memoria:  %3d%% (%s/%s MB) " "$mem_percent" "$mem_used" "$mem_total"
    if [ "$mem_percent" -gt 85 ]; then
        echo "🔴 ALTO"
    elif [ "$mem_percent" -gt 70 ]; then
        echo "🟡 MEDIO"
    else
        echo "🟢 NORMAL"
    fi
    
    # Disco
    IFS='|' read -ra DISK_DATA <<< "$(get_disk_usage)"
    local disk_percent="${DISK_DATA[0]}"
    local disk_used="${DISK_DATA[1]}"
    local disk_total="${DISK_DATA[2]}"
    
    printf "║ Disco:    %3d%% (%s/%s) " "$disk_percent" "$disk_used" "$disk_total"
    if [ "$disk_percent" -gt 90 ]; then
        echo "🔴 CRÍTICO"
    elif [ "$disk_percent" -gt 75 ]; then
        echo "🟡 ADVERTENCIA"
    else
        echo "🟢 NORMAL"
    fi
    
    # Load Average
    local load_avg
    load_avg=$(get_load_average)
    echo "║ Load Avg: $load_avg"
    
    # Procesos
    IFS='|' read -ra PROC_DATA <<< "$(get_process_count)"
    local total_procs="${PROC_DATA[0]}"
    local running_procs="${PROC_DATA[1]}"
    local zombie_procs="${PROC_DATA[2]}"
    
    echo "║ Procesos: $total_procs total, $running_procs ejecutando, $zombie_procs zombie"
    
    # Red
    IFS='|' read -ra NET_DATA <<< "$(get_network_info)"
    local connections="${NET_DATA[0]}"
    local established="${NET_DATA[1]}"
    
    echo "║ Red:      $connections conexiones ($established establecidas)"
    
    # Uptime
    local uptime_str
    uptime_str=$(get_uptime)
    echo "║ Uptime:   $uptime_str"
    
    # Temperatura
    local temp
    temp=$(get_temperature)
    echo "║ Temp:     $temp"
    
    echo "╚══════════════════════════════════════════════════════════════╝"
}

# Función para modo continuo
continuous_monitoring() {
    local interval="${1:-5}"
    
    echo "Iniciando monitoreo continuo (intervalo: ${interval}s)"
    echo "Presione Ctrl+C para detener"
    
    while true; do
        show_system_metrics
        sleep "$interval"
    done
}

# Función para generar reporte JSON
generate_json_report() {
    local cpu_usage
    cpu_usage=$(get_cpu_usage)
    
    IFS='|' read -ra MEM_DATA <<< "$(get_memory_usage)"
    IFS='|' read -ra DISK_DATA <<< "$(get_disk_usage)"
    IFS='|' read -ra PROC_DATA <<< "$(get_process_count)"
    IFS='|' read -ra NET_DATA <<< "$(get_network_info)"
    
    local load_avg
    load_avg=$(get_load_average)
    local uptime_str
    uptime_str=$(get_uptime)
    local temp
    temp=$(get_temperature)
    
    cat << EOF
{
  "hostname": "$HOSTNAME",
  "timestamp": "$TIMESTAMP",
  "cpu": {
    "usage_percent": $cpu_usage
  },
  "memory": {
    "usage_percent": ${MEM_DATA[0]},
    "used_mb": ${MEM_DATA[1]},
    "total_mb": ${MEM_DATA[2]}
  },
  "disk": {
    "usage_percent": ${DISK_DATA[0]},
    "used": "${DISK_DATA[1]}",
    "total": "${DISK_DATA[2]}"
  },
  "load_average": "$load_avg",
  "processes": {
    "total": ${PROC_DATA[0]},
    "running": ${PROC_DATA[1]},
    "zombie": ${PROC_DATA[2]}
  },
  "network": {
    "connections": ${NET_DATA[0]},
    "established": ${NET_DATA[1]}
  },
  "uptime": "$uptime_str",
  "temperature": "$temp"
}
EOF
}

# Función principal
main() {
    case "${1:-show}" in
        show)
            show_system_metrics
            ;;
        watch|continuous)
            continuous_monitoring "${2:-5}"
            ;;
        json)
            generate_json_report
            ;;
        help)
            echo "Uso: $0 [show|watch|continuous|json|help] [intervalo]"
            echo ""
            echo "Comandos:"
            echo "  show       - Mostrar métricas una vez (por defecto)"
            echo "  watch      - Monitoreo continuo"
            echo "  continuous - Alias para watch"
            echo "  json       - Generar reporte en formato JSON"
            echo "  help       - Mostrar esta ayuda"
            echo ""
            echo "Ejemplos:"
            echo "  $0                    # Mostrar métricas una vez"
            echo "  $0 watch 10           # Monitoreo cada 10 segundos"
            echo "  $0 json > report.json # Exportar a JSON"
            ;;
        *)
            echo "Comando no válido: $1"
            echo "Use '$0 help' para ver opciones disponibles"
            exit 1
            ;;
    esac
}

# Ejecutar función principal
main "$@"
./system_monitor.sh
./system_monitor.sh watch 5
./system_monitor.sh json > system_metrics.json

Monitor Avanzado con Sistema de Alertas

Monitor con alertas - advanced_monitor.sh
bash
#!/bin/bash

# Monitor avanzado del sistema con alertas y logging
# Versión: 2.0

set -euo pipefail

# Configuración
declare -g CONFIG_FILE="/etc/system_monitor.conf"
declare -g LOG_FILE="/var/log/system_monitor.log"
declare -g ALERT_LOG="/var/log/system_alerts.log"
declare -g PID_FILE="/var/run/system_monitor.pid"
declare -g DATA_DIR="/var/lib/system_monitor"
declare -g ALERTS_ENABLED=true

# Umbrales por defecto
declare -g CPU_WARNING=70
declare -g CPU_CRITICAL=90
declare -g MEM_WARNING=75
declare -g MEM_CRITICAL=90
declare -g DISK_WARNING=80
declare -g DISK_CRITICAL=95
declare -g LOAD_MULTIPLIER=2

# Email/Notificaciones
declare -g ALERT_EMAIL=""
declare -g SLACK_WEBHOOK=""
declare -g ALERT_COOLDOWN=300  # 5 minutos

# Crear directorios necesarios
mkdir -p "$DATA_DIR"

# Función de logging avanzado
log() {
    local level="$1"
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local log_entry="[$timestamp] [$level] $message"
    
    echo "$log_entry" >> "$LOG_FILE"
    
    # También mostrar en stdout si no es daemon
    if [ "${DAEMON_MODE:-false}" != "true" ]; then
        echo "$log_entry" >&2
    fi
}

log_info() { log "INFO" "$@"; }
log_warn() { log "WARN" "$@"; }
log_error() { log "ERROR" "$@"; }
log_alert() { 
    log "ALERT" "$@"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ALERT: $*" >> "$ALERT_LOG"
}

# Cargar configuración
load_config() {
    if [ -f "$CONFIG_FILE" ]; then
        source "$CONFIG_FILE"
        log_info "Configuración cargada desde $CONFIG_FILE"
    else
        log_warn "Archivo de configuración no encontrado, usando valores por defecto"
    fi
}

# Función para enviar alertas por email
send_email_alert() {
    local subject="$1"
    local message="$2"
    
    if [ -n "$ALERT_EMAIL" ] && command -v mail >/dev/null 2>&1; then
        echo "$message" | mail -s "$subject" "$ALERT_EMAIL"
        log_info "Alerta enviada por email: $subject"
    fi
}

# Función para enviar alertas a Slack
send_slack_alert() {
    local message="$1"
    local color="$2"
    
    if [ -n "$SLACK_WEBHOOK" ] && command -v curl >/dev/null 2>&1; then
        local payload=$(cat << EOF
{
    "attachments": [
        {
            "color": "$color",
            "title": "Alerta del Sistema - $(hostname)",
            "text": "$message",
            "ts": $(date +%s)
        }
    ]
}
EOF
        )
        
        curl -s -X POST -H 'Content-type: application/json' \
             --data "$payload" "$SLACK_WEBHOOK" >/dev/null
        log_info "Alerta enviada a Slack"
    fi
}

# Sistema de cooldown para alertas
check_alert_cooldown() {
    local alert_type="$1"
    local cooldown_file="$DATA_DIR/cooldown_$alert_type"
    local current_time=$(date +%s)
    
    if [ -f "$cooldown_file" ]; then
        local last_alert=$(cat "$cooldown_file")
        local time_diff=$((current_time - last_alert))
        
        if [ "$time_diff" -lt "$ALERT_COOLDOWN" ]; then
            return 1  # Todavía en cooldown
        fi
    fi
    
    echo "$current_time" > "$cooldown_file"
    return 0  # OK para enviar alerta
}

# Monitor de CPU
monitor_cpu() {
    local cpu_usage
    
    # Obtener promedio de CPU en los últimos 5 segundos
    cpu_usage=$(sar -u 1 5 | tail -1 | awk '{print 100 - $8}' | cut -d. -f1)
    
    if [ "$cpu_usage" -ge "$CPU_CRITICAL" ]; then
        if check_alert_cooldown "cpu_critical"; then
            local alert_msg="CPU CRÍTICA: ${cpu_usage}% de uso"
            log_alert "$alert_msg"
            send_email_alert "CRÍTICO: Alta carga de CPU en $(hostname)" "$alert_msg"
            send_slack_alert "$alert_msg" "danger"
        fi
        echo "CRITICAL|$cpu_usage"
    elif [ "$cpu_usage" -ge "$CPU_WARNING" ]; then
        if check_alert_cooldown "cpu_warning"; then
            local alert_msg="CPU ALTA: ${cpu_usage}% de uso"
            log_alert "$alert_msg"
            send_slack_alert "$alert_msg" "warning"
        fi
        echo "WARNING|$cpu_usage"
    else
        echo "OK|$cpu_usage"
    fi
}

# Monitor de memoria
monitor_memory() {
    local mem_percent
    mem_percent=$(free | awk '/^Mem:/ {printf("%.0f", $3/$2*100)}')
    
    if [ "$mem_percent" -ge "$MEM_CRITICAL" ]; then
        if check_alert_cooldown "mem_critical"; then
            local alert_msg="MEMORIA CRÍTICA: ${mem_percent}% de uso"
            log_alert "$alert_msg"
            send_email_alert "CRÍTICO: Alta uso de memoria en $(hostname)" "$alert_msg"
            send_slack_alert "$alert_msg" "danger"
        fi
        echo "CRITICAL|$mem_percent"
    elif [ "$mem_percent" -ge "$MEM_WARNING" ]; then
        if check_alert_cooldown "mem_warning"; then
            local alert_msg="MEMORIA ALTA: ${mem_percent}% de uso"
            log_alert "$alert_msg"
            send_slack_alert "$alert_msg" "warning"
        fi
        echo "WARNING|$mem_percent"
    else
        echo "OK|$mem_percent"
    fi
}

# Monitor de disco
monitor_disk() {
    local disk_usage
    disk_usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ "$disk_usage" -ge "$DISK_CRITICAL" ]; then
        if check_alert_cooldown "disk_critical"; then
            local alert_msg="DISCO CRÍTICO: ${disk_usage}% de uso en /"
            log_alert "$alert_msg"
            send_email_alert "CRÍTICO: Poco espacio en disco en $(hostname)" "$alert_msg"
            send_slack_alert "$alert_msg" "danger"
        fi
        echo "CRITICAL|$disk_usage"
    elif [ "$disk_usage" -ge "$DISK_WARNING" ]; then
        if check_alert_cooldown "disk_warning"; then
            local alert_msg="DISCO ALTO: ${disk_usage}% de uso en /"
            log_alert "$alert_msg"
            send_slack_alert "$alert_msg" "warning"
        fi
        echo "WARNING|$disk_usage"
    else
        echo "OK|$disk_usage"
    fi
}

# Monitor de load average
monitor_load() {
    local cpu_count
    cpu_count=$(nproc)
    local load_avg
    load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
    local load_threshold=$(echo "$cpu_count * $LOAD_MULTIPLIER" | bc -l)
    
    if (( $(echo "$load_avg > $load_threshold" | bc -l) )); then
        if check_alert_cooldown "load_high"; then
            local alert_msg="CARGA ALTA: Load average $load_avg (umbral: $load_threshold)"
            log_alert "$alert_msg"
            send_slack_alert "$alert_msg" "warning"
        fi
        echo "WARNING|$load_avg"
    else
        echo "OK|$load_avg"
    fi
}

# Monitor de servicios críticos
monitor_services() {
    local services=("ssh" "nginx" "apache2" "mysql" "postgresql" "docker")
    local failed_services=()
    
    for service in "${services[@]}"; do
        if systemctl is-enabled "$service" >/dev/null 2>&1; then
            if ! systemctl is-active "$service" >/dev/null 2>&1; then
                failed_services+=("$service")
            fi
        fi
    done
    
    if [ ${#failed_services[@]} -gt 0 ]; then
        if check_alert_cooldown "services_down"; then
            local alert_msg="SERVICIOS CAÍDOS: ${failed_services[*]}"
            log_alert "$alert_msg"
            send_email_alert "CRÍTICO: Servicios caídos en $(hostname)" "$alert_msg"
            send_slack_alert "$alert_msg" "danger"
        fi
        echo "CRITICAL|${#failed_services[@]} servicios caídos"
    else
        echo "OK|Todos los servicios activos"
    fi
}

# Almacenar métricas históricas
store_metrics() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local cpu_result
    cpu_result=$(monitor_cpu)
    local mem_result
    mem_result=$(monitor_memory)
    local disk_result
    disk_result=$(monitor_disk)
    local load_result
    load_result=$(monitor_load)
    
    # Extraer valores numéricos
    local cpu_value=$(echo "$cpu_result" | cut -d'|' -f2)
    local mem_value=$(echo "$mem_result" | cut -d'|' -f2)
    local disk_value=$(echo "$disk_result" | cut -d'|' -f2)
    local load_value=$(echo "$load_result" | cut -d'|' -f2)
    
    # Guardar en CSV para análisis posterior
    echo "$timestamp,$cpu_value,$mem_value,$disk_value,$load_value" >> "$DATA_DIR/metrics.csv"
    
    # Mantener solo los últimos 7 días de datos
    if [ -f "$DATA_DIR/metrics.csv" ]; then
        tail -n 10080 "$DATA_DIR/metrics.csv" > "$DATA_DIR/metrics.csv.tmp"
        mv "$DATA_DIR/metrics.csv.tmp" "$DATA_DIR/metrics.csv"
    fi
}

# Generar reporte detallado
generate_report() {
    local report_file="${1:-/tmp/system_report_$(date +%Y%m%d_%H%M%S).html}"
    
    log_info "Generando reporte detallado: $report_file"
    
    cat > "$report_file" << 'EOF'




    Reporte del Sistema
    


EOF
    
    echo "

Reporte del Sistema - $(hostname)

" >> "$report_file" echo "

Generado el: $(date)

" >> "$report_file" echo "

Estado Actual

" >> "$report_file" # CPU local cpu_result cpu_result=$(monitor_cpu) local cpu_status=$(echo "$cpu_result" | cut -d'|' -f1) local cpu_value=$(echo "$cpu_result" | cut -d'|' -f2) echo "
" >> "$report_file" echo "CPU: ${cpu_value}% - $cpu_status" >> "$report_file" echo "
" >> "$report_file" # Memoria local mem_result mem_result=$(monitor_memory) local mem_status=$(echo "$mem_result" | cut -d'|' -f1) local mem_value=$(echo "$mem_result" | cut -d'|' -f2) echo "
" >> "$report_file" echo "Memoria: ${mem_value}% - $mem_status" >> "$report_file" echo "
" >> "$report_file" # Historial reciente si existe if [ -f "$DATA_DIR/metrics.csv" ]; then echo "

Historial Reciente (últimas 24 horas)

" >> "$report_file" echo "" >> "$report_file" echo "" >> "$report_file" tail -n 288 "$DATA_DIR/metrics.csv" | while IFS=, read -r timestamp cpu mem disk load; do echo "" >> "$report_file" done echo "
TimestampCPU %Memoria %Disco %Load
$timestamp$cpu$mem$disk$load
" >> "$report_file" fi echo "" >> "$report_file" log_info "Reporte generado: $report_file" echo "$report_file" } # Modo daemon daemon_mode() { local interval="${1:-60}" log_info "Iniciando modo daemon (intervalo: ${interval}s)" # Crear archivo PID echo $$ > "$PID_FILE" # Configurar traps para limpieza trap 'rm -f "$PID_FILE"; exit 0' EXIT INT TERM export DAEMON_MODE=true while true; do store_metrics sleep "$interval" done } # Función de ayuda show_help() { cat << EOF Monitor Avanzado del Sistema v2.0 USO: $0 [COMANDO] [OPCIONES] COMANDOS: monitor Ejecutar monitoreo una vez daemon [SECS] Ejecutar como daemon (default: 60s) report [FILE] Generar reporte HTML status Mostrar estado actual stop Detener daemon config Mostrar configuración actual EJEMPLOS: $0 monitor # Monitoreo único $0 daemon 30 # Daemon cada 30 segundos $0 report /tmp/report.html # Generar reporte $0 stop # Detener daemon ARCHIVOS: Config: $CONFIG_FILE Log: $LOG_FILE Datos: $DATA_DIR/ CONFIGURACIÓN (en $CONFIG_FILE): CPU_WARNING=70 CPU_CRITICAL=90 MEM_WARNING=75 MEM_CRITICAL=90 DISK_WARNING=80 DISK_CRITICAL=95 ALERT_EMAIL="[email protected]" SLACK_WEBHOOK="https://hooks.slack.com/..." EOF } # Función principal main() { load_config case "${1:-monitor}" in monitor) log_info "Ejecutando monitoreo único" store_metrics echo "Monitoreo completado. Ver logs en $LOG_FILE" ;; daemon) daemon_mode "${2:-60}" ;; report) generate_report "${2:-}" ;; status) echo "=== ESTADO DEL SISTEMA ===" echo "CPU: $(monitor_cpu)" echo "Memoria: $(monitor_memory)" echo "Disco: $(monitor_disk)" echo "Load: $(monitor_load)" echo "Servicios: $(monitor_services)" ;; stop) if [ -f "$PID_FILE" ]; then local pid=$(cat "$PID_FILE") kill "$pid" 2>/dev/null && echo "Daemon detenido" || echo "No se pudo detener el daemon" rm -f "$PID_FILE" else echo "Daemon no está ejecutándose" fi ;; config) echo "=== CONFIGURACIÓN ACTUAL ===" echo "CPU Warning: $CPU_WARNING%" echo "CPU Critical: $CPU_CRITICAL%" echo "Memory Warning: $MEM_WARNING%" echo "Memory Critical: $MEM_CRITICAL%" echo "Disk Warning: $DISK_WARNING%" echo "Disk Critical: $DISK_CRITICAL%" echo "Alert Email: ${ALERT_EMAIL:-'No configurado'}" echo "Slack Webhook: ${SLACK_WEBHOOK:+'Configurado'}" ;; help|--help|-h) show_help ;; *) echo "Comando no válido: $1" show_help exit 1 ;; esac } # Verificar dependencias check_dependencies() { local deps=("sar" "bc" "nproc") local missing=() for dep in "${deps[@]}"; do if ! command -v "$dep" >/dev/null 2>&1; then missing+=("$dep") fi done if [ ${#missing[@]} -gt 0 ]; then echo "Error: Dependencias faltantes: ${missing[*]}" >&2 echo "Instale: apt install sysstat bc coreutils" >&2 exit 1 fi } # Verificar dependencias y ejecutar check_dependencies main "$@"

Dashboard Web Simple

Generador de dashboard - web_dashboard.sh
bash
#!/bin/bash

# Generador de dashboard web para monitoreo del sistema
# Crea un dashboard HTML que se actualiza automáticamente

set -euo pipefail

# Configuración
DASHBOARD_DIR="/var/www/html/monitor"
DASHBOARD_FILE="$DASHBOARD_DIR/index.html"
DATA_FILE="$DASHBOARD_DIR/data.json"
UPDATE_INTERVAL=30

# Crear directorio si no existe
mkdir -p "$DASHBOARD_DIR"

# Función para obtener métricas del sistema
collect_metrics() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # CPU
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//')
    
    # Memoria
    local mem_info=$(free -m)
    local mem_total=$(echo "$mem_info" | awk '/^Mem:/ {print $2}')
    local mem_used=$(echo "$mem_info" | awk '/^Mem:/ {print $3}')
    local mem_percent=$((mem_used * 100 / mem_total))
    
    # Disco
    local disk_info=$(df -h / | tail -1)
    local disk_percent=$(echo "$disk_info" | awk '{print $5}' | sed 's/%//')
    local disk_used=$(echo "$disk_info" | awk '{print $3}')
    local disk_total=$(echo "$disk_info" | awk '{print $2}')
    
    # Load average
    local load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
    
    # Procesos
    local processes=$(ps aux | wc -l)
    
    # Red (conexiones establecidas)
    local connections=$(ss -tun | grep ESTAB | wc -l)
    
    # Uptime
    local uptime_seconds=$(awk '{print int($1)}' /proc/uptime)
    local uptime_formatted=$(printf '%dd %dh %dm' $((uptime_seconds/86400)) $((uptime_seconds%86400/3600)) $((uptime_seconds%3600/60)))
    
    # Servicios (verificar algunos servicios comunes)
    local services_status=""
    local services=("ssh" "nginx" "apache2" "mysql" "postgresql")
    for service in "${services[@]}"; do
        if systemctl is-enabled "$service" >/dev/null 2>&1; then
            if systemctl is-active "$service" >/dev/null 2>&1; then
                services_status+="\"$service\": \"active\","
            else
                services_status+="\"$service\": \"inactive\","
            fi
        fi
    done
    services_status=${services_status%,}  # Remover última coma
    
    # Generar JSON
    cat > "$DATA_FILE" << EOF
{
    "timestamp": "$timestamp",
    "hostname": "$(hostname)",
    "cpu": {
        "usage": ${cpu_usage:-0}
    },
    "memory": {
        "total": $mem_total,
        "used": $mem_used,
        "percent": $mem_percent
    },
    "disk": {
        "percent": $disk_percent,
        "used": "$disk_used",
        "total": "$disk_total"
    },
    "load_average": "$load_avg",
    "processes": $processes,
    "network": {
        "connections": $connections
    },
    "uptime": "$uptime_formatted",
    "services": {
        $services_status
    }
}
EOF
}

# Generar dashboard HTML
generate_dashboard() {
    cat > "$DASHBOARD_FILE" << 'EOF'




    
    
    Monitor del Sistema
    


    

🖥️ Monitor del Sistema

Cargando...
Procesador (CPU)
--
Cargando...
💾 Memoria RAM
--
Cargando...
💿 Almacenamiento
--
Cargando...
📊 Carga del Sistema
--
Load Average
🔄 Procesos
--
Procesos activos
🌐 Conexiones de Red
--
Conexiones establecidas
Tiempo Activo
--
Uptime del sistema
🔧 Estado de Servicios
Cargando...
EOF } # Función principal para iniciar el dashboard start_dashboard() { echo "Generando dashboard web en $DASHBOARD_DIR" # Generar dashboard HTML generate_dashboard # Generar datos iniciales collect_metrics echo "Dashboard generado exitosamente!" echo "Archivo HTML: $DASHBOARD_FILE" echo "Datos JSON: $DATA_FILE" echo "" echo "Para servir el dashboard:" echo "1. Con Python: cd $DASHBOARD_DIR && python3 -m http.server 8080" echo "2. Con Node.js: cd $DASHBOARD_DIR && npx http-server -p 8080" echo "3. Con nginx: configure el directorio raíz a $DASHBOARD_DIR" echo "" echo "Luego accede a http://localhost:8080" } # Función para actualizar datos en bucle update_loop() { echo "Iniciando bucle de actualización de datos (cada ${UPDATE_INTERVAL}s)" echo "Presiona Ctrl+C para detener" while true; do collect_metrics echo "Datos actualizados: $(date)" sleep "$UPDATE_INTERVAL" done } # Función principal main() { case "${1:-start}" in start|generate) start_dashboard ;; update) collect_metrics echo "Datos actualizados" ;; loop|daemon) if [ ! -f "$DASHBOARD_FILE" ]; then start_dashboard fi update_loop ;; serve) if [ ! -f "$DASHBOARD_FILE" ]; then start_dashboard fi echo "Iniciando servidor web en puerto 8080..." cd "$DASHBOARD_DIR" if command -v python3 >/dev/null 2>&1; then python3 -m http.server 8080 elif command -v python >/dev/null 2>&1; then python -m SimpleHTTPServer 8080 elif command -v node >/dev/null 2>&1; then npx http-server -p 8080 else echo "No se encontró Python o Node.js para servir el dashboard" echo "Instale uno de estos o use nginx/apache" exit 1 fi ;; help) echo "Uso: $0 [start|update|loop|serve|help]" echo "" echo "Comandos:" echo " start - Generar dashboard inicial" echo " update - Actualizar datos una vez" echo " loop - Actualizar datos continuamente" echo " serve - Generar y servir dashboard web" echo " help - Mostrar esta ayuda" ;; *) echo "Comando no válido: $1" echo "Use '$0 help' para ver opciones disponibles" exit 1 ;; esac } # Verificar permisos para crear directorios if [ ! -w "$(dirname "$DASHBOARD_DIR")" ]; then echo "Advertencia: No se puede escribir en $(dirname "$DASHBOARD_DIR")" echo "Usando directorio temporal..." DASHBOARD_DIR="/tmp/system_monitor_dashboard" DASHBOARD_FILE="$DASHBOARD_DIR/index.html" DATA_FILE="$DASHBOARD_DIR/data.json" mkdir -p "$DASHBOARD_DIR" fi # Ejecutar función principal main "$@"
sudo ./web_dashboard.sh serve

Mejores Prácticas de Monitoreo

  • Establece umbrales realistas: Basados en el comportamiento normal de tu sistema
  • Implementa cooldown: Evita spam de alertas para el mismo problema
  • Monitoreo proactivo: Detecta tendencias antes de que se conviertan en problemas
  • Múltiples canales de alerta: Email, Slack, SMS para diferentes niveles de criticidad
  • Historiales: Mantén datos históricos para análisis de tendencias
  • Automatización: Automatiza respuestas a problemas comunes

Consideraciones Importantes

  • Impacto en el rendimiento: El monitoreo no debe afectar significativamente el sistema
  • Almacenamiento de logs: Implementa rotación para evitar llenar el disco
  • Seguridad: Protege dashboards y datos de monitoreo con autenticación
  • Falsos positivos: Ajusta umbrales para minimizar alertas innecesarias
  • Dependencias: Asegúrate de que el sistema de monitoreo sea robusto

Ejercicios Prácticos

Ejercicio 1: Sistema de Monitoreo Distribuido

Desarrolla un sistema para monitorear múltiples servidores:

  • Script maestro que recopile métricas de múltiples servidores
  • Dashboard centralizado con vista de todos los sistemas
  • Sistema de alertas que identifique qué servidor tiene problemas
  • Capacidad de ejecutar comandos remotos para diagnóstico

Ejercicio 2: Monitoreo Predictivo

Crea un sistema de monitoreo con capacidades predictivas:

  • Análisis de tendencias basado en datos históricos
  • Predicción de cuándo se agotará el espacio en disco
  • Alertas tempranas basadas en patrones de uso
  • Recomendaciones automáticas para optimización