Згенерувати повний звіт системи (апаратне забезпечення, драйвери та помилки) одним скриптом

Було корисно?

Ви знаєте цей момент. 02:13, база даних «повільна», і єдиний доказ — скриншот top
та туманна пам’ять, що «вчора все було нормально». Постачальник просить «повний звіт системи», ваш менеджер хоче таймлайн,
а ви хочете спати. Правильний крок — змусити машину розповісти свою історію в одному відтворюваному знімку.

Ось як побудувати один скрипт, який збирає апаратне забезпечення, драйвери, стан сховища, повідомлення ядра та ті помилки,
що справді важливі — без виведення системи з ладу, без витоку секретів і без створення нечитаємого 80MB бінарного блоба, який ніхто не відкриває.

Що означає «добре» у повному звіті системи

Повний звіт системи — це не трофей. Це інструмент. Якщо він не може швидко відповісти на «що змінилося?» і «що ламається?»,
то це просто звіт по дисковому простору з додатковими кроками.

Ось планка, яку я використовую в продакшені:

  • Одна команда для запуску. Без інтерактивних підказок. Ніяких «встановіть це» о 3 ранку.
  • Читабельність перш за все. Текстові файли, згруповані за темами. Людина повинна швидко переглянути їх.
  • Дружній до машинного diff. Стабільне форматування, щоб можна було порівнювати сьогодні та минулий тиждень.
  • Мінімальний ризик. Без бенчмарків за замовчуванням. Жодних інвазивних інструментів прошивки. Жодних «сканування шини» героїчних дій.
  • Уважність до секретів. Захоплюйте достатньо інформації для діагностики; уникайте дампів токенів, даних клієнтів і приватних ключів.
  • Коректність для сховища. Якщо на машині є ZFS, mdraid, LVM, multipath, NVMe — збирайте їхню стан правильно.
  • Фокус на помилках. Забирайте помилки ядра й журналу з контекстом. Не просто «всі журнали з 2019 року».

Також: стисніть архів. Назвіть його осмислено. Додайте маніфест. Якщо ви коли-небудь пробували відправити вендору «я скопіював трохи файлів з /var/log»,
ви вже знаєте, чому це погана ідея.

Факти й коротка історія: чому все так влаштовано

Трохи контексту робить інструмент кращим. Ці деталі пояснюють, чому Linux-звітування нагадує шафу з дивно-зігнутими гаками.

  1. /proc і /sys з’явилися тому, що ядру потрібен був «файлова система» API для інспекції. Це не диск; це вид на стан ядра.
  2. lspci походить з PCI-утиліт, які існували до багатьох «сучасних» систем спостереження. Він досі найшвидший спосіб зіставити пристрої з драйверами.
  3. dmesg — старомодний буфер кільця логів. Він шумний, але саме там апаратні та драйверні збої зізнаються першими.
  4. systemd’вий журнал створений, щоб виправити фрагментацію логів. Він централізує журнали, додає метадані та робить «показати завантаження» першокласним запитом.
  5. SMART існував раніше за NVMe. NVMe «SMART log» схожий за ідеєю, але не ідентичний; змішування інтерпретацій породжує погані висновки.
  6. mdraid пережив час, бо він нудний і хороший. Він в ядрі, стабільний і зрозумілий — все ще дефолт у багатьох підприємствах.
  7. Імена пристроїв типу /dev/sda ніколи не мали бути стабільними ідентифікаторами. Саме тому існує /dev/disk/by-id і udev-правила.
  8. Multipath існує тому, що SAN інколи мовчить про речі. Якщо ви не перевіряєте стан шляхів, ви повірите, що «резервування» означає «безпечність».
  9. Сучасна топологія CPU складна, бо продуктивність складна. NUMA, SMT і управління живленням можуть зробити «той самий модель CPU» поводитися по-різному.

Жарт №1: Журнали як місця злочину — усі кажуть, що «нічого не чіпали», а потім ви знаходите свіжі відбитки пальців по всьому /etc.

Принципи проєктування: безпечно, порівнювано, підтримувано

