dmesg 命令详解与参数实测(Ubuntu 22.04)

dmesg 命令逐参数实测详解:默认读取内核环形缓冲区、-T/-t 时间戳控制、--level 级别过滤、--facility 设施过滤、-H 人类可读、--color 彩色、-s 缓冲大小、-r 原始、-x 解码前缀、-w 跟随模式与 -c/-C 清空说明,含权限受限两形态排障与内核日志三入口对比,全部回显在 Ubuntu 22.04(util-linux 2.37.2)实测通过。

Linux命令Linux系统UbuntuUbuntu 22.04命令行系统信息2026/10/15

dmesg 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 dmesg 的每一个常用参数——默认读取内核环形缓冲区、-T 人类可读时间戳、-t 去时间前缀、--level/-l 级别过滤、--facility/-f 设施过滤、-H 人类可读输出、--color 彩色输出、-s 缓冲区大小、-r 原始输出、-x 设施:级别前缀、-w 跟随模式、-c/-C 清空缓冲区,全部命令与回显已在 Ubuntu 22.04(util-linux 2.37.2)实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • 内核版本:6.8.0-138-generic(uname -r 实测)
  • dmesg 版本:util-linux 2.37.2(dmesg --version 实测)
  • 实测环境一:最小化安装环境,当前用户 uid=0 但运行环境未授予 CAP_SYSLOG 能力,kernel.dmesg_restrict=1,用于实测「权限受限」形态
  • 实测环境二:root 全能力环境(具备 CAP_SYSLOG),可完整读取内核环形缓冲区(实测 2798 行)并可写入 /dev/kmsg,用于实测各参数的完整输出
  • 内核环形缓冲区:约 2800 行,覆盖从 [ 0.000000] 起的完整启动日志与运行期事件

二、命令概览

2.1 语法与实测环境准备

dmesg(display message / driver message)用于显示和控制内核环形缓冲区(kernel ring buffer):硬件自检、模块加载、文件系统挂载、OOM 事件等内核消息都会写入这里。核心语法:

  • dmesg [<options>]:不带参数读取全部缓冲区内容;
  • dmesg <过滤参数>:按级别、设施、时间等条件过滤输出。

为让各参数的过滤效果可复现、可观察,先以 root 身份向 /dev/kmsg 写入 6 条演示消息。写入内核缓冲区的优先级数值 = 设施编号 × 8 + 级别编号(设施编号:kern=0、user=1、daemon=3;级别编号:err=3、warning=4、notice=5、info=6、debug=7),因此 <3> 为 kern.err、<27>(3×8+3)为 daemon.err、<30>(3×8+6)为 daemon.info:

$ echo '<3>dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable' > /dev/kmsg

$ echo '<4>dmesg-demo: thermal zone cpu-thermal temperature above threshold' > /dev/kmsg

$ echo '<6>dmesg-demo: eth0 link up at 1000 Mbps full duplex' > /dev/kmsg

$ echo '<7>dmesg-demo: debug probe message for level filtering test' > /dev/kmsg

$ echo '<27>dmesg-demo: simulated udev worker error event' > /dev/kmsg

$ echo '<30>dmesg-demo: simulated scheduler info event' > /dev/kmsg

💡 说明:echo 重定向写入 /dev/kmsg 需要 root 权限。经 /dev/kmsg 写入的消息默认设施为 user 而非 kern(下文 3.5 节用 --facility 参数实测验证了这一行为)。

读一下确认 6 条消息已入缓冲区:

$ dmesg | grep dmesg-demo | head -n 6
[27546.723050] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[27546.723140] dmesg-demo: thermal zone cpu-thermal temperature above threshold
[27546.723160] dmesg-demo: eth0 link up at 1000 Mbps full duplex
[27546.723179] dmesg-demo: debug probe message for level filtering test
[27546.723196] dmesg-demo: simulated udev worker error event
[27546.723215] dmesg-demo: simulated scheduler info event

6 条演示消息全部可读,方括号内是内核启动后经过的秒数(相对时间戳)。下文参数实测都围绕这 6 条消息与缓冲区里的真实内核日志展开。

💡 技术拓展:读取内核日志不止 dmesg 一个入口。三个入口横向对比——

