← Back

2026

journalctl: Reading the System Journal

How to query the systemd journal effectively. Filtering by unit, time, priority and boot session so you find what you need fast.

Every time a systemd service writes to stdout or stderr, that output lands in the journal. The kernel writes its boot messages there. Authentication events, hardware errors and timer job output all go to the same place. That central store is managed by systemd-journald.

The journal is stored in a binary format under /run/journal/ or /var/log/journal/ depending on whether persistence is configured. Because it is binary you cannot read it with cat or grep. journalctl is the tool for querying it.

On a busy system the journal accumulates data fast. The real skill with journalctl is not reading everything. It is knowing how to filter down to exactly the entries you need.

Basic usage

Running journalctl with no arguments opens the entire journal in a pager. On any server that has been running for more than a few days this means thousands of lines. These four flags are what you actually reach for:

journalctl

Every entry in the journal, oldest first. Usually far too much output. Always add a filter.

journalctl -e

Jump straight to the end of the journal without scrolling through everything.

journalctl -f

Follow new entries as they arrive. The system-wide equivalent of tail -f.

journalctl -n 100

Show the last 100 lines. Omit the number and it defaults to 10.

Filtering by unit

The -u flag scopes output to a specific systemd unit. This is the filter you will use most often when debugging a particular service.

journalctl -u nginx

All log entries from the nginx unit.

journalctl -u nginx -f

Follow nginx logs in real time.

journalctl -u nginx -n 50

Last 50 lines from nginx only.

journalctl -u nginx -u postgresql

Logs from two units interleaved in time order.

The unit name matches the service file name. nginx works because there is a nginx.service file. You can also pass the full name with the extension if you prefer to be explicit.

Filtering by time

--since and --until accept both absolute timestamps and relative expressions. They combine cleanly with other filters.

journalctl --since "1 hour ago"

Everything from the last hour.

journalctl --since "2026-04-01 12:00"

From a specific date and time.

journalctl --since "09:00" --until "10:00"

Within a time window today.

journalctl -u nginx --since "2026-04-01"

Unit filter combined with a date. Filters stack.

Priority levels

journalctl uses the same eight priority levels as syslog. When you filter with -p you get entries at that level and everything above it. Running journalctl -p err gives you errors, critical messages, alerts and emergencies together.

Level
Name
When to use
0
emerg
System is unusable
1
alert
Immediate action required
2
crit
Critical conditions
3
err
Error conditions. A good default when something is broken
4
warning
Warning conditions. Useful for catching problems before they become errors
5
notice
Normal but significant events
6
info
Informational messages
7
debug
Debug-level messages. Very noisy

Starting with -p err is a good habit when something is broken but you are not sure where to look. It cuts through informational noise and surfaces the things that actually went wrong.

Boot sessions

Every time a machine boots, systemd assigns that session a unique boot ID. journalctl can scope its output to a specific boot. This is where it really earns its keep compared to plain log files. When a service crashed during the previous boot you can go back and read exactly what happened.

journalctl -b

Logs from the current boot only.

journalctl -b -1

Logs from the previous boot. Useful after a crash or unexpected reboot.

journalctl -b -2

The boot before that. Go back as far as the journal has data.

journalctl --list-boots

List all recorded boots with their IDs and timestamps.

Boot sessions are only available if the journal is configured for persistence. By default on some distributions the journal lives in /run/journal/ which is a tmpfs and gets wiped on reboot. To enable persistence, create the directory /var/log/journal/ and run systemd-tmpfiles --create.

Disk usage

The journal enforces a size cap configured in /etc/systemd/journald.conf. On most systems this defaults to around 10% of the filesystem. When the cap is hit, old entries are rotated out automatically. You can also trigger cleanup manually.

journalctl --disk-usage

Show how much disk space the journal is currently consuming.

journalctl --vacuum-size=500M

Remove old entries until the journal is under 500 MB.

journalctl --vacuum-time=30d

Remove entries older than 30 days.

Output formats

The default output is readable but not always what you want. The -o flag changes the format. The JSON options are particularly useful when you are piping output into scripts or log aggregation tools.

-o short

Default format. Timestamp, hostname, unit name and message on one line.

-o short-monotonic

Uses a monotonic timestamp instead of wall clock time. Useful for calculating the gap between events.

-o json

One JSON object per line. Pipe into jq to query or extract specific fields.

-o json-pretty

Human-readable multi-line JSON. Good for inspecting what metadata a single entry carries.

-o cat

Message text only with no metadata. Clean output for scripts that just need the content.

Putting it together

Most of these flags compose freely. The command you will find yourself writing most often on a real system looks something like this:

terminal
journalctl -u nginx -p err --since "1 hour ago"

Errors from nginx in the last hour. This covers most first-response debugging scenarios.

Once you have narrowed down the time window or the specific error, drop the filters and use -f to watch the service live while you reproduce the issue.