1) Віддавайте перевагу інспекції в режимі «тільки читання» над активним зондуванням

Ви можете отримати 90% цінності від інспекції: lsblk, lspci, modinfo, journalctl, читання SMART.
Активне зондування (стрес-тести, rescans, оновлення прошивки) може змінити систему або погіршити відмову. Не робіть цього за замовчуванням.

2) Спершу захоплюйте ідентичність і контекст

Перед тим як збирати щось інше, зафіксуйте:

  • hostname, версію ОС, версію kernel, uptime
  • стан синхронізації часу
  • підказки щодо віртуалізації/контейнера
  • історію завантажень і причину останнього перезавантаження (коли доступно)

Причина проста: багато «помилок» — це просто стрибки часу, часткові завантаження або невідповідність kernel. Контекст запобігає діагностиці привидів.

3) Зробіть вихід достатньо стабільним для diff

Людям подобається «останні вгорі». Інструментам для diff — стабільність. Ви можете поєднати обидва підходи, записуючи файли з детермінованими іменами та стабільними форматами,
і розділяючи «поточний стан» від «недавніх подій». Наприклад: збережіть вивід lsblk і також збережіть «journal errors since boot».

4) Уникайте випадкового збору секретів

Не збирайте:

  • /etc/shadow, приватні SSH-ключі, токени метаданих хмар
  • конфігурації додатків з обліковими даними (URL баз даних, API-ключі)
  • повні дампи оточення з виводів процесів

Замість цього збирайте санітайзені фрагменти конфігів (версії пакетів, статус сервісів, unit-файли) і журнали з обмеженим часовим вікном.
Support bundle має бути безпечним для внутрішнього обміну з вашою командою без довгого листа вибачень.

5) Будьте явними щодо дозволів

Багато корисних команд потребують root: читання SMART, доступ до журналу, деякі інструменти сховища. Ваш скрипт має:

  • запускатися як root (рекомендується) або деградуватися коректно
  • реєструвати, які команди не спрацювали через дозволи
  • ніколи не викликати «sudo» всередині скрипта (багато середовищ це забороняє)

6) Захоплюйте помилки з оточуючими доказами

Стек-треки ядра, повідомлення про скидання NVMe, помилки ext4, таймаути mpt3sas — це крихти хліба.
Коли ви витягуєте помилки, включайте кілька рядків контексту і ідентифікатор завантаження / часову мітку. Інакше ви вставите
один страшний рядок у чат і розпочнете паніку, якої не треба було.

План швидкої діагностики (перший/другий/третій)

Коли хтось каже «сервер повільний», вони мають на увазі «мій запит повільний». Це може бути CPU, сховище, пам’ять, мережа
або драйвер, що спамить скиданнями. Почніть з перевірок, які відкидають цілі класи проблем.

Перший: підтвердіть базові речі (10 секунд)

  • Чи час адекватний? Стрибки часу роблять журнали марними і можуть зламати TLS, кластери та кеші.
  • Чи машина перезавантажується або флапається? Uptime і журнали завантаження скажуть, чи ви женетеся за рухомою ціллю.
  • Чи є буря в dmesg? Якщо ядро кричить — послухайте, перш ніж щось підправляти.

Другий: ідентифікуйте домен вузького місця (1 хвилина)

  • Навантаження CPU? Високе load з високим user/sys або черга виконання зростає.
  • Тиск пам’яті? Активність swap, OOM kills, проблеми з reclaim.
  • I/O wait? Підвищений iowait, заблоковані завдання, затримки диска.
  • Мережа? Падіння пакетів, ретрансляції, скидання драйвера NIC.

Третій: зіставте симптоми з фізичним/драйверним шаром (5 хвилин)

  • Який пристрій повільний? Який контролер? Який драйвер?
  • Чи збігаються помилки з версією прошивки або модулем?
  • Чи пул RAID/ZFS деградований?
  • Чи змінився стек сховища після «малого» оновлення kernel?

Надійний робочий процес: журнали → топологія → здоров’я → дрейф конфігурації. Навпаки («спочатку налаштувати sysctl») —
це як полірувати капот, поки двигун горить.

