Когда система зависает, диск отваливается или после обновления ядра пропадает звук, первым делом смотрят в сообщения ядра. dmesg и журнал systemd хранят следы сбоя, но обилие строк и незнакомые термины отпугивают. Разберём, как читать эти сообщения, что означает kernel oops и какие данные собрать, чтобы понять причину.
Откуда берутся сообщения ядра
Ядро пишет диагностику в кольцевой буфер через printk. У каждой строки есть уровень важности от 0 (emerg) до 7 (debug), время в секундах с момента загрузки и имя подсистемы. Буфер ограничен, старые записи вытесняются; размер задаётся параметром log_buf_len. systemd-journald дополнительно забирает сообщения из /dev/kmsg и хранит их в журнале, поэтому после перезагрузки история обычно доступна.
На консоль попадают не все строки: порог задаёт параметр loglevel и файл /proc/sys/kernel/printk. Значение 4 означает, что в терминал выводятся только ошибки и выше, хотя в буфер по-прежнему пишется всё. Поэтому отсутствие сообщения на экране не значит, что его нет в dmesg.
Базовые команды
Утилита dmesg показывает буфер, а флаги делают его читаемым. Без прав root вывод может быть пуст, если включён kernel.dmesg_restrict=1.
sudo dmesg -T -l err,warn
sudo dmesg --since "1 hour ago" --time-format=iso
sudo dmesg -wH
journalctl -k -b -1 --no-pager
Флаг -T переводит секунды в человеческое время, но после смены часов или гибернации метка может смещаться. -w следит за новыми строками, -H добавляет цвета и удобное время. journalctl -k показывает только сообщения ядра, -b -1 — предыдущую загрузку.
Уровни важности и фильтры
Уровни помогают отсеять шум: err и warn дают ошибки и предупреждения, crit — критические события. Не игнорируйте строки с ACPI, PCIe, ata и nvme: именно там появляются ранние признаки отказа оборудования.
sudo dmesg -l emerg,alert,crit,err
journalctl -k -p warning --since today
journalctl -k --grep="Out of memory"
Как читать kernel oops
Oops — это неожиданное исключение в коде ядра. Типичная запись начинается с BUG: unable to handle page fault, затем идут причина, режим доступа и адрес. Строка RIP указывает функцию и смещение, Call Trace показывает стек вызовов, а Code — машинные инструкции вокруг сбоя.
BUG: unable to handle page fault for address: 0000000000000018
#PF: supervisor read access in kernel mode
RIP: 0010:example_driver_read+0x1c/0x80 [example_driver]
Call Trace:
__x64_sys_read+0x1a/0x20
do_syscall_64+0x5c/0x90
Tainted: P OE
Смещение после плюса помогает найти строку в исходниках, если известна версия ядра и конфигурация. Tainted перечисляет флаги, влияющие на доверие к отчёту. Если в стеке участвует сторонний модуль, первым подозреваемым становится он.
Флаги tainted
Ядро помечает себя грязным, когда условия отличаются от эталонных. P означает проприетарный модуль, O — модуль вне дерева, E — неподписанный модуль, W — уже было предупреждение, D — ядро погибло после oops, M — аппаратная ошибка. Полный список есть в Documentation/admin-guide/tainted-kernels.rst.
cat /proc/sys/kernel/tainted
sudo dmesg -T -l warn | grep -i tainted
modinfo example_driver | head -20
Числовое значение tainted — битовая маска. Если флаг появился после установки драйвера, начните с его удаления или обновления.
Что делать при oops
- Сохраните полный вывод dmesg и journalctl за текущую и предыдущую загрузку.
- Запишите версию ядра, дистрибутив и список модулей.
- Определите модуль из RIP и Call Trace, проверьте его происхождение.
- Попробуйте воспроизвести сценарий без подозрительного модуля.
- Проверьте память и диск: memtest86+ и smartctl исключают железо.
uname -a
lsmod | sort
sudo smartctl -a /dev/nvme0
sudo memtester 1G 1
Если oops повторяется на штатном ядре без сторонних модулей, это повод для отчёта разработчикам. Приложите полный лог, а не одну строку, и укажите шаги воспроизведения. Проверьте также, не совпадает ли сбой с моментом подключения конкретного устройства или запуска определённой программы.
Аппаратные ошибки
Строки Machine Check Exception, PCIe Bus Error и nvme timeout говорят о железе или прошивке. Для сбора MCE используйте rasdaemon, для PCIe — вывод lspci -vv и строки AER в журнале. Ошибки nvme часто сопровождаются сбросом контроллера.
sudo ras-mc-ctl --summary
sudo lspci -vv | grep -A5 "Advanced Error"
sudo nvme smart-log /dev/nvme0
sudo dmesg -T | grep -iE "mce|aer|nvme|ata error"
Не игнорируйте единичные corrected-ошибки: их рост предшествует отказу. Сохраните SMART-атрибуты и сравните через неделю. Полезно разделить события по времени: если ошибка появляется только под нагрузкой, проверяйте питание и охлаждение; если сразу после старта — прошивку и совместимость. Единичный сбой после обновления ядра чаще связан с драйвером, а серия одинаковых адресов указывает на память.
Записывайте, что менялось перед сбоем: ядро, модуль, firmware, настройки UEFI. Эта хронология часто важнее самого текста oops.
Зависания и нехватка памяти
Soft lockup означает, что процессор слишком долго не отдавал управление; hung task — что задача ждала более hung_task_timeout_secs. OOM killer пишет, какой процесс убит и сколько памяти было доступно. Во всех трёх случаях важен контекст: нагрузка, свободная память, состояние диска.
journalctl -k --grep="soft lockup"
journalctl -k --grep="blocked for more than"
free -h
vmstat 1 5
Сохранение лога после падения
При полном зависании обычный журнал не успевает сохраниться. Помогает pstore: настройте ramoops или EFI-переменные, и ядро сохранит хвост лога в /sys/fs/pstore. Для серьёзной диагностики настраивают kdump: резервируют память параметром crashkernel и загружают второе ядро, которое снимает дамп через /proc/vmcore.
ls -l /sys/fs/pstore
cat /proc/cmdline
sudo sysctl kernel.panic_on_oops=1
sudo sysctl kernel.panic=10
panic_on_oops полезен на серверах с kdump: система сразу перезагружается и сохраняет дамп, вместо того чтобы работать в неопределённом состоянии. На рабочей машине это может быть неудобно.
Чек-лист сбора данных
- полный dmesg текущей загрузки и journalctl -k -b -1;
- версия ядра, дистрибутив, список модулей;
- флаги tainted и подозрительный модуль;
- вывод smartctl и результаты теста памяти;
- шаги воспроизведения и время сбоя;
- наличие pstore или kdump-дампа.
Итог
dmesg — не страшный поток текста, а структурированный отчёт: уровень, подсистема, функция, стек. Научитесь находить RIP, Call Trace и tainted, отделяйте программную ошибку от аппаратной и всегда сохраняйте полный лог. Это экономит часы догадок и делает разговор с разработчиками предметным, а не эмоциональным.