$linuxjunkies
>

How to Read Logs with journalctl

Learn to filter systemd journal logs by unit, time, and priority with journalctl, follow logs live, and manage disk usage on any modern Linux system.

BeginnerUbuntuDebianFedoraArch8 min readUpdated June 7, 2026

Before you start

  • A Linux system running systemd (most distributions since 2015)
  • A terminal with sudo access for persistent storage and vacuum operations
  • Basic familiarity with the command line

systemd's journal is the central log store on most modern Linux systems. journalctl is the tool that reads it. Unlike the old syslog days where logs were scattered across /var/log/*.log files with varying formats, the journal stores structured, binary entries you can slice any way you need. This guide covers the filters and options you'll reach for daily.

How the Journal Works

The systemd journal is managed by systemd-journald. Logs are written to /run/log/journal/ (volatile, lost on reboot) by default. If /var/log/journal/ exists and is owned correctly, the journal persists across reboots. Check which mode you're in:

journalctl --disk-usage

If it reports a few megabytes, you're likely on volatile storage. To enable persistence:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

Basic Usage

Without arguments, journalctl dumps every entry from the oldest available, piped through a pager (usually less). That's rarely useful on a busy system. Jump straight to the end instead:

journalctl -e

For a fixed number of recent lines, like tail:

journalctl -n 50

Following Logs in Real Time

The -f flag follows new entries as they arrive, exactly like tail -f on a log file:

journalctl -f

You can combine -f with any other filter shown in this guide. For example, follow only SSH:

journalctl -f -u ssh

Filtering by Systemd Unit

The -u flag is the filter you'll use most. Pass any unit name — services, sockets, timers, mounts.

journalctl -u nginx.service

The .service suffix is optional; systemd infers it. To query multiple units at once, repeat the flag:

journalctl -u nginx -u php-fpm

On systems with many containers or instances, glob patterns work too (quote the pattern to stop the shell expanding it):

journalctl -u 'docker-*'

Filtering by Time

--since and --until accept timestamps in several formats. The most practical ones:

# Logs from the last hour
journalctl --since "1 hour ago"

# Logs between two specific times
journalctl --since "2024-06-01 08:00:00" --until "2024-06-01 09:30:00"

# Since last boot only
journalctl -b

The -b flag deserves its own mention. -b 0 is the current boot (default), -b -1 is the previous boot, -b -2 the one before that. List all recorded boots first:

journalctl --list-boots

Output will look roughly like this (it will vary by system):

-3 abc123... Mon 2024-05-27 ...
-2 def456... Tue 2024-05-28 ...
-1 ghi789... Wed 2024-05-29 ...
 0 jkl012... Thu 2024-05-30 ...

Then pull logs from a specific boot using its index:

journalctl -b -1

Filtering by Priority

Syslog priority levels run from 0 (emergency) to 7 (debug). journalctl accepts either the number or the name. The -p flag filters to that level and above in severity — meaning lower numbers, which are more critical.

NumberNameMeaning
0emergSystem unusable
1alertImmediate action needed
2critCritical condition
3errError condition
4warningWarning condition
5noticeNormal but significant
6infoInformational
7debugDebug-level messages

Show only errors and worse across the whole journal:

journalctl -p err

A useful triage command — errors from the current boot only:

journalctl -b -p err

You can also specify a range of priorities with a double-dot syntax:

journalctl -p warning..err

Combining Filters

Filters compose naturally. Show errors from nginx since yesterday:

journalctl -u nginx -p err --since yesterday

Multiple -u flags are OR'd together; other filter types are AND'd. So -u nginx -u php-fpm -p err means: (nginx OR php-fpm) AND priority <= err.

Output Formats

The default output is human-readable. For scripting or shipping logs to another system, use -o:

  • json — one JSON object per line, all fields included
  • json-pretty — same but formatted for reading
  • short-iso — human-readable with ISO 8601 timestamps
  • cat — message text only, no metadata
  • verbose — every journal field for each entry
# Machine-readable output for a specific unit
journalctl -u nginx -o json | jq '.MESSAGE'

Disk Usage and Housekeeping

Check how much disk space the journal is consuming:

journalctl --disk-usage

To vacuum old entries, use one of three strategies. They all do a dry-run unless you confirm with the actual flag:

# Keep only the last 500 MB
sudo journalctl --vacuum-size=500M

# Keep only logs from the last 2 weeks
sudo journalctl --vacuum-time=2weeks

# Keep only the last 5 boots worth of data
sudo journalctl --vacuum-files=5

To set permanent limits, edit /etc/systemd/journald.conf. The key options are SystemMaxUse, MaxRetentionSec, and MaxFileSec. After editing:

sudo systemctl restart systemd-journald

Verifying Your Setup

Confirm journald is running and the journal is healthy:

systemctl status systemd-journald
journalctl --verify

--verify checks the cryptographic seals (if enabled) and file integrity. Any line beginning with FAIL indicates a corrupted journal file.

Troubleshooting

No logs from before a certain date

You're likely on volatile storage. The journal is cleared on every reboot. Enable persistence as shown in the first section.

Permission denied running journalctl

By default, non-root users can only see their own logs. Add your user to the systemd-journal group for full read access without sudo:

sudo usermod -aG systemd-journal $USER

Log out and back in for the change to take effect.

journalctl output is very slow

This usually means the journal is large and you're scanning without a time or unit filter. Add --since or -u to narrow the search. Also confirm you have a persistent journal on a fast disk — SD cards and slow USB drives make journal reads painful.

Unit name not found

Check the exact unit name with systemctl list-units or systemctl status. Some distros name the same service differently — for example, sshd.service on Fedora/RHEL vs ssh.service on Debian/Ubuntu.

tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

Frequently asked questions

Why do my logs disappear after every reboot?
The journal is in volatile mode, storing logs only in /run/log/journal/ which is cleared at shutdown. Create /var/log/journal/ and restart systemd-journald to enable persistent storage.
Can I read journals from another machine or a rescued system?
Yes. Use journalctl -D /path/to/journal/directory to point at any journal directory, or --root to specify an alternative filesystem root.
How do I search journal logs for a specific string?
Pipe through grep: journalctl -u nginx | grep 'connection refused'. For large time ranges, narrow with --since first to keep it fast.
What is the difference between journalctl -p err and journalctl -p err..emerg?
They are equivalent. -p err alone already means 'err and more severe' (emerg, alert, crit, err). The range syntax is just more explicit about the upper bound.
How do I stop journalctl output from being paged through less?
Use --no-pager to print directly to stdout, which is also what you want in scripts: journalctl --no-pager -u nginx -n 100.

Related guides