12+ практичних завдань: команди, значення, рішення

Ось конкретні завдання, які має охоплювати «повний звіт системи». Кожне містить: команду, що показує вихід, і яке рішення можна з цього зробити.
Використовуйте їх інтерактивно, а також впровадьте в один скрипт бандла пізніше.

Завдання 1: Визначити ОС + kernel + режим завантаження

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

Значення: Версія kernel і збірка впливають на поведінку драйверів (особливо сховища та NIC).

Рішення: Якщо kernel нещодавно змінився, розглядайте «регрес продуктивності» як «невідповідність драйвера/прошивки, поки не доведено протилежне».

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)"

Значення: Політика оновлень пакетів і kernel зазвичай витікає з дистрибутиву та релізу.

Рішення: Підтримка вендора часто залежить від мінорного релізу дистрибутиву; не ігноруйте це.

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

Значення: Режим завантаження впливає на розділення дисків, поведінку завантажувача і іноді інструменти прошивки.

Рішення: Для флоту: стандартизуйте режим завантаження; мікс UEFI/BIOS ускладнює автоматизацію та відновлення.

Завдання 2: Підтвердити uptime і журнали останнього завантаження

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

Значення: Довгі uptimes ховають повільну деградацію; короткі означають, що вікно доказів маленьке.

Рішення: Якщо uptime підозріло короткий, приділіть пріоритет «чому перезавантажився» перед «чому повільний».

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

Значення: Повідомлення попередніх завантажень часто показують першу появу проблеми (наприклад, скидання сховища).

Рішення: Якщо в попередніх загрузках видно скидання пристроїв, припиніть звинувачувати додаток і почніть перевіряти стан сховища/PCIe.

Завдання 3: Швидкий знімок CPU і пам’яті

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

Значення: r черга виконання, b заблоковані завдання, swap in/out, і wa iowait.

Рішення: Високий wa і заблоковані завдання означають затримки сховища; не «додайте CPU», щоб виправити проблему диска.

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

Значення: «free» пам’ять — це не вся історія; «available» важливіший показник.

Рішення: Якщо available низький і затримки високі, перевірте reclaim/IO; якщо swap існує і активний — очікуйте спайки хвостової затримки.

Завдання 4: Швидко знайти помилки ядра

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

Значення: Це ядро каже вам правду: таймаути, скидання, наслідки файлової системи.

Рішення: Якщо ви бачите скидання/таймаути, призупиніть налаштування продуктивності. Далі збирайте версії прошивки, стан PCIe-лінку і здоров’я сховища.

Завдання 5: Зіставити PCI пристрої з драйверами

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

Значення: «Який пристрій, який драйвер.» Це дозволяє зв’язати таймаут у dmesg з конкретним контролером і модулем.

Рішення: Якщо драйвер несподіваний (fallback driver або старий out-of-tree модуль), це ризик підтримуваності та стабільності.

Завдання 6: Підтвердити завантажені модулі та їх версії

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

Значення: Завантажені модулі показують, що насправді виконується, а не те, що ви думаєте, встановлено.

Рішення: Якщо модулі сховища/NIC відсутні або мають дивні «Used by» значення, підозрюйте churn драйверів або часткові оновлення.

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

Значення: Версія драйвера і очікувані пакети прошивки тут присутні.

Рішення: Якщо драйвер очікує пакет прошивки, якого немає — ви можете отримати деградовані функції або дивну поведінку лінку.

Завдання 7: Інвентаризація дисків, файлових систем і опцій монтування

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   /

Значення: Це зіставляє фізичні пристрої з логічними шарами (розділи → LVM → файлові системи).

Рішення: Якщо бачите несподіване наслаювання (наприклад, mdraid поверх dm-crypt поверх LVM), продуктивність і відновлення ускладнюються. Документуйте це.

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

Значення: Опції монтування мають значення: barriers, atime, discard, обробка помилок.

Рішення: Якщо критичні файлові системи змонтовані з ризикованими опціями (наприклад, відключення журналювання або barriers), вважайте це потенційним інцидентом.

