Generar un informe completo del sistema (Hardware + Drivers + Errores) en un script

¿Te fue útil?

Conoces el momento. Son las 02:13, una base de datos está “lenta” y la única evidencia que hay es una captura de pantalla de top
más un recuerdo vago de que “ayer iba bien”. El proveedor quiere “un informe completo del sistema”, tu jefe quiere una línea de tiempo,
y tú quieres dormir. La decisión correcta es hacer que la máquina cuente su historia en una única instantánea reproducible.

Aquí verás cómo construir un único script que recopile hardware, drivers, estado del almacenamiento, mensajes del kernel y los errores que
realmente importan—sin dejar inservible el host, sin filtrar secretos y sin producir un blob ilegible de 80MB que nadie abre.

Cómo es un buen informe completo del sistema

Un informe completo del sistema no es un trofeo. Es una herramienta. Si no puede responder rápidamente “¿qué cambió?” y “¿qué está fallando?”,
es simplemente uso de disco con pasos extra.

Aquí está el estándar que uso en producción:

  • Un comando para ejecutar. Sin solicitudes interactivas. Nada de “instala esto” a las 3 a.m.
  • Legibilidad primero. Archivos de texto agrupados por tema. Una persona debe poder hojearlos.
  • Amigable para diff de máquina. Formato estable para poder comparar hoy vs la semana pasada.
  • Riesgo mínimo. Sin benchmarks por defecto. Sin herramientas de firmware invasivas. Sin heroísmos de “re-escanear el bus”.
  • Con conciencia de secretos. Capturar lo necesario para depurar; evitar volcar tokens, datos de clientes y claves privadas.
  • Crédible en almacenamiento. Si la máquina tiene ZFS, mdraid, LVM, multipath, NVMe—recopilar su salud correctamente.
  • Enfocado en errores. Recopilar errores del kernel y del journal con contexto. No solo “aquí están todos los logs desde 2019”.

Además: comprímelo. Nómbralo sensatamente. Incluye un manifiesto. Si alguna vez intentaste enviar por correo a un proveedor “unos archivos que copié de /var/log”
ya sabes por qué.

Hechos y breve historia: por qué esto es así

Un poco de contexto mejora la herramienta. Estos detalles explican por qué la recopilación en Linux parece un gabinete lleno de llaves de formas extrañas.

  1. /proc y /sys existen porque el kernel necesitaba una API tipo “sistema de archivos” para introspección. No es un disco; es una vista del estado del kernel.
  2. lspci viene de utilidades PCI que preceden a mucha observabilidad “moderna”. Sigue siendo la forma más rápida de mapear dispositivos a drivers.
  3. dmesg es el registro en buffer circular clásico. Es ruidoso, pero es donde fallos de hardware y drivers suelen confesarse primero.
  4. El journal de systemd fue diseñado para arreglar la fragmentación de logs. Centraliza logs, añade metadatos y hace “muéstrame arranques” una consulta de primera clase.
  5. SMART precede a NVMe. El “SMART log” de NVMe es similar en espíritu pero no idéntico; mezclar interpretaciones causa malas decisiones.
  6. mdraid ha sobrevivido porque es aburrido y bueno. Está en el kernel, es estable y entendido—todavía un valor por defecto en muchas empresas.
  7. Nombres de dispositivos como /dev/sda nunca estuvieron pensados como identificadores estables. Por eso existen /dev/disk/by-id y reglas de udev.
  8. Multipath existe porque los SANs mienten por omisión. Si no verificas la salud de las rutas, creerás que “redundante” significa “seguro”.
  9. La topología moderna de CPU es complicada porque el rendimiento es complicado. NUMA, SMT y la gestión de energía pueden hacer que “mismo modelo de CPU” se comporte distinto.

Chiste #1: Los logs son como escenas del crimen—todos dicen que “no tocaron nada”, y luego encuentras huellas recientes por todo /etc.

Principios de diseño: seguro, comparable, soportable

1) Preferir inspección “solo lectura” sobre sondeo activo

Puedes obtener el 90% del valor con inspección: lsblk, lspci, modinfo, journalctl, lecturas SMART.
El sondeo activo (pruebas de estrés, rescans, actualizaciones de firmware) puede cambiar el sistema o amplificar una falla. No lo hagas en la ruta por defecto.

2) Capturar identidad y contexto primero

Antes de recopilar cualquier otra cosa, captura:

  • hostname, versión del SO, versión del kernel, uptime
  • estado de sincronización horaria
  • pistas de virtualización/contenedor
  • historial de arranques y razón del último reinicio (cuando esté disponible)

La razón es simple: muchos “errores” son solo saltos en el tiempo, arranques parciales o desajustes de kernel. El contexto evita que diagnostiques fantasmas.

3) Hacer la salida lo suficientemente estable para diff

A la gente le gusta “lo más reciente primero”. A las herramientas diff les gusta la estabilidad. Puedes tener ambos escribiendo archivos con nombres deterministas y formatos estables,
y separando “estado actual” de “eventos recientes”. Por ejemplo: guarda la salida de lsblk y también guarda
“errores del journal desde el arranque”.

4) Evitar recopilar secretos por accidente

No recojas:

  • /etc/shadow, claves privadas SSH, tokens de metadatos cloud
  • configuraciones de aplicaciones con credenciales (URLs de BD, claves API)
  • volcados completos del entorno desde listados de procesos

En su lugar, recopila fragmentos de configuración saneados (versiones de paquetes, estado de servicios, archivos unit) y logs con ventanas temporales acotadas.
Un bundle de soporte debe ser seguro para compartir con tu propio equipo de seguridad sin un largo correo de disculpa.

5) Ser explícito sobre permisos

Muchos comandos útiles requieren root: lecturas SMART, acceso al journal, algunas herramientas de almacenamiento. Tu script debe:

  • ejecutarse como root (recomendado) o degradarse con gracia
  • registrar qué comandos fallaron por permisos
  • nunca usar “sudo” dentro del script (demasiados entornos lo prohíben)

