How to use journalctl to trace why my systemd‑service crashes after a kernel upgrade

After a kernel upgrade a service that used to run fine suddenly dies.
The first instinct is to blame the new kernel, but the real problem is often a missing module, a changed sysctl, or a subtle API change.
journalctl is the first tool you should use to trace the exact moment the service stops, what the kernel was doing, and whether the crash was caused by the upgrade or by something else.

Why kernel upgrades can break services

Kernel updates bring new drivers, security patches, and sometimes deprecations.
A service that relies on a specific kernel feature (e.g., a particular ioctl, a netfilter rule, or a cgroup v2 capability) may fail if that feature is altered or removed.
Even a benign change in the kernel’s default sysctl values can cause a service to misbehave.
Because systemd services are tightly coupled to the kernel, a crash often manifests as a “failed” unit in the journal.

The role of journalctl in debugging

journalctl aggregates all system logs, including kernel messages (kernel:), systemd unit logs (systemd[1]), and application logs that write to stdout/stderr.
It provides powerful filtering, time‑based queries, and the ability to follow logs in real time.
When a service crashes after a kernel upgrade, the journal usually contains:

  1. The service’s own output (error messages, stack traces).
  2. Kernel messages that may explain why the service was killed (e.g., Killed process, OOM, SIGKILL).
  3. Systemd’s state changes (Started, Failed, Reloaded).

By combining these, you can pinpoint the root cause.

Basic journalctl usage

# Show the last 50 lines of the journal
journalctl -n 50

# Show only the most recent boot
journalctl -b

# Show logs for the current boot, following new entries
journalctl -b -f

journalctl stores logs in binary format in /var/log/journal.
If the directory does not exist, logs are kept in volatile memory and lost on reboot.
For long‑term debugging you should ensure persistent storage is enabled (systemd-journald.conf → Storage=persistent).

Filtering by unit and time

The most common scenario is to look at a specific unit:

journalctl -u myservice.service

To narrow it to the time of the crash, use the --since and --until options:

journalctl -u myservice.service --since "2026-10-12 14:00" --until "2026-10-12 15:00"

You can also combine filters:

journalctl -u myservice.service -k -b

-k shows only kernel messages, which is handy when you suspect a kernel panic or OOM.

Inspecting kernel messages

Kernel logs are prefixed with kernel:.
Look for patterns like OOM, Killed process, SIGSEGV, or BUG.
Example:

journalctl -k -b | grep -i 'killed'

If the service was terminated by the kernel’s OOM killer, you’ll see a line similar to:

kernel: Out of memory: Kill process 1234 (myservice) score 42 or sacrifice child

That tells you the kernel ran out of memory, not that the service crashed by itself.

Step‑by‑step workflow

1. Identify the crash

Start with the most recent boot:

journalctl -b | grep -i 'failed' | grep -i 'myservice'

If the unit shows Result: exit-code or Result: signal, the service itself reported a failure.

2. Narrow to the service

Show the service’s logs around the failure:

journalctl -u myservice.service -n 200

Scroll to the bottom; the last few lines usually contain the crash message or a stack trace.

3. Correlate with the kernel upgrade

Check the kernel version that was booted:

uname -r

If you upgraded the kernel recently, the version will be newer than the one that was running when the service last succeeded.
You can also list all installed kernels:

rpm -qa | grep kernel

or on Debian/Ubuntu:

dpkg -l | grep linux-image

4. Look for kernel panic or Oops

Kernel panics or Oopses are logged with kernel: and often contain a stack trace.
Search for oops or panic:

journalctl -k -b | grep -i -E 'oops|panic'

If


See also