Завдання 8: Перевірити здоров’я NVMe (якщо присутній)

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

Значення: Ревізія прошивки — не дрібниця; часто вона відрізняє «стабільно» від «таємничих скидань».

Рішення: Якщо FW Rev відома як проблемна у вашому середовищі — заплануйте контрольоване оновлення, а не аварійний патч у продакшені.

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

Значення: critical_warning, media_errors і кількість записів у журналі помилок — ваші ранні тривожні сигнали.

Рішення: Якщо лічильник помилок росте і ви бачите таймаути ядра — підозрівайте пристрій, PCIe-лінк або взаємодію контролера/прошивки.

Завдання 9: Перевірити класичний SMART (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

Значення: «PASSED» — не чиста довідка про здоров’я; потрібні тренди атрибутів і журнали помилок.

Рішення: Якщо є переспрямовані/очікувані сектора або зростають помилки — замініть проактивно. Диски не лікуються; вони лише стають поетичнішими.

Завдання 10: Стан RAID/ZFS (що застосовно)

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]

Значення: [UU] означає, що всі члени працюють. Будь-що інше — деградовано, а деградовані масиви працюють повільно.

Рішення: Якщо деградовано — припиніть «розслідування продуктивності» і почніть «розслідування захисту даних». Потім відновлюйте безпечно.

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

Значення: ZFS підкаже, чи збережена надмірність і чи scrubs знаходять корупцію.

Рішення: Якщо scrubs показують помилки або статус DEGRADED, вважайте апаратний шар підозрюваним, поки не доведено протилежне.

Завдання 11: Санітарність LVM та device-mapper

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

Значення: Відображення PV/VG/LV ловить сюрпризи «хтось щось змінив розмір».

Рішення: Якщо бачите відсутні PV або часткові VGs — зупиніться. Можливо ви працюєте на деградованому або неправильно зібраному стеку.

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)

Значення: Показує, які підлеглі пристрої підтримують логічні томи.

Рішення: Якщо LV несподівано розподілено по багатьох PV — змінюються кордони продуктивності та зони відмов. Оновіть ментальну модель.

Завдання 12: Помилки файлової системи та сигнали журналу

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

Значення: Відфільтровані попередження ядра дають компактний наратив помилок.

Рішення: Якщо з’являються попередження файлової системи — плануйте контрольовану перевірку файлової системи і негайно інспектуйте підлегле сховище.

Завдання 13: Мережеві помилки, що маскуються під «проблеми сховища»

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

Значення: Втрачені пакети і помилки можуть створювати ретрансляції та таймаути, які виглядають як «база даних повільна».

Рішення: Якщо різко зростають дропи — перевірте драйвер/прошивку NIC, розміри кольцевих буферів і upstream-завантаження, перш ніж розбиратися зі сховищем.

Завдання 14: Синхронізація часу та дисципліна годинника

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

Значення: Якщо час не синхронізований, кореляція журналів між системами стає гаданням.

Рішення: Якщо синхронізація порушена — виправте NTP/chrony перш за все. Наблююваність без часу — це інтерпретаційний танець.

Один скрипт support bundle (готовий до продакшену)

Тепер перетворимо ці завдання в один скрипт. Він збирає:

  • Ідентичність системи (OS, kernel, uptime, режим завантаження)
  • Інвентар апаратури (CPU, пам’ять, PCI, USB)
  • Драйвери/модулі та підказки щодо прошивки
  • Топологію та стан сховища (lsblk, LVM, mdraid, ZFS, multipath якщо є)
  • Помилки (dmesg попередження/помилки, витяги з journal)
  • Стан мережі
  • Маніфест плюс stderr лог команд

Він також робить кілька «дубових» речей: оборонні перевірки, логування з часовими межами і редагування очевидних секретів у деяких виводах.
Редагування не ідеальне. Це ремінь безпеки, а не невразливість.

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"

Як його запускати

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

Значення: Ви отримуєте один tarball, який можна прикріпити до інцидентного тікета, поділитися внутрішньо або порівняти з «відомо-гарною» машиною.