6) Capturar errores con evidencia circundante

Trazas de pila del kernel, mensajes de reinicio NVMe, errores ext4, timeouts mpt3sas—estas son las migas de pan.
Cuando extraigas errores, incluye unas líneas de contexto e incluye el boot ID / timestamp. Si no, pegarás
una línea aterradora en el chat y empezarás un pánico innecesario.

Guía rápida de diagnóstico (primero/segundo/tercero)

Cuando alguien dice “el servidor está lento”, quiere decir “mi petición está lenta”. Eso puede ser CPU, almacenamiento, presión de memoria, red,
o un driver que está enviando reinicios. Empieza con las comprobaciones que descartan clases enteras de problemas.

Primero: confirmar lo básico (10 segundos)

  • ¿El reloj está sano? Saltos de tiempo vuelven inútiles los logs y pueden romper TLS, clustering y caches.
  • ¿La máquina está reiniciando o haciendo flapping? Uptime y logs de arranque indican si estás persiguiendo un objetivo que se mueve.
  • ¿Hay una tormenta en dmesg? Si el kernel está gritando, escucha antes de tunear nada.

Segundo: identificar el dominio del cuello de botella (1 minuto)

  • ¿Saturación de CPU? Alta carga con alto user/sys, o cola de ejecución acumulándose.
  • ¿Presión de memoria? Actividad de swap, kills por OOM, estancamientos de reclaim.
  • ¿Espera de I/O? iowait elevado, tareas bloqueadas, latencia de disco.
  • ¿Red? Pérdidas, retransmisiones, reinicios del driver NIC.

Tercero: mapear síntomas a la capa física/driver (5 minutos)

  • ¿Qué dispositivo es lento? ¿Qué controlador? ¿Qué driver?
  • ¿Los errores coinciden con una versión de firmware o módulo?
  • ¿Estás en un pool RAID/ZFS degradado?
  • ¿Un “pequeño” update del kernel cambió la pila de almacenamiento?

Un flujo de trabajo fiable es: logs → topología → salud → deriva de configuración. Lo contrario (“tunear sysctl primero”) es como
pulir el capó mientras el motor está en llamas.

12+ tareas prácticas: comandos, significado, decisión

Estas son las tareas específicas que espero que cubra un “informe completo del sistema”. Cada una incluye: un comando, qué indica su salida,
y qué decisión puedes tomar a partir de ello. Úsalas de forma interactiva y también incorpóralas al bundle de un solo script más abajo.

Task 1: Identificar OS + kernel + modo de arranque

cr0x@server:~$ uname -a
Linux server 6.5.0-21-generic #21~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC x86_64 x86_64 x86_64 GNU/Linux

Significado: La versión y la variante del kernel importan para el comportamiento de drivers (especialmente almacenamiento y NIC).

Decisión: Si este kernel cambió recientemente, trata la “regresión de rendimiento” como “incompatibilidad driver/firmware hasta que se demuestre lo contrario.”

cr0x@server:~$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"

Significado: La política de actualizaciones de paquetes y kernel se deduce por la distribución y la versión.

Decisión: El soporte del proveedor a menudo depende de la versión menor de la distro; no lo minimices.

cr0x@server:~$ test -d /sys/firmware/efi && echo UEFI || echo BIOS
UEFI

Significado: El modo de arranque influye en el particionado, el comportamiento del bootloader y a veces en herramientas de firmware.

Decisión: En flotas: estandariza el modo de arranque; mezclar UEFI/BIOS complica la automatización y la recuperación.

Task 2: Confirmar uptime y logs del último arranque

cr0x@server:~$ uptime -p
up 17 days, 3 hours, 12 minutes

Significado: Uptime largos esconden degradación lenta; uptime corto significa que tu ventana de evidencia es pequeña.

Decisión: Si el uptime es sospechosamente corto, prioriza “por qué se reinició” sobre “por qué está lento”.

cr0x@server:~$ journalctl -b -1 -n 30 --no-pager
Feb 05 01:02:11 server kernel: Linux version 6.5.0-21-generic (buildd@lcy02-amd64-039) ...
Feb 05 01:02:19 server systemd[1]: Started Journal Service.
Feb 05 01:02:26 server kernel: nvme nvme0: controller is down; will reset: CSTS=0x1, PCI_STATUS=0x10
Feb 05 01:02:28 server kernel: nvme nvme0: reset controller

Significado: Los mensajes del arranque previo a menudo muestran la primera aparición del problema (como reinicios de almacenamiento).

Decisión: Si arranques previos muestran reinicios de dispositivo, deja de culpar a la aplicación y valida la salud del almacenamiento/PCIe.

Task 3: Instantánea rápida de CPU y presión de memoria

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 512340  92112 4213900   0    0    12    44  320  510  6  2 90  2  0
 5  1      0 120480  93200 4061012   0    0   180   920 1250 2100 14  6 60 20  0

Significado: r cola de ejecución, b tareas bloqueadas, swap in/out, y wa iowait.

Decisión: Alto wa y tareas bloqueadas significan latencia de almacenamiento; no “añadas CPU” para arreglar un problema de disco.

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           31Gi        12Gi       490Mi       1.2Gi        18Gi        17Gi
Swap:           0B          0B          0B

Significado: “free” no es toda la historia; “available” importa.

Decisión: Si available es bajo y la latencia es alta, revisa reclaim/I/O; si hay swap y está activo, espera picos de latencia en cola.

Task 4: Encontrar errores del kernel rápidamente

cr0x@server:~$ dmesg -T --level=err,warn | tail -n 20
[Mon Feb  5 03:11:22 2026] nvme nvme0: I/O 129 QID 7 timeout, aborting
[Mon Feb  5 03:11:22 2026] nvme nvme0: Abort status: 0x0
[Mon Feb  5 03:11:23 2026] nvme nvme0: controller is down; will reset: CSTS=0x3, PCI_STATUS=0x10
[Mon Feb  5 03:11:25 2026] EXT4-fs warning (device dm-0): ext4_end_bio:344: I/O error 10 writing to inode 262402 starting block 8392704