入口数据来源持久性典型场景
dmesg内核环形缓冲区(/dev/kmsg)内存中,重启清空、写满覆盖最旧看启动日志、硬件报错、实时事件
journalctl -ksystemd-journald 收集的内核日志落盘 /var/log/journal/追溯历史(含上一次启动 -b -1)
tail /var/log/kern.logrsyslog 转存的文本文件落盘文本用 grep/文本工具直接检索

后两个入口依赖对应服务:本实验的最小化环境实测 journalctl -k 输出 No journal files were found.、/var/log/kern.log 不存在(rsyslog 未安装),此时 dmesg 是唯一入口。三种入口本文实际以 dmesg 为主线,journal 与 kern.log 的分工详见第五节常见问题。

2.2 --help 全量输出(逐行照抄)

先看 dmesg --help 的完整输出,建立参数全景图(util-linux 2.37.2 实测,逐行照抄):

$ dmesg --help

Usage:
 dmesg [options]

Display or control the kernel ring buffer.

Options:
 -C, --clear                 clear the kernel ring buffer
 -c, --read-clear            read and clear all messages
 -D, --console-off           disable printing messages to console
 -E, --console-on            enable printing messages to console
 -F, --file <file>           use the file instead of the kernel log buffer
 -f, --facility <list>       restrict output to defined facilities
 -H, --human                 human readable output
 -k, --kernel                display kernel messages
 -L, --color[=<when>]        colorize messages (auto, always or never)
                               colors are enabled by default
 -l, --level <list>          restrict output to defined levels
 -n, --console-level <level> set level of messages printed to console
 -P, --nopager               do not pipe output into a pager
 -p, --force-prefix          force timestamp output on each line of multi-line messages
 -r, --raw                   print the raw message buffer
     --noescape              don't escape unprintable character
 -S, --syslog                force to use syslog(2) rather than /dev/kmsg
 -s, --buffer-size <size>    buffer size to query the kernel ring buffer
 -u, --userspace             display userspace messages
 -w, --follow                wait for new messages
 -W, --follow-new            wait and print only new messages
 -x, --decode                decode facility and level to readable string
 -d, --show-delta            show time delta between printed messages
 -e, --reltime               show local time and time delta in readable format
 -T, --ctime                 show human-readable timestamp (may be inaccurate!)
 -t, --notime                don't show any timestamp with messages
     --time-format <format>  show timestamp using the given format:
                               [delta|reltime|ctime|notime|iso]
Suspending/resume will make ctime and iso timestamps inaccurate.
     --since <time>          display the lines since the specified time
     --until <time>          display the lines until the specified time

 -h, --help                  display this help
 -V, --version               display version

Supported log facilities:
    kern - kernel messages
    user - random user-level messages
    mail - mail system
  daemon - system daemons
    auth - security/authorization messages
  syslog - messages generated internally by syslogd
     lpr - line printer subsystem
    news - network news subsystem

Supported log levels (priorities):
   emerg - system is unusable
   alert - action must be taken immediately
    crit - critical conditions
     err - error conditions
    warn - warning conditions
  notice - normal but significant condition
    info - informational
   debug - debug-level messages

For more details see dmesg(1).

从 --help 可以看出:dmesg 的参数分为「输出内容控制」(-k/-u/-r/-x)、「过滤」(-l/--level、-f/--facility、--since/--until)、「时间格式」(-T/-t/-e/-d/--time-format)、「输出形态」(-H/-L/-P)、「缓冲区与控制台控制」(-s/-C/-c/-D/-E/-n)几组。帮助输出还列出了全部 8 种设施(facilities)与 8 个级别(levels)——这两个清单正是过滤参数 --facility 与 --level 的合法取值。

2.3 版本信息

$ dmesg --version
dmesg from util-linux 2.37.2

Ubuntu 22.04 仓库中的 dmesg 由 util-linux 2.37.2 提供(util-linux 是 Linux 基础工具集,dmesg 属于它的组成部分)。

三、参数逐项实测

本章在 root 全能力环境逐个实测参数。除特别说明外,示例都基于 2.1 节注入的 6 条演示消息与缓冲区中已有的真实内核日志。

3.1 无参数:读取全部内核环形缓冲区