Рішення: Якщо stderr містить багато помилок доступу, запустіть знову як root або задокументуйте обмежену видимість і прийміть це.

Як читати бандл як SRE, а не турист

Почніть з помилок, потім підтвердіть топологію

Найшвидший шлях зазвичай такий:

  1. errors/dmesg-warn-err.txt і errors/journal-kernel-warning-alert.txt
  2. hardware/lspci-nnk.txt щоб зіставити пристрої з драйверами
  3. storage/lsblk.txt і статус RAID/ZFS щоб побачити, який стек сховища фактично працює
  4. perf/vmstat.txt і perf/iostat.txt (якщо доступно) для напрямку вузького місця

Шукайте ці «показники»

  • Цикли скидань: Повторювані «controller is down; will reset» — не нормальний шум.
  • Скарги файлової системи: Попередження ext4/xfs часто запізнюються відносно фактичної відмови пристрою. Коренева причина зазвичай нижче.
  • Невідповідність драйвера: NIC-драйвер, що відрізняється від флот-стандарту — це дрейф і майбутні інциденти.
  • Деградована надмірність: mdraid не [UU], ZFS degraded, multipath — відсутні шляхи. Це перетворює дрібні збої в аварії.
  • Термальність: висока температура плюс PCIe-помилки — реальна закономірність, особливо у щільних стояках.

Цитата (парафраз) від W. Edwards Deming: «Ви не можете покращити те, що не вимірюєте». В опсах: ви не можете виправити те, що не захопили.

Жарт №2: «Швидке виправлення» — це довгий інцидент у фальшивих вусах.

Три корпоративні міні-історії (і уроки, за які заплатили)

Міні-історія 1: Аутейдж через хибне припущення

Середня компанія тримала внутрішній репозиторій артефактів на парі «ідентичних» серверів. Та сама модель CPU, той самий обсяг RAM, той самий образ дистрибутиву.
Команда припустила, що сховище теж однакове, бо закупівля в обох позиціях писала «2TB NVMe». «Достатньо близько», правда?

Інцидент почався як періодичні спайки затримок. Метрики додатку виглядали як гребінь: нормально, нормально, нормально, потім різкий зуб.
On-call перевірив CPU (добре), пам’ять (добре), мережу (добре). Перезапустили сервіс. Спайки зникли на годину, потім повернулися.
Класика «працює після перезапуску».

Коли нарешті зібрали правильний system report bundle, різниця була в storage/nvme-list.txt:
на одному хості була інша модель NVMe і інша ревізія прошивки. Журнал ядра показував періодичні скидання контролера на тому конкретному пристрої.
Під навантаженням прошивка накопичувала крайовий випадок, контролер «виходив з ладу», kernel скидав його, I/O зависав,
і додаток виглядав «повільним».

Хибне припущення було не в «NVMe швидкий». Хибне припущення — «така ж ємність = така сама поведінка». Сховище — не товар; це характер.

Виправлення було нудним: стандартизували модель/прошивку диска і додали one-script bundle до чекліста інцидентів.
Наступного разу закупівля змінила деталь — дрейф помітили в staging, а не під час трафіку клієнтів.

Міні-історія 2: Оптимізація, що відбилася боком

Фінансова команда мала конвеєр обробки файлів на ext4 поверх LVM. Було «добре», доки в кінці місяця пропускна здатність не впала і завдання не просрочило вікно.
Хтось запропонував сміливу оптимізацію: змінити опції монтування, відключити atime, підкрутити dirty ratios і включити discard скрізь, щоб «підтримувати SSD здоровим».

Після зміни конвеєр спочатку прискорився. Люди святкували. Потім почалися повільні зависання під час пікових записів.
Затримки стали гірші. System report bundle (зібраний після інциденту, бо куди ж без цього) показав два вагомі сліди.

По-перше, опції монтування і sysctl відійшли від дефолтів без письмового пояснення.
По-друге, журнали ядра містили NVMe-таймаути під час інтенсивної активності discard. «Оптимізація» випадково узгодила discard з піковими записами конвеєра.
Прошивка SSD цього не полюбила. Патерн скидань контролера повернувся, як і пропущені дедлайни.