Significado: Esto es el kernel diciéndote la verdad: timeouts, reinicios, consecuencias en el sistema de ficheros.

Decisión: Si ves reinicios/timeouts, pausa el tuning de rendimiento. Recopila versiones de firmware, estado del enlace PCIe y salud del almacenamiento a continuación.

Task 5: Mapear dispositivos PCI a drivers

cr0x@server:~$ lspci -nnk | sed -n '1,80p'
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3e30] (rev 0a)
03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
        Subsystem: Samsung Electronics Co Ltd Device [144d:a801]
        Kernel driver in use: nvme
        Kernel modules: nvme
05:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ [8086:1572]
        Kernel driver in use: i40e
        Kernel modules: i40e

Significado: “Qué dispositivo, qué driver.” Así conectas un timeout en dmesg con un controlador y un módulo específico.

Decisión: Si el driver es inesperado (driver de fallback, o módulo fuera del árbol), tienes un riesgo de soporte y estabilidad.

Task 6: Confirmar módulos cargados y versiones

cr0x@server:~$ lsmod | head
Module                  Size  Used by
nvme                   61440  2
nvme_core             212992  4 nvme
i40e                  557056  0
xfs                  1703936  1

Significado: Los módulos cargados muestran lo que realmente está ejecutándose, no lo que crees que está instalado.

Decisión: Si los módulos de almacenamiento/NIC faltan dependencias esperadas o muestran conteos “Used by” inusuales, sospecha churn de drivers o actualizaciones parciales.

cr0x@server:~$ modinfo i40e | sed -n '1,15p'
filename:       /lib/modules/6.5.0-21-generic/kernel/drivers/net/ethernet/intel/i40e/i40e.ko
version:        2.24.0-k
license:        GPL
description:    Intel(R) Ethernet Connection XL710 Network Driver
firmware:       i40e/ddp/i40e-1.3.34.0.pkg

Significado: La versión del driver y las expectativas sobre paquetes de firmware están aquí.

Decisión: Si el driver espera un paquete de firmware que no está presente, puedes tener funciones degradadas o comportamiento de enlace extraño.

Task 7: Inventario de discos, sistemas de archivos y opciones de montaje

cr0x@server:~$ lsblk -e7 -o NAME,TYPE,SIZE,MODEL,SERIAL,ROTA,TRAN,HCTL,FSTYPE,MOUNTPOINTS
NAME        TYPE   SIZE MODEL              SERIAL        ROTA TRAN HCTL       FSTYPE MOUNTPOINTS
nvme0n1     disk  1.8T  Samsung SSD 980    S6X...           0 nvme -          -      -
nvme0n1p1   part   512M -                  -                0 nvme -          vfat   /boot/efi
nvme0n1p2   part   1.8T -                  -                0 nvme -          LVM2_member
dm-0        lvm   1.8T  -                  -                0 -    -          ext4   /

Significado: Esto mapea dispositivos físicos a capas lógicas (particiones → LVM → sistema de archivos).

Decisión: Si ves apilamientos inesperados (p. ej., mdraid sobre dm-crypt sobre LVM), el rendimiento y la recuperación se complican. Documenta la pila.

cr0x@server:~$ findmnt -Dno TARGET,SOURCE,FSTYPE,OPTIONS | sed -n '1,20p'
/ /dev/mapper/vg0-root ext4 rw,relatime,errors=remount-ro
/boot/efi /dev/nvme0n1p1 vfat rw,relatime,fmask=0077,dmask=0077

Significado: Las opciones de montaje importan: barriers, atime, discard, manejo de errores.

Decisión: Si sistemas de archivos críticos montan con opciones riesgosas (como desactivar características de journaling o barriers), trátalo como una interrupción esperando cortesía.

Task 8: Comprobar salud NVMe (si está presente)

cr0x@server:~$ nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev
/dev/nvme0n1     S6X...               Samsung SSD 980 PRO 2TB                  1          1.80  TB /   2.00  TB    512   B +  0 B   5B2QGXA7

Significado: La revisión de firmware no es trivia; a menudo es la diferencia entre “estable” y “reinicios misteriosos.”

Decisión: Si la FW Rev es conocida como mala en tu entorno, programa una actualización controlada, no un parche de emergencia en producción.

cr0x@server:~$ nvme smart-log /dev/nvme0n1 | sed -n '1,25p'
Smart Log for NVME device:nvme0n1 namespace-id:ffffffff
critical_warning                    : 0x00
temperature                         : 44 C
available_spare                     : 100%
percentage_used                     : 3%
data_units_read                     : 12,345,678
data_units_written                  : 9,876,543
media_errors                        : 0
num_err_log_entries                 : 18

Significado: critical_warning, media_errors y entradas en el log de errores son tus señales tempranas.

Decisión: Si las entradas de error aumentan y ves timeouts en el kernel, sospecha del dispositivo, del enlace PCIe o de la interacción controlador/firmware.

Task 9: Comprobar SMART clásico (SATA/SAS)

cr0x@server:~$ smartctl -a /dev/sda | sed -n '1,40p'
smartctl 7.2 2020-12-30 r5155 [x86_64-linux-6.5.0-21-generic] (local build)
Device Model:     ST12000NM0007
Serial Number:    ZRT0...
Firmware Version: SN02
SMART overall-health self-assessment test result: PASSED

Significado: “PASSED” no es un chequeo limpio; aún necesitas tendencias de atributos y logs de errores.

Decisión: Si existen sectores realocados/pendientes o los errores aumentan, reemplaza de manera proactiva. Los discos no se curan; se vuelven poéticos.

Task 10: Estado RAID/ZFS (según aplique)

cr0x@server:~$ cat /proc/mdstat
Personalities : [raid1] [raid10] [raid6] [raid5] [raid4]
md0 : active raid1 sdb1[0] sdc1[1]
      976630336 blocks super 1.2 [2/2] [UU]

