When a USB stick never mounts, a disk starts throwing I/O errors, or the machine OOMs under load, the answer often lives in the kernel ring buffer — not in your application logs. That is what dmesg is for. It prints (and can follow) the messages the kernel and drivers have been writing since boot.
You do not need every flag on day one. Start with a plain dump, then layer on timestamps, level filters, and live follow as the problem gets noisier. The sections below walk through the commands you will reach for most often — with enough context that each one feels intentional, not magical.
Warm-up: peek at the buffer
Unlike file-based tools, there is no sample log to create — your playground is the live ring buffer on the machine in front of you. Start by printing everything, then trim to the end so you are not scrolling through a full boot history.
Dump the buffer:
dmesg
Most of the time you only care about the newest lines. Pipe to tail for a quick recent snapshot:
dmesg | tail -n 20
Typical output looks something like this (your lines will differ — hardware, drivers, and uptime all change the story):
[12345.678901] usb 1-2: new high-speed USB device number 5 using xhci_hcd
[12345.790123] usb 1-2: New USB device found, idVendor=0781, idProduct=5567
[12346.012345] scsi host2: usb-storage 1-2:1.0
[12346.234567] sd 2:0:0:0: [sdb] Attached SCSI removable disk
When the dump is long, page through it with less so you can search and scroll without flooding the terminal:
dmesg | less
Note: On many modern distros, unprivileged users cannot read the ring buffer. If you see Operation not permitted or an empty result that feels wrong, retry with sudo dmesg. The permissions section below explains why.
Readable timestamps
By default, dmesg prefixes each line with seconds since boot inside brackets. That is precise for ordering, but awkward when you are correlating with wall-clock logs from an app or journal.
Print timestamps as local wall-clock time with -T:
dmesg -T | tail -n 5
You should see human dates instead of [12345.67…]:
[Wed Aug 5 00:10:12 2026] usb 1-2: new high-speed USB device number 5 using xhci_hcd
[Wed Aug 5 00:10:12 2026] usb 1-2: New USB device found, idVendor=0781, idProduct=5567
For interactive reading, -H (human) enables a friendly format and often pairs well with a pager. Many people use it as their default “open the buffer and browse” command:
dmesg -H
Note: Reach for -T when you need to align a kernel event with an application timestamp. Stay with the default boot-relative clock when you only care about the order of events after boot.
Filter by facility and level
A full dmesg dump mixes informational driver chatter with real faults. Level and facility filters cut the noise before you start grepping.
Restrict to warning and above with -l (level). Names like warn, err, and crit are easier to remember than numeric priorities:
dmesg -l warn
To include a range, use a comma-separated list. This keeps errors and critical lines while dropping routine info:
dmesg -l err,crit,alert,emerg
Facility filters with -f narrow by subsystem when you already know the neighborhood (kernel, user, daemon, and so on):
dmesg -f kern -l err
Note: When you are still exploring, prefer a broad dump plus grep. When you already know “something is broken at error severity,” start with -l err so the signal is not buried in boot spam.
Color and decode
Raw lines are dense. Two flags make triage easier on the eyes and in pipelines.
Enable color so levels stand out in a terminal that supports it:
dmesg --color=always | less -R
Add -x to decode facility and priority into readable prefixes on each line. That makes it obvious whether you are looking at a kernel warning or something else:
dmesg -x | tail -n 10
Sample shape (exact text varies by util-linux version):
kern :info : [12345.678901] usb 1-2: new high-speed USB device number 5 using xhci_hcd
kern :warn : [12350.111222] usb 1-3: device descriptor read/64, error -71
Note: Combine -x with grep when you want both the decoded level and a keyword match — for example, keep only lines that mention usb after decoding.
Hunt common failures with pipes
dmesg dumps the buffer; grep answers “did this failure appear?” Stack them the way you would any log. Case-insensitive searches catch mixed driver wording.
USB not mounting or disconnecting oddly:
dmesg -T | grep -i usb
Out-of-memory kills when a process vanishes under pressure:
dmesg -T | grep -i -E 'out of memory|oom-kill|killed process'
Disk and filesystem trouble — I/O errors, reset links, unclean buffers:
dmesg -T | grep -i -E 'i/o error|ext4|xfs|nvme|ata|blk_update_request'
Firmware or ACPI complaints during boot:
dmesg -T | grep -i -E 'firmware|acpi|failed'
Note: Kernel messages are not a stable API — wording shifts across versions. Prefer short distinctive tokens (oom-kill, I/O error, a device name like sdb) over long phrases you saw on one machine.
Watch live
Some faults only appear while you reproduce them: plug in a cable, load a module, stress a disk. Follow mode prints new ring-buffer lines as they arrive.
Watch the kernel in real time:
dmesg -w
Equivalently:
dmesg --follow
Leave that running in one terminal, then plug the USB device or run the workload in another. New messages appear as the kernel emits them. Stop with Ctrl+C when you have enough signal.
Note: Follow still respects permissions. If a plain dmesg needs sudo, so does dmesg -w.
Clear the buffer — and know its limits
The ring buffer is fixed-size. When it fills, older lines wrap away. Clearing is useful before a controlled reproduction so you only see fresh messages — but it is a privileged operation and destroys history.
Clear without printing (requires root):
sudo dmesg -C
Read and clear in one step with -c (also needs privilege on most systems):
sudo dmesg -c
Because the buffer wraps, a machine that has been up for weeks may no longer hold early boot lines. On systemd systems, persistent kernel messages live in the journal. For a quick companion check without leaving the CLI:
journalctl -k -b --no-pager | tail -n 20
Note: Prefer journalctl -k when you need history across reboots or after the ring buffer has wrapped. Prefer dmesg when you want the live buffer, follow mode, or util-linux’s level and facility filters.
Permissions: when dmesg says no
Many distributions set kernel.dmesg_restrict so only privileged users can read the ring buffer. That is a deliberate hardening choice: kernel logs can leak addresses and hardware details.
If you see a permission error, re-run with elevated rights:
sudo dmesg -T | tail -n 20
To check whether the restrict knob is enabled:
sysctl kernel.dmesg_restrict
A value of 1 means unprivileged dmesg is blocked; 0 means it is open. Changing that sysctl is an admin policy decision — for day-to-day debugging, sudo is the straightforward path.
Note: Scripts that scrape dmesg on locked-down hosts need either root or an alternate source such as journalctl -k with appropriate journal ACLs.
Quick reference card
Keep this nearby until the flags become muscle memory:
| Goal | Command |
|---|---|
| Full dump | dmesg |
| Recent lines | dmesg | tail -n 20 |
| Wall-clock time | dmesg -T |
| Human / browse | dmesg -H |
| Warnings+ | dmesg -l warn |
| Errors only | dmesg -l err |
| Decode facility/level | dmesg -x |
| Color | dmesg --color=always |
| Follow live | dmesg -w |
| Clear buffer | sudo dmesg -C |
| USB hunt | dmesg -T | grep -i usb |
| OOM hunt | dmesg -T | grep -i oom |
| Persistent kernel log | journalctl -k -b |
Practice drills
Use your own machine’s ring buffer (with sudo if needed) and try these without peeking. The point is to choose the flag with intent, not to memorize syntax under pressure.
- Print the last 15 kernel messages with wall-clock timestamps.
- Show only error-level (and more severe) messages, with facility/priority decoded.
- Search the buffer for USB-related lines from the last few minutes of activity.
- Start a live follow, then plug or unplug a USB device and confirm new lines appear.
- Write a one-liner that exits non-zero when the ring buffer contains an OOM-related message.
When you are ready to compare, here are solid answers — not the only ones, but clear and portable:
dmesg -T | tail -n 15
dmesg -x -l err,crit,alert,emerg
dmesg -T | grep -i usb
dmesg -w
dmesg | grep -qi -E 'out of memory|oom-kill|killed process'; echo $?
If you can work through those five comfortably, you already cover most real dmesg work: boot and driver triage, hardware hunts, live reproduction, and a quick scripted check. Start with a plain dump, then tighten with timestamps, levels, and grep only when the first pass gets noisy.