Жорсткий урок: тюнінг продуктивності, що змінює патерни I/O, може виявити баги прошивки і межі контролера. Дефолти не святі, але вони перевірені бойовою експлуатацією.
Якщо хочете налаштовувати — робіть це з планом відкату і метриками, а не «на відчуття».

Команда повернула discard до запланованого контрольованого процесу (або вимкнула його, якщо пристрій керував цим сам),
відкотила адекватні dirty налаштування і вимагала, щоб будь-які ядрові/сховищні налаштування документувалися в «meta» директорії бандла як нотатка про зміну.
Конвеєр повернувся до «нудного» стабільного стану. Нудність — це бажано у фінансах.

Міні-історія 3: Нудна, але правильна практика, що врятувала день

Одна регульована організація вела щотижневі «snapshot support bundle» для кожного production хоста бази даних. Це було просто: запускати скрипт, зберігати tarball, тримати обертання.
Інженери скаржилися, що це нудна рутина. Не відчувалося, що це прогрес. Це було наче чистити зуби.

Потім кластер почав викидати випадкові попередження файлової системи. Нічого катастрофічного, але достатньо, щоб нервувати.
On-call витягнув останній бандл і порівняв його з тижневим з того ж хоста і його піром.
Різниці були миттєво помітні: оновлення kernel відбулося на одному вузлі, але не на іншому, і версія драйвера контролера сховища змінилася разом з цим.

Також помітили невелике зростання записів помилок NVMe на оновленому вузлі — видно в збережених NVMe SMART логах —
і відповідне збільшення попереджень ядра. Без історичних бандлів було б складно довести причинно-наслідковий зв’язок.
З бандлами було очевидно: це не «рандомний хардвер», а зміна + симптом.

Команда зафіксувала версію kernel по кластеру, запланувала вікно обслуговування і протестувала новий драйвер/прошивку в staging.
Попередження зникли. «Нудні знімки» окупилися за один інцидент, перевівши страшну загадку в контрольований відкат.

Це недооцінений виграш: support bundle корисні не лише для вендора. Вони корисні вам, через тиждень, коли ваша пам’ять — це художній твір.

Типові помилки: симптом → корінна причина → виправлення

Це не абстракції. Я бачив, як команди губили години (або вихідні) через кожну з них.

1) Симптом: «Високий load average» → Корінь: I/O wait та заблоковані завдання → Виправлення: перевірити затримки сховища та журнали ядра

Що ви бачите: Load average високий, CPU idle виглядає нормальним, користувачі наполягають «CPU завантажений».
Корінь: Завдання застрягли в uninterruptible sleep, чекаючи I/O.
Виправлення: Використайте vmstat, iostat і журнали ядра; потім зіставте повільні пристрої через lsblk і контролер через lspci.
Якщо dmesg показує таймаути/скидання — ескалюйте до апаратного/прошивкового рівня.

2) Симптом: «Випадкові помилки файлової системи» → Корінь: скидання підлеглого пристрою → Виправлення: не лікуйте спочатку як проблему ФС

Що ви бачите: Попередження ext4/xfs, випадкові перевантаження читанням, повідомлення журналу.
Корінь: Диск/контролер флакує; файлова система лише повідомляє.
Виправлення: Збирайте SMART/NVMe логи, версії драйверів контролера і шукайте PCIe-помилки в dmesg. Заміна/оновлення за потреби; потім відновіть ФС.

3) Симптом: «NIC дропи під навантаженням» → Корінь: невідповідність драйвера/прошивки або налаштування offload → Виправлення: підтвердити версію драйвера і стан лінку

Що ви бачите: Пакети падають, ретрансляції зростають, додатки таймаутять.
Корінь: Невідповідність прошивки NIC з драйвером kernel або погана комбінація offload.
Виправлення: Перевірте lspci -nnk і modinfo. Стандартизуйте драйвер/прошивку; валідируйте offloads обережно.