Significado: [UU] significa que todos los miembros están arriba. Cualquier otra cosa está degradada, y arreglos degradados se vuelven lentos.

Decisión: Si está degradado, deja de investigar “rendimiento” y empieza a investigar “protección de datos”. Luego reconstruye con seguridad.

cr0x@server:~$ zpool status
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:12:31 with 0 errors on Sun Feb  4 02:00:01 2026
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0

errors: No known data errors

Significado: ZFS te dice si la redundancia está intacta y si los scrubs están encontrando corrupción.

Decisión: Si los scrubs muestran errores o DEGRADED, trata la capa de hardware como sospechosa hasta ser exonerada.

Task 11: Sanidad LVM y device-mapper

cr0x@server:~$ pvs
PV         VG  Fmt  Attr PSize  PFree
/dev/nvme0n1p2 vg0 lvm2 a--  1.81t    0

Significado: El mapeo PV/VG/LV detecta sorpresas de “alguien redimensionó algo”.

Decisión: Si ves PVs faltantes o VGs parciales, detente. Podrías estar corriendo sobre una pila degradada o mal ensamblada.

cr0x@server:~$ lvs -a -o +devices
LV   VG  Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert Devices
root vg0 -wi-ao---- 1.81t                                                     /dev/nvme0n1p2(0)

Significado: Muestra qué dispositivos subyacentes soportan los volúmenes lógicos.

Decisión: Si un LV abarca múltiples PVs inesperadamente, el rendimiento y los dominios de fallo cambian. Actualiza tu modelo mental.

Task 12: Errores de sistema de archivos y señales del journal

cr0x@server:~$ journalctl -k --since "2 hours ago" -p warning --no-pager | tail -n 30
Feb 05 03:11:22 server kernel: nvme nvme0: I/O 129 QID 7 timeout, aborting
Feb 05 03:11:23 server kernel: EXT4-fs warning (device dm-0): ext4_end_bio:344: I/O error 10 writing to inode 262402 starting block 8392704

Significado: Advertencias del kernel filtradas te dan una narrativa concisa de errores.

Decisión: Si aparecen advertencias de sistema de archivos, planifica un chequeo controlado del sistema de archivos e inspecciona el almacenamiento subyacente de inmediato.

Task 13: Errores de red que se disfrazan de “problemas de almacenamiento”

cr0x@server:~$ ip -s link show dev ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
      987654321  1234567      0      12       0       0
    TX:  bytes packets errors dropped carrier collsns
      123456789  7654321      0       0       0       0

Significado: Pérdidas y errores pueden crear retransmisiones y timeouts que parecen “la base de datos está lenta”.

Decisión: Si las pérdidas aumentan, revisa driver/firmware NIC, buffers de anillo y congestión upstream antes de desmontar el almacenamiento.

Task 14: Sincronización de tiempo y disciplina del reloj

cr0x@server:~$ timedatectl
               Local time: Mon 2026-02-05 03:24:11 UTC
           Universal time: Mon 2026-02-05 03:24:11 UTC
                 RTC time: Mon 2026-02-05 03:24:10
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Significado: Si el tiempo no está sincronizado, correlacionar logs entre sistemas se vuelve trabajo interpretativo.

Decisión: Si la sincronización está fuera, arregla NTP/chrony primero. Observabilidad sin tiempo es un baile interpretativo.

El bundle de soporte en un script (listo para producción)

Ahora convertimos esas tareas en un único script. Recopila:

  • Identidad del sistema (OS, kernel, uptime, modo de arranque)
  • Inventario de hardware (CPU, memoria, PCI, USB)
  • Drivers/módulos y pistas de firmware
  • Topología y salud del almacenamiento (lsblk, LVM, mdraid, ZFS, multipath si existe)
  • Errores (advertencias/errores de dmesg y extractos del journal)
  • Estado de la red
  • Un manifiesto más registros stderr de los comandos

También hace algunas cosas “de adulto”: comprobaciones defensivas, logs acotados en el tiempo y redacción de secretos evidentes en un par de salidas.
La redacción no es perfecta. Es un cinturón de seguridad, no invulnerabilidad.

cr0x@server:~$ cat sysreport.sh
#!/usr/bin/env bash
set -euo pipefail

# Full system report: hardware + drivers + errors
# Safe-by-default. No benchmarks. No destructive actions.
# Run as root for best results.

ts_utc="$(date -u +%Y%m%dT%H%M%SZ)"
host="$(hostname -s 2>/dev/null || hostname)"
out_root="${SYSREPORT_OUTDIR:-/tmp}"
bundle_dir="${out_root%/}/sysreport-${host}-${ts_utc}"
mkdir -p "$bundle_dir"/{meta,identity,hardware,drivers,storage,network,logs,errors,perf}

manifest="$bundle_dir/meta/manifest.txt"
stderr_log="$bundle_dir/meta/stderr.log"

run() {
  # run "command string" "output-file"
  local cmd="$1"
  local out="$2"
  {
    echo "### CMD: $cmd"
    echo "### WHEN_UTC: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo
    bash -lc "$cmd"
    echo
  } >"$out" 2>>"$stderr_log" || true

  {
    echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)  $out  $cmd"
  } >>"$manifest"
}

have() { command -v "$1" >/dev/null 2>&1; }

redact() {
  # Very light redaction for outputs likely to contain tokens/keys.
  # You should still review before sharing externally.
  sed -E \
    -e 's/(Authorization:)[[:space:]]*Bearer[[:space:]]+[A-Za-z0-9._-]+/\1 Bearer [REDACTED]/Ig' \
    -e 's/([Pp]assword=)[^[:space:]]+/\1[REDACTED]/g' \
    -e 's/([Tt]oken=)[^[:space:]]+/\1[REDACTED]/g'
}

