Stop Losing Full Kernel Crash Dumps: Practical kdump and kexec on Linux
When a Linux host panics, you usually get one of three outcomes:
- A short oops snippet in the journal or pstore
- A userspace core from a crashed daemon
- A reboot and no useful memory image
The third case is the expensive one. Full kernel crash dumps exist for a reason: kdump boots a small capture kernel via kexec, preserves the panicked kernel’s memory, and writes it out as /proc/vmcore so you can keep a filtered vmcore for later analysis.
This is not a replacement for systemd-pstore or systemd-coredump. Those tools answer different questions. kdump is what you want when you need a real memory image of the crashed kernel.
What kdump actually does
From the kernel’s kdump documentation:
- At normal boot, the production kernel reserves memory with
crashkernel=... - Userspace loads a dump-capture kernel into that reserved region with
kexec -p - On panic (or SysRq crash), the machine jumps into the capture kernel without a full firmware reboot
- The capture kernel exposes the old memory image as
/proc/vmcore - Tools like
cp,scp, ormakedumpfilewrite the dump to disk or over the network - The host reboots back into the normal kernel
That design matters. Dumping from a freshly booted capture kernel is far more reliable than trying to write files from a kernel that already panicked.
Where this sits next to pstore and coredump
Use the right tool for the evidence you need:
| Layer | Tool | What you get | Typical size |
|---|---|---|---|
| Userspace crash |
systemd-coredump / coredumpctl
|
Process core + journal metadata | MB–GB per process |
| Kernel oops/panic breadcrumbs | pstore + systemd-pstore
|
dmesg/oops fragments that survive reboot | KB–low MB |
| Full kernel memory image | kdump / kexec | Filtered or full vmcore
|
Hundreds of MB–many GB |
If you only need “what was the last kernel message?”, pstore is enough.
If you need “why did the kernel die, and what was in memory?”, you want kdump.
Prerequisites
You need:
- A kernel built with kexec + crash dump support (
CONFIG_KEXEC/CONFIG_KEXEC_FILE,CONFIG_CRASH_DUMP,CONFIG_PROC_VMCORE) - Reserved crash memory via
crashkernel= - Userspace packaging:
-
Debian/Ubuntu:
kdump-tools,kexec-tools,makedumpfile -
Fedora/RHEL-family:
kexec-tools(provideskdumpctl/kdump.service), optionallycrash+ matchingkernel-debuginfofor analysis
-
Debian/Ubuntu:
- Disk space under
/var/crash(or a remote NFS/SSH target) - A maintenance window for one reboot after setting
crashkernel=
Most distribution kernels already ship the needed config options. The missing pieces are usually reserved memory and the dump service.
Path A: Debian / Ubuntu with kdump-tools
1. Install packages
sudo apt update
sudo apt install kdump-tools kexec-tools makedumpfile
On Debian/Ubuntu, the main config file is:
/etc/default/kdump-tools
2. Enable kdump-tools
Edit /etc/default/kdump-tools and set:
USE_KDUMP=1
Useful defaults from the package man page:
# Where dumps land (default if unset)
KDUMP_COREDIR="/var/crash"
# makedumpfile args (package default if unset)
# -c compress, -d 31 keep only useful kernel pages
MAKEDUMP_ARGS="-c -d 31"
# Keep only N local dumps after a successful capture
KDUMP_NUM_DUMPS=5
# Also save dmesg content from the panicked kernel
KDUMP_DUMP_DMESG=1
MAKEDUMP_ARGS="-c -d 31" is the practical default on Debian-family systems. Dump level 31 excludes zero pages, cache pages, user pages, and free pages, leaving the kernel-relevant content that crash analysis usually needs.
3. Reserve crashkernel memory
kdump cannot work without reserved memory. Add a crashkernel= argument to the bootloader.
On GRUB systems:
sudo sed -n 's/^GRUB_CMDLINE_LINUX_DEFAULT=//p' /etc/default/grub
Add something like:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash crashkernel=256M"
Then:
sudo update-grub
sudo reboot
Sizing notes from upstream and distro docs:
- Simple fixed reserve:
crashkernel=256Morcrashkernel=512M - Auto placement:
crashkernel=256M(omit@offsetunless you know you need it) - RAM-dependent syntax from the kernel docs:
crashkernel=512M-2G:64M,2G-:128M
That means:
- under 512M RAM: reserve nothing
- 512M–2G: reserve 64M
- 2G and above: reserve 128M
For modern servers with lots of drivers/modules in the capture path, start higher than the absolute minimum. Many operators begin around 256M–512M on x86_64 and raise it if load/capture fails.
After reboot, confirm the cmdline:
cat /proc/cmdline
# expect crashkernel=...
4. Load and verify the capture kernel
sudo kdump-config show
sudo kdump-config test
sudo kdump-config status
sudo kdump-config load
sudo kdump-config status
What these do:
-
show— current parameters and last saved kexec command -
test— compute load parameters without loading -
status— check/sys/kernel/kexec_crash_loaded -
load— actually load the dump-capture kernel with kexec
A healthy loaded state looks like:
cat /sys/kernel/kexec_crash_loaded
# 1
If the sysfs file is missing, the running kernel was built without crash dump support or booted without a usable crashkernel= reservation.
5. Optional remote dump targets
Still in /etc/default/kdump-tools, choose one of SSH or NFS (not both):
# SSH example
SSH="kdump@crash-collector.example.net"
SSH_KEY="/root/.ssh/kdump_id_rsa"
# or NFS example
# NFS="crash-collector.example.net:/var/crash"
For SSH key distribution:
sudo kdump-config propagate
That pushes the public key so the capture path can write without an interactive password.
6. Sysctl panic triggers worth enabling
kdump-tools already leans toward collecting dumps on oops. For production hosts, also decide whether OOM and NMI should panic:
# /etc/sysctl.d/99-kdump-triggers.conf
kernel.panic_on_oops = 1
vm.panic_on_oom = 1
kernel.hardlockup_panic = 1
kernel.softlockup_panic = 1
kernel.panic = 60
Apply:
sudo sysctl --system
kernel.panic = 60 reboots sixty seconds after panic if dump capture does not complete cleanly. Tune to your recovery model.
kdump-specific sysctl overrides for the capture environment live in:
/etc/kdump/sysctl.conf
Keep hugepage overrides there unless you have a measured reason to remove them. Capture kernels are memory-constrained.
Path B: Fedora / RHEL-family with kexec-tools
1. Install and enable
sudo dnf install kexec-tools
sudo systemctl enable --now kdump.service
For later analysis on the same machine:
sudo dnf install crash
# plus matching kernel-debuginfo from debuginfo repos when you actually need to inspect a dump
2. Set crashkernel reservation
On current Fedora-style tooling:
sudo kdumpctl reset-crashkernel
sudo reboot
kdumpctl reset-crashkernel writes a range-based reservation into the current kernel’s boot entry. After reboot:
cat /proc/cmdline
systemctl status kdump.service --no-pager
sudo kdumpctl status
3. Configure dump location and filtering
Main config:
/etc/kdump.conf
Common practical settings:
path /var/crash
core_collector makedumpfile -l --message-level 1 -d 31
default reboot
Notes:
-
-d 31is the same “kernel-useful pages only” filter used on Debian -
-lselects LZO compression when built into makedumpfile -
default rebootreturns the host to normal operation after capture
Network targets are also supported in this file (NFS/SSH style destinations). Keep credentials and mount permissions boring and explicit; the capture environment is intentionally minimal.
Make sure the dump will fit
Before you ever trigger a test crash:
df -h /var/crash
sudo mkdir -p /var/crash
sudo chmod 700 /var/crash
Rough planning:
- Unfiltered
vmcorecan approach system RAM size - Filtered dumps with
-d 31are much smaller, but still large on big hosts - Keep retention low (
KDUMP_NUM_DUMPSor external cleanup) - Prefer a dedicated volume or remote collector for fleets
If local disk is tight, remote dump is not optional — it is the design.
Lab verification (safe procedure)
Only do this on a lab host or during a planned window. Triggering kdump will interrupt workloads.
1. Confirm loaded state
Debian/Ubuntu:
sudo kdump-config status
cat /sys/kernel/kexec_crash_loaded
Fedora/RHEL-family:
systemctl is-active kdump.service
cat /sys/kernel/kexec_crash_loaded
2. Prefer a text console for the test
Framebuffer/GUI consoles can look frozen or corrupted during capture even when kdump is working. Serial console or a plain multi-user text session is easier to interpret.
3. Trigger a controlled crash
# requires SysRq enabled
echo 1 | sudo tee /proc/sys/kernel/sysrq
echo c | sudo tee /proc/sysrq-trigger
Upstream documents the same triggers: ALT-SysRq-c, echo c > /proc/sysrq-trigger, or a panic-inducing test module.
4. After reboot, find the dump
sudo find /var/crash -type f -mtime -1 -ls
Typical layout:
/var/crash/<timestamp>/vmcore
/var/crash/<timestamp>/dmesg # when dmesg capture is enabled
Also check:
sudo ls -lah /var/crash
journalctl -b -1 -u kdump* --no-pager
If there is no dump:
-
crashkernel=missing or too small - capture kernel/initrd not loaded (
kexec_crash_loaded != 1) -
/var/crashfull or not writable from capture environment - remote SSH/NFS path unreachable during capture
- filtering/compression tool failed and fallback also failed
Analyze a vmcore without folklore
Quick dmesg extraction
If you only need the panicked kernel log:
sudo makedumpfile --dump-dmesg /var/crash/<timestamp>/vmcore /tmp/panic.dmesg
less /tmp/panic.dmesg
crash utility (preferred for kdump-compressed dumps)
# vmlinux with debug symbols must match the crashed kernel
crash /usr/lib/debug/boot/vmlinux-$(uname -r) \
/var/crash/<timestamp>/vmcore
Inside crash, start with:
sys
bt
log
ps
kmem -i
quit
Package paths differ by distro:
- Debian/Ubuntu debug kernels often come from
linux-image-$(uname -r)-dbg - Fedora/RHEL-family use
kernel-debuginfo
gdb on ELF dumps
If you generated an ELF dump (makedumpfile -E ...), gdb can do limited inspection:
gdb vmlinux /var/crash/<timestamp>/vmcore
For normal compressed kdump files, use crash, not gdb.
makedumpfile dump levels that matter in practice
From makedumpfile(8), dump level is a bitfield:
| Bit | Excludes |
|---|---|
| 1 | zero pages |
| 2 | non-private cache |
| 4 | all cache |
| 8 | user data pages |
| 16 | free pages |
So:
-
-d 1— tiny reduction, still huge -
-d 31— exclude all of the above (common production default) - fallback patterns like
-d 11,31retry a more aggressive filter if space runs out
Examples:
# local filtered compressed dump
sudo makedumpfile -c -d 31 /proc/vmcore /var/crash/manual/vmcore
# ELF dump for gdb-oriented workflows
sudo makedumpfile -E -d 31 /proc/vmcore /var/crash/manual/vmcore.elf
During a real capture you usually do not run these by hand; the distro dump service runs them. Knowing the flags still helps when a capture fails and you need to adjust MAKEDUMP_ARGS or core_collector.
Operational checklist for real hosts
-
Reserve memory once, verify forever
grep -o 'crashkernel=[^ ]*' /proc/cmdline- alert if missing after kernel/bootloader changes
-
Confirm loaded state after every reboot
-
cat /sys/kernel/kexec_crash_loadedmust be1
-
-
Watch dump storage
- capacity on
/var/crashor collector - retention (
KDUMP_NUM_DUMPSor remote lifecycle policy)
- capacity on
-
Keep debug symbols available offline
- you do not need debuginfo on every production box
- you do need matching debug symbols on the analysis workstation
-
Test after major kernel upgrades
- new kernel, new modules, new Secure Boot state, new root layout
-
Document the blast radius
- kdump test is a hard crash
- never “just test it” on a primary database node mid-day
Secure Boot and signed kernels
If the host uses UEFI Secure Boot, the capture path still has to satisfy your boot trust policy. Distro-signed kernels usually continue to work. Custom/self-managed signing setups need the kexec capture kernel and related bits to remain trusted after upgrades.
kdump itself does not replace Secure Boot policy. It depends on it when Secure Boot is enabled.
Common failure modes
kexec_crash_loaded stays 0
- no
crashkernel=in cmdline - reservation failed (too large / fragmented / unsupported placement)
- dump service disabled
- broken kdump initrd/symlink after a kernel install
Capture kernel boots, no vmcore written
- target filesystem full
- wrong
KDUMP_COREDIR/path - NFS export permissions
- SSH key not authorized for the capture user
-
makedumpfilefailed and fallbackcpalso failed
Dump exists but analysis is useless
- missing matching debug symbols
- over-filtered dump for the question you need
- analyzed with the wrong
vmlinuxversion
Host appears wedged after panic
- capture is still writing a large dump
- console is graphical and not redrawing
- crashkernel too small, capture kernel OOM’d
Patience plus serial console saves a lot of false conclusions here.
Minimal production baseline
If you want a boring, supportable setup on a Debian/Ubuntu server:
sudo apt install kdump-tools kexec-tools makedumpfile
sudo tee -a /etc/default/kdump-tools >/dev/null <<'EOF'
USE_KDUMP=1
KDUMP_COREDIR="/var/crash"
MAKEDUMP_ARGS="-c -d 31"
KDUMP_NUM_DUMPS=5
KDUMP_DUMP_DMESG=1
EOF
# add crashkernel=256M (or larger) to GRUB_CMDLINE_LINUX_DEFAULT, then:
sudo update-grub
sudo reboot
# after reboot
sudo kdump-config load
sudo kdump-config status
mkdir -p /var/crash
chmod 700 /var/crash
Then schedule one controlled lab crash before you trust it in production.
Boundaries and honesty
kdump is excellent at preserving kernel crash evidence. It is not:
- a substitute for good HA and health checks
- a full forensics platform by itself
- free — reserved crash memory is RAM you cannot use for workloads
- guaranteed on every broken machine path (firmware hangs, early-boot failures before kexec load, storage dead ends)
Pair it with:
-
systemd-pstorefor small panic breadcrumbs -
systemd-coredumpfor userspace crashes - watchdogs for hard hangs that never reach a clean panic path
- remote logging so you still know a host died if dump capture fails
References
- Linux kernel docs: Kdump - The kexec-based Crash Dumping Solution
- Linux kernel docs: VMCOREINFO
- Debian man pages:
kdump-config(8),kdump-tools(5),makedumpfile(8) - Fedora Wiki: How to use kdump to debug kernel crashes
Full vmcore capture is one of those systems features you either set up before the outage, or wish you had set up during it. Reserve the memory, load the capture kernel, verify kexec_crash_loaded, and do one planned test. Future-you gets evidence instead of a shrug.
Top comments (0)