不带参数时 dmesg 输出缓冲区中全部消息,每行前置相对时间戳(内核启动后秒数)。先用 wc -l 看总量,再取开头 8 行:

$ dmesg | wc -l
2798

$ dmesg | head -n 8
[    0.000000] Linux version 6.8.0-138-generic (buildd@lcy02-amd64-008) (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04.3) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #138~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug  7 13:43:15 UTC  (Ubuntu 6.8.0-138.138~22.04.1-generic 6.8.12)
[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-6.8.0-138-generic root=UUID=43e68207-7df4-4f66-933a-8a595cdde8c8 ro quiet splash
[    0.000000] KERNEL supported cpus:
[    0.000000]   Intel GenuineIntel
[    0.000000]   AMD AuthenticAMD
[    0.000000]   Hygon HygonGenuine
[    0.000000]   Centaur CentaurHauls
[    0.000000]   zhaoxin   Shanghai

💡 要点:dmesg | wc -l 的 2798 行不是固定值——内核日志是「活」的,每有新事件写入行数就增长(本文多次实测中该值在 2781→2801 之间浮动)。第一行永远从 [ 0.000000] 内核版本信息开始,这是判断缓冲区是否完整(未被清空/覆盖)的标志。

3.2 -T(--ctime):人类可读时间戳

默认的相对秒数对排障不直观,-T 把时间戳换算成本地墙上时间:

$ dmesg -T | grep dmesg-demo | head -n 6
[Thu Oct 15 13:55:40 2026] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[Thu Oct 15 13:55:40 2026] dmesg-demo: thermal zone cpu-thermal temperature above threshold
[Thu Oct 15 13:55:40 2026] dmesg-demo: eth0 link up at 1000 Mbps full duplex
[Thu Oct 15 13:55:40 2026] dmesg-demo: debug probe message for level filtering test
[Thu Oct 15 13:55:40 2026] dmesg-demo: simulated udev worker error event
[Thu Oct 15 13:55:40 2026] dmesg-demo: simulated scheduler info event

6 条演示消息的写入时刻被换算成了 Thu Oct 15 13:55:40 2026 格式的本地时间。

💡 技术拓展:dmesg 的时间戳有多种格式可选——

格式形态示例对应参数
rel(默认)[27546.723050] 内核启动后秒数默认输出
ctime[Thu Oct 15 13:55:40 2026] 墙上时间-T 或 --time-format=ctime
reltime本地时间 + 与上条消息的间隔-e
isoISO-8601 精确时间--time-format=iso
notime不显示时间戳-t 或 --time-format=notime
delta与上条消息的时间差-d

本文示例默认采用 rel 与 -T 两种。注意 --help 原文提示:Suspending/resume will make ctime and iso timestamps inaccurate.——系统休眠恢复后 ctime/iso 时间会失准,需要精确时间溯源时应以 journalctl -k 为准。

3.3 -t(--notime):不带时间前缀

-t 去掉每行开头的时间戳,适合把内核消息纯文本化后做 diff 或二次加工:

$ dmesg -t | grep dmesg-demo | head -n 6
dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
dmesg-demo: thermal zone cpu-thermal temperature above threshold
dmesg-demo: eth0 link up at 1000 Mbps full duplex
dmesg-demo: debug probe message for level filtering test
dmesg-demo: simulated udev worker error event
dmesg-demo: simulated scheduler info event

💡 要点:与 --time-format=notime 等价。去掉时间前缀后配合 sort -u 可以快速得到「出现过哪些内核消息」的去重清单。

3.4 --level / -l:按级别过滤

--level(短格式 -l)只输出指定级别的消息,级别名就是 2.2 节 --help 列出的 8 个:emerg、alert、crit、err、warn、notice、info、debug,逗号分隔可传多个。先看 err+warn 的前 6 行(缓冲区里的真实内核告警):

$ dmesg --level=err,warn | head -n 6
[    0.936438] core: CPUID marked event: 'cpu cycles' unavailable
[    0.936446] core: CPUID marked event: 'instructions' unavailable
[    0.936454] core: CPUID marked event: 'bus cycles' unavailable
[    0.936462] core: CPUID marked event: 'cache references' unavailable
[    0.936470] core: CPUID marked event: 'cache misses' unavailable
[    0.936477] core: CPUID marked event: 'branch misses' unavailable

再看最近 3 条 err/warn(含注入的演示消息):

$ dmesg --level=err,warn | tail -n 3
[27877.135633] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[27877.135744] dmesg-demo: thermal zone cpu-thermal temperature above threshold
[27877.135866] dmesg-demo: simulated udev worker error event

注入的 <3>(err)与 <4>(warn)消息被精确捕获,而 <6>(info)、<7>(debug)、<30>(daemon.info)都被过滤掉了。统计一下 err+warn 总量:

$ dmesg -l err,warn | wc -l
52

💡 要点:-l 与 --level 完全同义。52 条中既有系统真实的启动期告警(如 CPUID 性能事件不可用),也包含注入的演示消息;排障时 dmesg -l err,warn 是「先看有没有报错」的第一快查命令。级别列表还支持区间写法(如 dmesg -l emerg..err 表示 emerg 到 err 的所有级别)。

3.5 --facility / -f:按设施过滤

--facility(短格式 -f)按消息来源设施过滤,合法取值同样是 --help 列出的 8 种。daemon 设施的前 5 行(systemd 进程的内核侧消息):

$ dmesg --facility=daemon | head -n 5
[   23.113138] systemd[1]: Inserted module 'autofs4'
[   23.413930] systemd[1]: systemd 249.11-0ubuntu3.22 running in system mode (+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
[   23.414145] systemd[1]: Detected virtualization vmware.
[   23.414181] systemd[1]: Detected architecture x86-64.
[   23.415091] systemd[1]: Hostname set to <ops>.

用 kern 设施过滤演示消息,结果为空;换 user 设施则能读到:

$ dmesg --facility=kern | grep dmesg-demo

$ dmesg --facility=user | grep dmesg-demo | head -n 4
[27546.723050] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[27546.723140] dmesg-demo: thermal zone cpu-thermal temperature above threshold
[27546.723160] dmesg-demo: eth0 link up at 1000 Mbps full duplex
[27546.723179] dmesg-demo: debug probe message for level filtering test

💡 要点:两条命令的对比实证了 2.1 节的说明——经 /dev/kmsg 用 echo 写入的消息默认设施是 user,所以 --facility=kern 匹配不到任何演示消息(空输出正是设施过滤生效的证明),而 --facility=user 能读到。内核自身产生的硬件/驱动日志才是 kern 设施。

3.6 -H(--human):人类可读输出

-H 开启人类可读模式:时间戳按「小时分组 + 相对增量」显示,同小时内的消息只显示与上一条的间隔:

$ dmesg -H | grep dmesg-demo | head -n 8
[Oct15 13:55] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[  +0.000090] dmesg-demo: thermal zone cpu-thermal temperature above threshold
[  +0.000020] dmesg-demo: eth0 link up at 1000 Mbps full duplex
[  +0.000019] dmesg-demo: debug probe message for level filtering test
[  +0.000017] dmesg-demo: simulated udev worker error event
[  +0.000019] dmesg-demo: simulated scheduler info event
[  +1.166804] dmesg-demo: follow mode message one
[  +1.002014] dmesg-demo: follow mode message two

💡 要点:[Oct15 13:55] 是小时分组头(该小时的第一条消息显示时刻),后续 [ +0.000090] 表示距上一条消息过去了 90 微秒。-H 在终端上还会自动进入分页器(less),管道或重定向时则正常输出;不想进分页器可加 -P(--nopager)。

3.7 --color / -L:彩色输出

--color=always 强制输出 ANSI 颜色码(终端上时间戳绿色、级别关键词按严重度着色)。用 cat -v 把不可见字符显示出来,验证颜色码确实存在:

$ dmesg --color=always | head -n 2 | cat -v
^[[32m[    0.000000] ^[[0mLinux version 6.8.0-138-generic (buildd@lcy02-amd64-008) (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04.3) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #138~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug  7 13:43:15 UTC  (Ubuntu 6.8.0-138.138~22.04.1-generic 6.8.12)
^[[32m[    0.000000] ^[[0m^[[33mCommand line^[[0m: BOOT_IMAGE=/boot/vmlinuz-6.8.0-138-generic root=UUID=43e68207-7df4-4f66-933a-8a595cdde8c8 ro quiet splash

💡 要点:^[[32m(绿色)、^[[33m(黄色)就是 ANSI 转义序列。默认 --color=auto——输出到终端时着色、管道/重定向时自动关闭;写脚本处理输出时用 --color=never 保险,直接看错误时 --color=always 可以让 err 级别红色高亮。-L 与 --color 同义。

3.8 -s(--buffer-size):查询缓冲区大小

-s 指定读取缓冲区时使用的临时缓冲区大小(字节)。这是为旧内核的 syslog(2) 系统调用准备的——旧接口一次只返回调用方提供的缓冲区那么多的数据,太小会截断;新内核经 /dev/kmsg 读取时基本不受影响,输出行数应当一致:

$ dmesg | wc -l
2798

$ dmesg -s 4096 | wc -l
2798

💡 要点:util-linux 的 dmesg 会先探测缓冲区再读取,默认值已足够大;默认与显式 -s 4096 行数一致,说明本机内核走 /dev/kmsg 路径不受该参数影响。只有当内核很老或输出被截断时才需要调大 -s(上限 131072)。

3.9 -r(--raw):原始输出

-r 输出原始消息:每行行首带 <优先级> 数值前缀(= 设施×8+级别),不做任何解码:

$ dmesg -r | head -n 4
<5>[    0.000000] Linux version 6.8.0-138-generic (buildd@lcy02-amd64-008) (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04.3) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #138~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug  7 13:43:15 UTC  (Ubuntu 6.8.0-138.138~22.04.1-generic 6.8.12)
<6>[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-6.8.0-138-generic root=UUID=43e68207-7df4-4f66-933a-8a595cdde8c8 ro quiet splash
<6>[    0.000000] KERNEL supported cpus:
<6>[    0.000000]   Intel GenuineIntel

💡 要点:<5> = kern.notice(0×8+5)、<6> = kern.info,与 2.1 节的优先级公式对应。-r 输出最接近 syslog(2) 协议的原始形态,适合交给日志采集器或其他程序按优先级再处理;人读时用 -x(见 3.10)更直观。

3.10 -x(--decode):facility:level 可读前缀

-x 把每条消息的优先级解码为「设施:级别」前缀:

$ dmesg -x | grep dmesg-demo | head -n 6
user  :err   : [27546.723050] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
user  :warn  : [27546.723140] dmesg-demo: thermal zone cpu-thermal temperature above threshold
user  :info  : [27546.723160] dmesg-demo: eth0 link up at 1000 Mbps full duplex
user  :debug : [27546.723179] dmesg-demo: debug probe message for level filtering test
daemon:err   : [27546.723196] dmesg-demo: simulated udev worker error event
daemon:info  : [27546.723215] dmesg-demo: simulated scheduler info event

💡 要点:user:err 与 daemon:err 直接可读,是验证「这条消息到底是什么设施什么级别」的权威手段——上文 3.5 节的设施归属结论、2.1 节的优先级公式都可用 -x 逐一复核。

3.11 -w(--follow):跟随模式

-w(--follow)读取完现有缓冲区后不退出,持续等待并打印新消息(类似 tail -f)。为能观察到效果,先注入 2 条新消息,再用 timeout 包裹 dmesg 运行 4 秒:

$ echo '<5>dmesg-demo: follow mode message one' > /dev/kmsg
$ echo '<3>dmesg-demo: follow mode message two' > /dev/kmsg

$ timeout 4 dmesg -w --time-format=reltime | tail -n 4
[  +0.000046] dmesg-demo: simulated udev worker error event
[  +0.000046] dmesg-demo: simulated scheduler info event
[  +1.195778] dmesg-demo: follow mode message one
[  +1.002237] dmesg-demo: follow mode message two

💡 要点:dmesg -w 会先把现有缓冲区全部打出来再跟随,上面用 tail -n 4 只留了末尾——最后两行正是注入后被实时捕获的 follow mode message one/two,时间增量约 1 秒,与注入节奏吻合。只想看「开始跟随之后」的新消息用 -W(--follow-new)。生产上用它实时盯 USB 插拔、磁盘报错非常顺手,退出按 Ctrl+C。

3.12 -c / -C:清空内核环形缓冲区

两个清空参数的标准形态:

dmesg -c          # 读取全部消息后清空缓冲区(读后清)
dmesg -C          # 直接清空缓冲区(不读取)
dmesg | wc -l     # 验证:清空后应输出 0

⚠️ 注意:清空操作需要 root(CAP_SYSLOG)权限,且不可恢复——缓冲区在内存里,清掉的日志无法找回,执行前务必先留存快照(dmesg -T > /var/log/dmesg-backup.log,见 4.4)。本实验环境是常驻系统,清空会丢掉既有未落盘的内核日志、影响其他排障工作,因此本节仅给出标准命令形态与验证方法(dmesg | wc -l 应为 0),未实际执行。日常排障建议优先用 4.4 节的快照方式留档,而不是频繁清空。

四、实战示例

4.1 开机后硬件健康巡检

目标:确认启动期有没有报错,并把最近的错误带上可读时间。-T --level=err 组合输出「最近 3 条 err 级别消息 + 墙上时间」:

$ dmesg -T --level=err | tail -n 3
[Thu Oct 15 14:01:11 2026] dmesg-demo: simulated nvme0n1 I/O error, sector 2048 not readable
[Thu Oct 15 14:01:11 2026] dmesg-demo: simulated udev worker error event
[Thu Oct 15 14:01:13 2026] dmesg-demo: follow mode message two

真实巡检中如果这里出现 I/O error、ECC、thermal 相关字样,就该进一步查磁盘/内存/散热;演示消息只是为了让回显可复现。

4.2 设备事件入账验证

目标:模拟一条设备插入事件,确认它进入内核缓冲区并可被检索。写入一条 USB 枚举消息后立即查看最后 1 行:

$ echo '<6>dmesg-demo: usb 1-1: new high-speed USB device number 5 attached' > /dev/kmsg

$ dmesg -T | tail -n 1
[Thu Oct 15 14:01:15 2026] dmesg-demo: usb 1-1: new high-speed USB device number 5 attached

写入即生效(实时性验证)。真实场景中插上 USB 设备后,用同样的 dmesg -T | tail -n 5 就能看到内核为新设备分配的端口号与厂商信息。

4.3 按设备名检索内核日志

目标:只看磁盘相关消息。用扩展正则匹配 sdX/nvme 设备名:

$ dmesg | grep -E 'sd[a-z]|nvme' | head -n 4
[   10.364213] sd 2:0:0:0: [sda] 1677721600 512-byte logical blocks: (859 GB/800 GiB)
[   10.364647] sd 2:0:0:0: [sda] Write Protect is off
[   10.364660] sd 2:0:0:0: [sda] Mode Sense: 61 00 00 00
[   10.365007] sd 2:0:0:0: [sda] Cache data unavailable

💡 要点:内核对磁盘的命名([sda])与 SCSI 通道号(sd 2:0:0:0)都在消息里,配合 grep -E 是不装任何额外工具时最快的磁盘排障入口。

4.4 保存内核日志快照

目标:把当前缓冲区带时间戳落盘,用于故障复盘或清空前备份:

$ dmesg -T > /var/log/dmesg-snapshot.log; wc -l /var/log/dmesg-snapshot.log
2801 /var/log/dmesg-snapshot.log

$ tail -n 2 /var/log/dmesg-snapshot.log
[Thu Oct 15 14:01:13 2026] dmesg-demo: follow mode message two
[Thu Oct 15 14:01:15 2026] dmesg-demo: usb 1-1: new high-speed USB device number 5 attached

2801 行全量快照已保存,末尾正是 4.1/4.2 节注入的消息,落盘内容与缓冲区一致。

4.5 设施 + 级别 + 时间戳组合输出

目标:把过滤条件叠加——只要 user 设施的 err 级别、带可读时间、带设施:级别前缀:

$ dmesg -xT | grep dmesg-demo | tail -n 2
user  :err   : [Thu Oct 15 14:01:13 2026] dmesg-demo: follow mode message two
user  :info  : [Thu Oct 15 14:01:15 2026] dmesg-demo: usb 1-1: new high-speed USB device number 5 attached

-xT(解码前缀 + 墙上时间)再叠加 --level/--facility 即可精确圈定,如 dmesg -xT -l err --facility=user。参数之间全部可叠加,按「内容过滤(-l/-f)→ 时间格式(-T/-t/-e)→ 输出形态(-x/-H/--color)」三步组合即可覆盖绝大多数排障诉求。

五、注意事项与常见问题

Q1:dmesg: read kernel buffer failed: Operation not permitted 是怎么回事? 这是最常见的报错,有两种典型形态。形态一:kernel.dmesg_restrict=1 时,非特权用户读取被内核拒绝。先确认开关:

$ sysctl kernel.dmesg_restrict
kernel.dmesg_restrict = 1

形态二:即使是 uid=0 的 root,若运行环境未授予 CAP_SYSLOG 能力(本实验的最小化环境即如此),读缓冲区同样失败:

$ id -u
0

$ dmesg; echo rc=$?
dmesg: read kernel buffer failed: Operation not permitted
rc=1

用管道接其他命令时退出码会被掩盖(返回的是管道最后一个命令的退出码):

$ dmesg | tail -n 3; echo rc=$?
dmesg: read kernel buffer failed: Operation not permitted
rc=0

Q2:如何放开 dmesg 读取权限? 两条路:其一,具备 CAP_SYSLOG 的 root 账户(服务器上默认的 root 即是)不受 dmesg_restrict 限制——本文实测环境二在 kernel.dmesg_restrict=1 的情况下依然完整读到了 2798 行,所以普通用户加 sudo 运行即可;其二,放开 sysctl 开关让所有本地用户可读(标准形态,改完即生效):sudo sysctl -w kernel.dmesg_restrict=0;要开机持久生效则写入 /etc/sysctl.d/99-dmesg.conf(内容为 kernel.dmesg_restrict = 0 一行)后执行 sudo sysctl --system。

⚠️ 注意:内核日志包含物理地址、内核指针等信息,dmesg_restrict=1 是防信息泄露的安全加固项(配合 KASLR 生效)。多用户生产服务器建议保持默认的 1,需要看日志的账号走 sudo dmesg 按需读取,而不是全局放开。

Q3:为什么 dmesg 明明失败了,脚本的退出码却是 0? 见 Q1 第三段实测:管道中 dmesg 的失败退出码(1)被 tail 的 0 覆盖。排障脚本要么先单独执行 dmesg 判断退出码,要么把 dmesg 写入临时文件再处理,不要依赖管道末端的退出码。

Q4:-T 显示的时间可靠吗? 基本可靠但有已知盲区:--help 原文明确提示 Suspending/resume will make ctime and iso timestamps inaccurate.——系统休眠/恢复后,ctime 与 iso 格式的时间会失准,因为换算基于「内核单调时钟 + 本次开机时刻」。需要严格可信的时间线时用 journalctl -k(journald 在事件发生时即刻记录时间)。

Q5:dmesg 的日志会丢吗? 会。内核环形缓冲区是固定大小的内存环形队列:写满后新消息覆盖最旧消息;系统重启后缓冲区清零。所以 dmesg 只适合看「当前这次开机以来」的事件,历史追溯要用持久化设施——启用并使用 journalctl -k -b(本次开机)/journalctl -k -b -1(上次开机),或安装 rsyslog 让内核日志持续转存到 /var/log/kern.log。重要现场的缓冲区内容应尽快用 4.4 节的快照方式落盘。

Q6:journalctl -k 提示 "No journal files were found." 是什么情况? 本实验最小化环境的实测输出:

$ journalctl -k; echo rc=$?
No journal files were found.
-- No entries --
rc=0

含义是 journald 没有可读的日志文件(服务未持久化或当前用户不在可读组)。此时内核日志只能靠 dmesg 读实时缓冲区;要启用 journald 持久化,标准做法是创建 /var/log/journal 目录并重启 systemd-journald 服务,之后 journalctl -k 即可读到历史内核日志。另外 /var/log/kern.log 依赖 rsyslog 转存,本实验环境中该文件同样不存在:

$ ls -l /var/log/kern.log
ls: cannot access '/var/log/kern.log': No such file or directory

装好并启动 rsyslog 后该文件才会生成。

六、参考链接