4) Симптом: «Вендор не може допомогти; просить більше даних» → Корінь: звіт не має версій і топології → Виправлення: додайте мапуючі файли

Що ви бачите: Ви послали логи; вендор просить модель апаратури, версії драйверів, ревізії прошивки, стан RAID.
Корінь: Ви зібрали симптоми, але не ідентифікацію і конфігурацію.
Виправлення: Переконайтеся, що скрипт включає lspci -nnk, modinfo, виводи стану сховища, версії ОС/kernel і історію завантажень.

5) Симптом: «Бандл величезний і марний» → Корінь: необмежені журнали і бінарні дампи → Виправлення: обмежувати час і підсумовувати

Що ви бачите: 500MB tarball, який ніхто не завантажує.
Корінь: Повний експорт журналу, повний список пакетів, копіювання усього /var/log.
Виправлення: Захоплюйте нещодавні журнали (хвіст поточного завантаження, помилки за останні 24 години) і сфокусовані підсумки; залиште інше як опцію.

6) Симптом: «Ми не можемо поділитися; там секрети» → Корінь: необережний збір → Виправлення: безпечні дефолти і контроль перед обміном

Що ви бачите: Безпека блокує зовнішню передачу вендору, інцидент тягнеться.
Корінь: Скрипт зібрав конфіги або аргументи процесів з обліковими даними.
Виправлення: Не збирайте чутливі шляхи; робіть редагування ризикових виводів; зберігайте бандл у безпечному місці; перед зовнішньою передачею пройдіть чекліст рев’ю.

Перевірочні списки / покроковий план

Чекліст A: Побудуйте свій скрипт безпечно (один раз)

  1. Визначте мету. Знімок для інцидент-реакції? Support bundle для вендора? Виявлення дрейфу? (Виберіть одне основне.)
  2. Обирайте стабільну структуру виводу. identity/, hardware/, drivers/, storage/, network/, logs/, errors/, meta/.
  3. Зробіть кожну команду неінтерактивною. Якщо може блокувати — ставте її за перевіркою наявності інструменту.
  4. Обмежуйте журнали за часом. Хвіст поточного завантаження + помилки за останні 24 години зазвичай оптимально.
  5. Записуйте збої. stderr.log — не опція. Тихі збої марнують час.
  6. Не змінюйте стан. Ніяких rescans, перевірок ФС, налаштувань, оновлень прошивки за замовчуванням.
  7. Запаковуйте. Tarball плюс маніфест виконаних команд.

Чекліст B: Запускайте під час інциденту (кожного разу)

  1. Запустіть на ураженому хості перш за все, потім на «здоровому peer», якщо є.
  2. Прикріпіть tarball до тікета негайно. Не тримайте його на лаптопі як реліквію.
  3. Погляньте meta/stderr.log, щоб переконатися, що ви дійсно захопили потрібні дані.
  4. Починайте аналіз з errors/. Потім зіставляйте пристрої/драйвери. Потім підтверджуйте стан надмірності.
  5. Запишіть «першу погану часову мітку» з журналів. Використайте її для кореляції з деплоєм та змінами конфігурації.

Чекліст C: Зробіть це готовим для флоту (різниця між скриптом і практикою)

  1. Зберігайте щотижневі знімки для критичних шарів (бази даних, ноди сховища, load balancers).
  2. Стандартизуйте базові набори kernel/драйвер/прошивка для класів апаратури.
  3. Автоматизуйте diff проти золотого хоста для виявлення дрейфу (навіть простий diff краще за нічого).
  4. Визначте політику ретеншну та контроль доступу; бандли містять чутливі операційні дані навіть після редагування.

FAQ

1) Чи треба запускати це як root?

Так, якщо хочете корисний звіт. Root дає доступ до журналів ядра, здоров’я SMART/NVMe і деталей стеку сховища.
Якщо не можете запустити як root — все одно запустіть, але очікуйте відсутності даних і зафіксуйте це в тікеті інциденту.

2) Чи вплине збір даних на продуктивність?