# Identity
run "hostnamectl 2>/dev/null || true" "$bundle_dir/identity/hostnamectl.txt"
run "uname -a" "$bundle_dir/identity/uname.txt"
run "cat /etc/os-release 2>/dev/null || true" "$bundle_dir/identity/os-release.txt"
run "uptime -p; uptime" "$bundle_dir/identity/uptime.txt"
run "who -b 2>/dev/null || true" "$bundle_dir/identity/last-boot-who.txt"
run "test -d /sys/firmware/efi && echo UEFI || echo BIOS" "$bundle_dir/identity/boot-mode.txt"
run "timedatectl 2>/dev/null || true" "$bundle_dir/identity/timedatectl.txt"

# Hardware
run "lscpu" "$bundle_dir/hardware/lscpu.txt"
run "free -h" "$bundle_dir/hardware/free.txt"
run "cat /proc/meminfo" "$bundle_dir/hardware/proc-meminfo.txt"
run "dmidecode -t system -t baseboard -t bios -t processor -t memory 2>/dev/null || true" "$bundle_dir/hardware/dmidecode.txt"
run "lspci -nnk" "$bundle_dir/hardware/lspci-nnk.txt"
run "lsusb -t 2>/dev/null || true" "$bundle_dir/hardware/lsusb-tree.txt"
run "ls -l /dev/disk/by-id 2>/dev/null || true" "$bundle_dir/hardware/dev-disk-by-id.txt"

# Drivers / kernel
run "lsmod" "$bundle_dir/drivers/lsmod.txt"
run "sysctl -a 2>/dev/null | egrep '^(kernel\\.|vm\\.|fs\\.|net\\.)' | head -n 2000" "$bundle_dir/drivers/sysctl-kernel-vm-fs-net.txt"
run "cat /proc/cmdline" "$bundle_dir/drivers/kernel-cmdline.txt"
run "grep -R . /etc/modprobe.d 2>/dev/null || true" "$bundle_dir/drivers/modprobe-d.txt"

# Storage topology
run "lsblk -e7 -o NAME,TYPE,SIZE,MODEL,SERIAL,ROTA,TRAN,HCTL,FSTYPE,FSVER,UUID,MOUNTPOINTS" "$bundle_dir/storage/lsblk.txt"
run "blkid 2>/dev/null || true" "$bundle_dir/storage/blkid.txt"
run "findmnt -D" "$bundle_dir/storage/findmnt.txt"
run "df -hT" "$bundle_dir/storage/df-ht.txt"
run "mount" "$bundle_dir/storage/mount.txt"

# LVM / mdraid
run "pvs 2>/dev/null || true" "$bundle_dir/storage/lvm-pvs.txt"
run "vgs 2>/dev/null || true" "$bundle_dir/storage/lvm-vgs.txt"
run "lvs -a -o +devices 2>/dev/null || true" "$bundle_dir/storage/lvm-lvs.txt"
run "cat /proc/mdstat 2>/dev/null || true" "$bundle_dir/storage/mdstat.txt"
run "mdadm --detail --scan 2>/dev/null || true" "$bundle_dir/storage/mdadm-detail-scan.txt"

# ZFS (if present)
if have zpool; then
  run "zpool status -v" "$bundle_dir/storage/zpool-status.txt"
  run "zfs list -o name,used,avail,refer,mountpoint,compression,recordsize,atime,primarycache,secondarycache -t filesystem,volume 2>/dev/null || true" "$bundle_dir/storage/zfs-list.txt"
  run "zpool get all 2>/dev/null || true" "$bundle_dir/storage/zpool-get-all.txt"
fi

# Multipath (if present)
if have multipath; then
  run "multipath -ll 2>/dev/null || true" "$bundle_dir/storage/multipath-ll.txt"
fi

# NVMe and SMART (if present)
if have nvme; then
  run "nvme list" "$bundle_dir/storage/nvme-list.txt"
  run "for d in /dev/nvme*n1; do echo '## ' \$d; nvme id-ctrl \$d 2>/dev/null | head -n 80; echo; nvme smart-log \$d 2>/dev/null; echo; done" "$bundle_dir/storage/nvme-health.txt"
fi

if have smartctl; then
  run "lsblk -dn -o NAME,TYPE | awk '\$2==\"disk\"{print \"/dev/\"\$1}' | while read -r d; do echo '## ' \$d; smartctl -a \$d 2>/dev/null | head -n 120; echo; done" "$bundle_dir/storage/smartctl-head.txt"
fi

# Performance snapshots (safe)
run "vmstat 1 5" "$bundle_dir/perf/vmstat.txt"
run "iostat -xz 1 3 2>/dev/null || true" "$bundle_dir/perf/iostat.txt"
run "pidstat 1 3 2>/dev/null || true" "$bundle_dir/perf/pidstat.txt"
run "top -b -n 1 | head -n 80" "$bundle_dir/perf/top.txt"

# Network
run "ip -br link" "$bundle_dir/network/ip-link.txt"
run "ip -s link" "$bundle_dir/network/ip-link-stats.txt"
run "ip addr" "$bundle_dir/network/ip-addr.txt"
run "ip route" "$bundle_dir/network/ip-route.txt"
run "ss -s" "$bundle_dir/network/ss-summary.txt"
run "ss -tupna 2>/dev/null | head -n 2000" "$bundle_dir/network/ss-sockets.txt"

# Logs / errors (time-bounded)
run "dmesg -T" "$bundle_dir/logs/dmesg.txt"
run "dmesg -T --level=err,warn" "$bundle_dir/errors/dmesg-warn-err.txt"

if have journalctl; then
  run "journalctl -b --no-pager -n 3000" "$bundle_dir/logs/journal-this-boot-tail.txt"
  run "journalctl -k -b --no-pager -p warning..alert" "$bundle_dir/errors/journal-kernel-warning-alert.txt"
  run "journalctl -b --no-pager -p err..alert --since '24 hours ago'" "$bundle_dir/errors/journal-errors-24h.txt"
  run "journalctl --list-boots --no-pager" "$bundle_dir/logs/journal-boot-list.txt"
fi

