kmail.at
contact

elsewhere

EnglishEN
← learning

sysadmin · difficulty ◆◆

journalctl — read the systemd journal

Every service's log, one command, zero guesswork.

Your service died at 3am and /var/log/syslog is a wall of noise. journalctl is the tool that answers 'what happened, when, and to which unit' in a single query — if you know its filters.

AI-generated draft · reviewed and editedThis text was generated with AI as a first draft, then reviewed and edited by the author, who holds editorial responsibility for it.

2026-09-03 · 6 min read

$ journalctl

What it does

journalctl reads the journal: the structured, binary log that systemd has been collecting since boot. Unlike plain-text logs, every entry carries metadata — the unit, PID, priority, boot ID, and a timestamp — which is why you can filter by service (-u), by severity (-p), by time (--since/--until), and by boot (-b) without ever touching grep. It is the front door to everything systemd knows about your machine.

Why it matters

Before systemd, debugging meant opening /var/log/syslog and hoping. journalctl collapses that into one query language. Want every error in the last hour? `journalctl -p err --since '1 hour ago'`. Want what a specific service logged at boot? `journalctl -b -u nginx`. It can also survive reboots, and whether it does comes down to one directory: journald's default Storage=auto writes to /var/log/journal when that directory exists at boot, and keeps everything in /run/log/journal — RAM, lost on reboot — when it does not. Debian, Ubuntu, Fedora and RHEL ship the directory, so the journal persists there and you can inspect last boot's crash with `-b -1`. For anyone running a server, this is the log tool.

Cap the journal before it fills the disk

A binary journal grows until something stops it. `journalctl --disk-usage` tells you what it takes right now, and journald.conf's SystemMaxUse= sets the ceiling — SystemMaxUse=500M, say — which is the durable fix, applied from the next rotation on. For a one-off cleanup there are the vacuum switches: `journalctl --vacuum-size=500M` deletes the oldest archived files until the journal fits under that size, `journalctl --vacuum-time=2weeks` deletes anything older, and --vacuum-files= keeps a maximum number of files. All three act only on archived files, so the journal currently being written is untouched and --disk-usage can still read higher than the limit you set. The same limits can be set per directory or per service in a journald.conf.d drop-in.

Example

$ journalctl -u ssh --since '10 minutes ago'
$ journalctl -u ssh --since '10 minutes ago'
Sep 03 09:03:25 nuc sshd[633403]: Connection closed by authenticating user root 192.169.232.109 port 49254 [preauth]
Sep 03 09:03:41 nuc sshd[633782]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.169.232.109  user=root
Sep 03 09:03:43 nuc sshd[633782]: Failed password for root from 192.169.232.109 port 55592 ssh2
Sep 03 09:03:45 nuc sshd[633782]: Connection closed by authenticating user root 192.169.232.109 port 55592 [preauth]

-u filters to one unit. This is a live box being hammered by a brute-forcer on port 22 — journalctl makes that obvious in one line.

$ journalctl -p err --since '1 hour ago'
$ journalctl -p err --since '1 hour ago'
Sep 03 09:04:19 nuc kernel: i915 0000:00:02.0: [drm] *ERROR* LSPCON init failed on port B
Sep 03 09:04:19 nuc kernel: i915 0000:00:02.0: [drm] *ERROR* Failed to probe lspcon
Sep 03 09:04:19 nuc kernel: i915 0000:00:02.0: [drm] *ERROR* LSPCON init failed on port B

-p err shows only errors and worse. This machine has a flaky HDMI port driver spamming errors — exactly the kind of thing you want to surface, not bury.

$ journalctl -n 5
$ journalctl -n 5
Sep 03 09:01:16 nuc kernel: i915 0000:00:02.0: [drm] *ERROR* Failed to probe lspcon
Sep 03 09:01:17 nuc kernel: i915 0000:00:02.0: [drm] *ERROR* Failed to probe lspcon
Sep 03 09:01:21 nuc sshd[630751]: Connection closed by 192.169.232.109 port 51692

-n 5 is the tail of the journal — the last 5 lines. Add -f to follow live, like tail -f.

$ journalctl --disk-usage
$ journalctl --disk-usage
Archived and active journals take up 2.4G in the file system.

The journal is binary and it grows. Check yours with this command, and cap it with journald.conf's SystemMaxUse if it is ballooning.

Common flags

-u <unit>
show only entries from one systemd unit, e.g. -u nginx
-p <level>
filter by priority: emerg, alert, crit, err, warning, notice, info, debug
--since / --until
time filter, e.g. '1 hour ago', 'yesterday', '2026-09-01 08:00'
-b [n]
show a specific boot: -b is current, -b -1 is the previous boot
-n <num>
show the last N lines (default 10)
-f
follow — keep printing new entries as they arrive, like tail -f
-o <format>
output format: short, json, json-pretty, cat, etc.

History

Origin

journalctl is the query front-end for systemd's journal, which landed with systemd v38 in January 2012 — the release announcement described it as 'the first release with the journal'. It replaced the scattered, plain-text /var/log files with a single structured, binary log that records metadata alongside each message. The name is simply 'journal' plus the standard 'ctl' (control) suffix systemd uses for its management tools.

Fun fact

The journal is not just text — each entry carries structured fields like _PID, _BOOT_ID, and SYSLOG_IDENTIFIER. That is why `journalctl -o json-pretty` can dump a full machine-readable record, and why you can filter on fields the plain-text logs never captured. It is a database, not a log file.

Fun facts

Pros & cons

pros

  • + One query language for every service's logs — no more hunting through /var/log
  • + Structured metadata (unit, PID, priority, boot) enables precise filtering
  • + Persistent across reboots where /var/log/journal exists, so you can inspect previous boots with -b -1
  • + Built into systemd — present on every modern distro, no install

cons

  • − Binary format — you cannot just cat or grep the journal file directly
  • − Not persistent by default on all distros unless you configure journald.conf
  • − The full journal can grow huge — check it with --disk-usage — and needs size capping
  • − systemd-only — on non-systemd systems you are back to /var/log

Takeaways

  1. 1Debug one service: `journalctl -u <unit> --since '1 hour ago'`
  2. 2Surface only problems: add `-p err` to skip the noise
  3. 3Watch live: `journalctl -f` follows new entries like tail -f
  4. 4Check disk: `journalctl --disk-usage`, then cap it in journald.conf
  5. 5Inspect last boot's crash with `journalctl -b -1`

Related commands