Трохи. Команди типу lspci, lsblk, journalctl запити і читання SMART зазвичай мають низький вплив.
Уникайте важких команд (бенчмарки, довгі SMART-тести) за замовчуванням. Якщо потрібне активне тестування — робіть це в планованому вікні.

3) Чому не відправити все в лог-платформу і все?

Централізовані логи — чудово, поки ні. Support bundle захоплює «локальну правду», включно з ідентифікацією апаратури, мапою драйверів і топологією сховища,
яких часто немає в централізованому пайплайні логів. До того ж під час аварій лог-пайплайн може бути першим, хто впаде.

4) Навіщо включати і dmesg, і journalctl?

Бо середовища різні. Деякі системи обмежують dmesg для non-root, деякі агресивно ротають журнали, і іноді потрібні обидва погляди.
Journal додає метадані завантаження; dmesg показує kernel ring buffer просто. Резерв — це фіча, а не мотлох.

5) Як порівняти два бандли?

Розпакуйте їх і зробіть diff ключових файлів: identity/uname.txt, hardware/lspci-nnk.txt, drivers/lsmod.txt,
storage/lsblk.txt, статус RAID/ZFS та журнали помилок. Не починайте з повних логів; захлинетесь.

6) Що з контейнерами та Kubernetes нодами?

Запускайте скрипт на вузлі, а не в контейнері, якщо вам важливі апаратні/драйверні помилки. Контейнери не бачать повного виду ядра.
Для Kubernetes додайте ідентифікацію ноди (версія kubelet, runtime) як опціональне розширення — але тримайте базовий скрипт простим.

7) Що робити, якщо інструменти nvme-cli або smartmontools не встановлені?

Скрипт перевіряє наявність інструментів і пропускає блоки коректно. У продакшені стандартизуйте мінімальний «diagnostics toolset» для образу.
Не змушуйте on-call встановлювати пакети під час аварії, якщо ви не зацікавлені створювати нові проблеми.

8) Як тримати секрети поза звітом?

По-перше: не збирайте чутливі шляхи. По-друге: обмежуйте журнали за часом. По-третє: робіть селективне редагування (як у скрипті).
І нарешті: трактуйте бандл як конфіденційний — зберігайте у безпечних системах і переглядайте перед зовнішньою передачею.

9) Чи можна додати журнали додатку?

Можна, але дисципліновано. Додайте окремий опціональний прапорець (наприклад, --app) і тримайте його вимкненим за замовчуванням.
Логи додатку часто великі і частіше містять дані клієнтів. Базовий system report має залишатися сфокусованим.

10) Який найцінніший файл у бандлі?

Зазвичай errors/dmesg-warn-err.txt. Там апаратура і драйвери визнають, що вони ламаються. Другий за цінністю — hardware/lspci-nnk.txt,
бо він перетворює розпливчасті помилки на конкретний пристрій/драйвер, з яким можна працювати.

Висновок: наступні кроки, які ви справді виконаєте

Повний звіт системи — не магічний артефакт. Це дисциплінований знімок: ідентичність, топологія, здоров’я і помилки —
захоплені безпечно, у формі, яку можна порівнювати і передавати. Скрипт вище — основа. Практика — те, що робить його корисним.

  1. Додайте скрипт в ops-репо і ставтесь до нього як до production-коду: рев’ю, версіювання, тести.
  2. Стандартизуйте набір діагностичних інструментів на образах, щоб скрипт послідовно міг збирати NVMe/SMART і деталі сховища.
  3. Зробіть «збір бандла» кроком нуль у ваших runbooks інцидентів, до налаштувань, перезапусків чи звинувачень.
  4. Почніть зберігати щотижневі знімки для критичних систем. Вам це не сподобається — поки не врятує день.
  5. Використовуйте бандл для підтримки базових ліній: kernel, драйвери, прошивка, налаштування сховища. Дрейф — це інцидент частинами.
← Попередня
Апаратний CPU: пастка оновлення — перевірка реальності BIOS, мікрокоду та VRM
Наступна →
Знаходження та безпечне видалення старих оновлень Windows за допомогою PowerShell

Залишити коментар