# A light touch of redaction on socket listings (can include tokens in args on some systems)
if [ -f "$bundle_dir/network/ss-sockets.txt" ]; then
  redact <"$bundle_dir/network/ss-sockets.txt" >"$bundle_dir/network/ss-sockets.redacted.txt"
fi

# Meta
run "id; umask; ulimit -a" "$bundle_dir/meta/runtime.txt"
run "dpkg -l 2>/dev/null | head -n 4000 || true" "$bundle_dir/meta/packages-dpkg.txt"
run "rpm -qa 2>/dev/null | head -n 4000 || true" "$bundle_dir/meta/packages-rpm.txt"

# Bundle
tarball="${bundle_dir}.tar.gz"
tar -C "$out_root" -czf "$tarball" "$(basename "$bundle_dir")" 2>>"$stderr_log" || true

echo "Wrote: $tarball"
echo "Manifest: $manifest"
echo "Stderr log: $stderr_log"

Cómo ejecutarlo

cr0x@server:~$ sudo bash sysreport.sh
Wrote: /tmp/sysreport-server-20260205T032411Z.tar.gz
Manifest: /tmp/sysreport-server-20260205T032411Z/meta/manifest.txt
Stderr log: /tmp/sysreport-server-20260205T032411Z/meta/stderr.log

Significado: Obtienes un único tarball que puedes adjuntar al ticket del incidente, compartir internamente o comparar contra un host “conocido bueno”.

Decisión: Si stderr contiene muchos errores de permisos, vuelve a ejecutarlo como root o acepta explícitamente la visibilidad reducida y documenta la limitación.

Cómo leer el bundle como un SRE, no como turista

Empieza por los errores, luego confirma la topología

El camino más rápido suele ser:

  1. errors/dmesg-warn-err.txt y errors/journal-kernel-warning-alert.txt
  2. hardware/lspci-nnk.txt para mapear dispositivos a drivers
  3. storage/lsblk.txt y estado RAID/ZFS para ver qué pila de almacenamiento estás usando realmente
  4. perf/vmstat.txt y perf/iostat.txt (si están disponibles) para la dirección del cuello de botella

Busca estos “indicios”

  • Bucle de reinicios: “controller is down; will reset” repitiéndose no es un ruido normal.
  • Quejas del sistema de archivos: advertencias ext4/xfs suelen ir detrás del fallo real del dispositivo. La causa raíz suele estar más abajo.
  • Desajuste de driver: un driver NIC en uso que no coincide con el estándar de tu flota es deriva y riesgo de incidentes futuros.
  • Redundancia degradada: mdraid no [UU], ZFS degradado, multipath con rutas faltantes. Esto convierte pequeños fallos en interrupciones.
  • Temperaturas: alta temperatura más errores PCIe es un patrón real, especialmente en racks densos.

Cita (idea parafraseada) de W. Edwards Deming: “No puedes mejorar lo que no mides.” En ops: no puedes arreglar lo que no capturaste.

Chiste #2: Un “arreglo rápido” es solo un incidente largo con un bigote falso.

Tres mini-historias corporativas (y las lecciones que costaron)

Mini-historia 1: El outage causado por una suposición equivocada

Una compañía mediana ejecutaba un repositorio interno de artefactos en un par de servidores “idénticos”. Mismo modelo de CPU, misma cantidad de RAM, misma imagen de distro.
El equipo supuso que el almacenamiento también era igual, porque procurement dijo “NVMe 2TB” en ambas órdenes. ¿Casi lo mismo, no?

El incidente empezó como picos de latencia intermitentes. Las gráficas de la aplicación parecían un peine: bien, bien, bien, luego un diente afilado.
El on-call revisó CPU (bien), memoria (bien), red (bien). Reiniciaron el servicio. Los picos desaparecieron por una hora, luego volvieron.
Clásico “funciona tras reiniciar” absurdo.

Cuando finalmente generaron un bundle de informe apropiado, la diferencia estaba en storage/nvme-list.txt:
un host tenía un modelo NVMe y una revisión de firmware diferentes. El log del kernel mostraba reinicios periódicos del controlador en ese dispositivo específico.
Bajo el patrón de carga, el firmware del disco golpeó un caso límite, el controlador se descompuso, el kernel lo reinició, I/O se detenía,
y la app parecía “lenta”.

La suposición equivocada no era “NVMe es rápido.” Era “misma capacidad significa mismo comportamiento.” El almacenamiento no es una commodity; es una personalidad.
Misma interfaz, firmware distinto, modos de fallo distintos.

La solución fue aburrida: estandarizar el modelo/revisión del disco y añadir el bundle de un solo script al checklist de incidentes.
La próxima vez que procurement cambiara piezas, lo detectaron en staging en vez de descubrirlo con tráfico de clientes.

Mini-historia 2: La optimización que salió mal

Un equipo financiero tenía un pipeline de procesamiento de archivos sobre un ext4 encima de LVM. “Funcionaba” hasta fin de mes cuando
el rendimiento colapsó y el trabajo perdió su ventana. Alguien propuso una optimización audaz: montar con opciones agresivas,
desactivar atime, ajustar ratios de dirty y activar discard en todas partes para “mantener los SSDs sanos”.

Tras el cambio, el pipeline mejoró inicialmente. La gente celebró. Luego vino el lento deterioro: stalls esporádicos durante ráfagas de escritura pico.
La latencia empeoró, no mejoró. El bundle de informe (recopilado después, por supuesto) mostró dos pistolas humeantes.

Primero, las opciones de montaje y valores sysctl habían derivado lejos de los valores por defecto de la distro sin justificación escrita.
Segundo, los logs del kernel contenían timeouts NVMe durante actividad intensa de discard. La “optimización” alineó accidentalmente operaciones de discard
con las escrituras en ráfaga del pipeline. El firmware del SSD no lo agradeció. El patrón de reinicios del controlador volvió, y con ello las ventanas perdidas.

