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:
journalctlEvery entry in the journal, oldest first. Usually far too much output. Always add a filter.
journalctl -eJump straight to the end of the journal without scrolling through everything.
journalctl -fFollow new entries as they arrive. The system-wide equivalent of tail -f.
journalctl -n 100Show 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 nginxAll log entries from the nginx unit.
journalctl -u nginx -fFollow nginx logs in real time.
journalctl -u nginx -n 50Last 50 lines from nginx only.
journalctl -u nginx -u postgresqlLogs 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.
0emerg1alert2crit3err4warning5notice6info7debugStarting 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 -bLogs from the current boot only.
journalctl -b -1Logs from the previous boot. Useful after a crash or unexpected reboot.
journalctl -b -2The boot before that. Go back as far as the journal has data.
journalctl --list-bootsList 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-usageShow how much disk space the journal is currently consuming.
journalctl --vacuum-size=500MRemove old entries until the journal is under 500 MB.
journalctl --vacuum-time=30dRemove 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 shortDefault format. Timestamp, hostname, unit name and message on one line.
-o short-monotonicUses a monotonic timestamp instead of wall clock time. Useful for calculating the gap between events.
-o jsonOne JSON object per line. Pipe into jq to query or extract specific fields.
-o json-prettyHuman-readable multi-line JSON. Good for inspecting what metadata a single entry carries.
-o catMessage 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:
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.