La lección dura: los tweaks de rendimiento que cambian patrones de I/O pueden exponer bugs de firmware y límites del controlador. Los defaults no son sagrados,
pero están probados en batalla. Si quieres tunear, hazlo con un plan de rollback y con instrumentación, no con intuiciones.

El equipo revirtió discard a un proceso programado y controlado (o lo deshabilitó cuando el dispositivo lo manejaba internamente),
restauró ajustes sensatos de dirty y requirió que cualquier tuning de kernel/almacenamiento se documente en el directorio “meta” del bundle como nota de cambio.
El pipeline volvió a ser aburrido. Aburrido es lo que quieres en finanzas.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

Una organización del ámbito salud (regulada, cauta, alérgica a sorpresas) mantenía un “snapshot de bundle de soporte” semanal
para cada host de base de datos en producción. No era sofisticado: ejecutar el script, almacenar el tarball, mantener una ventana rodante.
Los ingenieros se quejaban de que era trabajo administrativo. No parecía progreso. Parecía lavarse los dientes.

Luego un clúster empezó a lanzar advertencias de sistema de archivos ocasionalmente. Nada catastrófico, solo suficiente para poner nerviosa a la gente.
El on-call tiró del bundle más reciente y lo comparó con el de la semana pasada del mismo host y su par.
Las diferencias saltaron de inmediato: una actualización del kernel había aterrizado en un nodo pero no en el otro, y la versión del driver del controlador de almacenamiento cambió con ello.

También notaron un pequeño aumento en las entradas del log de errores NVMe en el nodo actualizado—visible en los SMART NVMe guardados—más
un aumento correspondiente en advertencias del kernel. Sin los bundles históricos hubiera sido difícil probar causalidad.
Con ellos fue obvio: no era “hardware aleatorio”. Era cambio + síntoma.

El equipo fijó la versión del kernel en todo el clúster, programó una ventana de mantenimiento y probó una combinación nueva de driver/firmware en staging.
Las advertencias cesaron. La práctica de “snapshots aburridos” se pagó en un incidente al convertir un misterio espeluznante en un rollback controlado.

Esa es la ganancia subestimada: los bundles de soporte no son solo para proveedores. Son para ti, una semana después, cuando tu memoria es ficción.

Errores comunes: síntoma → causa raíz → solución

Estos no son abstractos. He visto equipos perder horas (o fines de semana) con cada uno.

1) Síntoma: “Alta media de carga” → Causa raíz: espera de I/O y tareas bloqueadas → Solución: comprobar latencia de almacenamiento y logs del kernel

Lo que ves: La media de carga está alta, CPU idle parece decente, usuarios insisten “la CPU está al 100%”.
Causa raíz: Tareas en estado sleep ininterrumpible esperando I/O.
Solución: Usa vmstat, iostat y logs del kernel; luego mapea dispositivos lentos con lsblk y el controlador con lspci.
Si dmesg muestra timeouts/reinicios, escala a hardware/firmware.

2) Síntoma: “Errores de sistema de archivos aleatorios” → Causa raíz: reinicios del dispositivo subyacente → Solución: dejar de tratarlo como problema del sistema de archivos primero

Lo que ves: advertencias ext4/xfs, remounts ocasionales en modo solo lectura, mensajes del journal.
Causa raíz: El disco/controlador está inestable; el sistema de archivos es el mensajero.
Solución: Recopila logs SMART/NVMe, versiones de driver del controlador y busca errores PCIe en dmesg. Reemplaza/actualiza según convenga; luego repara el sistema de archivos.

3) Síntoma: “La NIC pierde paquetes bajo carga” → Causa raíz: desajuste driver/firmware o ajustes de offload → Solución: confirmar versión de driver y estado de enlace

Lo que ves: Las pérdidas de paquetes aumentan, retransmisiones suben, las apps hacen timeouts.
Causa raíz: Desajuste firmware NIC con driver del kernel, o una combinación de offloads mala.
Solución: Revisa lspci -nnk y modinfo. Estandariza driver/firmware; valida offloads deliberadamente, no al azar.

4) Síntoma: “El proveedor no puede ayudar; piden más info” → Causa raíz: el informe no tiene versiones ni topología → Solución: incluir archivos de mapeo

Lo que ves: Envías logs; el proveedor pide modelo de hardware, versiones de driver, revisiones de firmware, estado RAID.
Causa raíz: Recopilaste síntomas pero no identidad y configuración.
Solución: Asegura que el script incluya lspci -nnk, modinfo, salidas de salud de almacenamiento, versiones OS/kernel y historial de arranque.

5) Síntoma: “El bundle es enorme e inútil” → Causa raíz: logs y volcados binarios sin límite → Solución: acotar en el tiempo y resumir

Lo que ves: tarball de 500MB que nadie descarga.
Causa raíz: Export completo del journal, lista completa de paquetes, copiar /var/log entero.
Solución: Captura logs recientes (tail del arranque, errores últimas 24h) más resúmenes enfocados; deja el resto como flags opcionales.

6) Síntoma: “No podemos compartirlo; contiene secretos” → Causa raíz: recopilación descuidada → Solución: establecer defaults seguros y controles de revisión

Lo que ves: Seguridad bloquea compartir con el proveedor, el incidente se alarga.
Causa raíz: El script capturó configuraciones o argumentos de procesos con credenciales.
Solución: No recopiles rutas sensibles; redacta salidas de alto riesgo; almacena el bundle con seguridad; ten una lista de verificación antes de compartir externamente.

Listas de verificación / plan paso a paso

Checklist A: Construye tu script de forma segura (una vez)

  1. Define el propósito. Instantánea de respuesta a incidentes? Bundle de soporte para proveedor? Detección de deriva? (Elige uno primario.)
  2. Escoge un layout de salida estable. identity/, hardware/, drivers/, storage/, network/, logs/, errors/, meta/.
  3. Haz cada comando no interactivo. Si puede bloquear, ponlo detrás de un guard “have tool”.
  4. Logs acotados en el tiempo. Tail del arranque actual + errores últimas 24h suele ser el punto óptimo.
  5. Registra fallos. Un stderr.log no es opcional. Fallos silenciosos desperdician tiempo.
  6. No mutar el estado. No rescans, no checks de sistema de archivos, no tuning, no actualizaciones de firmware en la ejecución por defecto.
  7. Empaquétalo. Tarball más manifiesto de comandos ejecutados.

Checklist B: Ejecútalo durante un incidente (cada vez)

  1. Ejecuta en el host afectado primero, luego en un “peer sano” si lo tienes.
  2. Adjunta el tarball al ticket inmediatamente. No lo guardes en tu laptop como un artefacto preciado.
  3. Ojea meta/stderr.log para asegurarte de que capturaste lo que importaba.
  4. Empieza el análisis con errors/. Luego mapea dispositivos/drivers. Luego confirma estado de redundancia.
  5. Anota el “primer timestamp malo” de los logs. Úsalo para correlacionar con despliegues y cambios de configuración.

Checklist C: Hacerlo apto para flotas (la diferencia entre un script y una práctica)

  1. Almacena snapshots semanales para niveles críticos (bases de datos, nodos de almacenamiento, balanceadores).
  2. Estandariza baselines de kernel/driver/firmware por clase de hardware.
  3. Automatiza diffs contra un host dorado para detección de deriva (incluso un diff rudimentario es mejor que nada).
  4. Define retención y controles de acceso; los bundles pueden contener detalles operativos sensibles aun redactedos.

Preguntas frecuentes

1) ¿Debo ejecutar esto como root?

Sí, si quieres un informe realmente útil. Root te da logs del kernel, salud SMART/NVMe y detalles de la pila de almacenamiento.
Si no puedes ejecutarlo como root, ejecútalo igualmente, pero espera datos faltantes y registra esa limitación en el ticket del incidente.

2) ¿Recopilar estos datos afectará el rendimiento?

Ligeramente. Comandos como lspci, lsblk, consultas de journalctl y lecturas SMART suelen tener bajo impacto.
Evita comandos pesados (benchmarks, tests SMART largos) en el script por defecto. Si necesitas pruebas activas, házlas explícitamente y en ventana controlada.

3) ¿Por qué no enviar todo a una plataforma de logging y ya?

El logging central es excelente—hasta que no lo es. Los bundles de soporte capturan la “verdad local” incluyendo identidad de hardware, mapeos de drivers y topología de almacenamiento
que a menudo no están en la pipeline de logging. Además, durante outages la pipeline de logging a veces es la primera víctima.

4) ¿Por qué incluir tanto dmesg como journalctl?

Porque los entornos difieren. Algunos sistemas restringen dmesg para no-root, algunos rotan logs agresivamente, y a veces necesitas ambas vistas.
Journal añade metadatos de arranque; dmesg muestra el buffer del kernel de forma clara. Redundancia es una característica, no desorden.

5) ¿Cómo comparo dos bundles?

Descomprime y diff archivos clave: identity/uname.txt, hardware/lspci-nnk.txt, drivers/lsmod.txt,
storage/lsblk.txt, estado RAID/ZFS y logs de errores. No diffs todo el log de entrada primero; te ahogarás.

6) ¿Y los contenedores y nodos Kubernetes?

Ejecuta el script en el nodo, no dentro de un contenedor, si te importan errores de hardware/driver. Los contenedores no ven la vista completa del kernel.
Para Kubernetes, añade identidad del nodo (versión de kubelet, info del runtime) como extensión opcional—pero mantén el script base genérico.

7) ¿Y si herramientas como nvme-cli o smartmontools no están instaladas?

El script comprueba la presencia de herramientas y se salta con gracia. En producción, estandariza una imagen mínima con el “diagnostics toolset” por distro.
No pidas al on-call instalar paquetes durante un outage a menos que disfrutes crear nuevos outages.

8) ¿Cómo mantengo los secretos fuera del informe?

Primero: no recopiles rutas sensibles. Segundo: acota los logs en el tiempo. Tercero: redacta selectivamente (como lo hace el script para algunos casos).
Finalmente: trata el bundle como sensible igualmente—almacénalo en sistemas seguros y revísalo antes de compartir externamente.

9) ¿Puedo añadir logs de aplicación a esto?

Puedes, pero con disciplina. Añade una flag opcional separada (por ejemplo, --app) y mantenla desactivada por defecto.
Los logs de aplicación suelen ser enormes y más propensos a contener datos de clientes. El informe base del sistema debe permanecer enfocado.

10) ¿Cuál es el archivo más valioso del bundle?

Usualmente errors/dmesg-warn-err.txt. Es donde hardware y drivers admiten que están fallando. El segundo más valioso es
hardware/lspci-nnk.txt, porque convierte errores vagos en un dispositivo/driver específico sobre el que actuar.

Conclusión: próximos pasos que realmente harás

Un informe completo del sistema no es un artefacto mágico. Es una instantánea disciplinada: identidad, topología, salud y errores—capturados de forma segura,
en un formato que puedes diffear y compartir. El script anterior es la columna vertebral. La práctica es lo que la hace rentable.

  1. Incluye el script en tu repo de ops y trátalo como código de producción: revisado, versionado, probado.
  2. Estandariza un conjunto de herramientas de diagnóstico en tus imágenes para que el script pueda recopilar NVMe/SMART y detalles de almacenamiento de forma consistente.
  3. Haz que “recopilar bundle” sea el paso cero en tus runbooks de incidentes, antes de tunear, reiniciar o culpar.
  4. Empieza a guardar snapshots semanales para sistemas críticos. Lo detestarás hasta el día en que te salve.
  5. Usa el bundle para hacer cumplir baselines: kernel, drivers, firmware, configuración de almacenamiento. La deriva es una interrupción en cuotas.
← Anterior
CPU de hardware: La trampa de la actualización — BIOS, microcódigo y realidad de los VRM
Siguiente →
Encontrar y eliminar actualizaciones antiguas de Windows (de forma segura) con PowerShell

Deja un comentario