XK0-006 · Security · Updated July 26, 2026
journalctl Commands: Filtering, Persisting, and Rate-Limiting the systemd Journal
On a systemd distribution, log collection is handled by systemd-journald, a daemon that gathers kernel messages, service stdout/stderr, syslog traffic, and boot output into a structured, indexed binary journal — and journalctl is the query tool for reading it. Because the journal is binary rather than flat text, you don’t grep files under /var/log to work with it; you pass journalctl filters for unit, boot, priority, and time range. Two journald behaviors matter as much as the query flags: where the journal is stored (volatile by default on many distributions) and how its built-in rate limiting throttles a flooding service.
journald: what it is and what it stores
systemd-journald ingests log records from multiple sources — the kernel ring buffer, native systemd service output, the syslog socket, and audit-adjacent boot messages — and writes them as structured entries with indexed metadata fields (_SYSTEMD_UNIT, _PID, PRIORITY, boot ID, and dozens more). That metadata is what makes the filtering below possible without text-parsing. Traditional syslog daemons like rsyslog often run alongside journald, reading from it and writing the familiar flat files, but the authoritative structured store on a modern system is the journal. When a monitoring or log-aggregation question asks which component collects kernel, service, and boot messages into a binary store queried by journalctl, the answer is journald.
The core filtering flags
The flags below cover nearly every real-world query. Each is independently useful, and they combine freely:
-u <unit>— entries from one systemd unit:journalctl -u nginx.service.-b— entries since the current boot;-b -1is the previous boot, andjournalctl --list-bootsenumerates boot IDs.-k— kernel messages only (the journal’s equivalent ofdmesg) — the first stop when confirming a failing disk.-f— follow: stream new entries live, liketail -f.-e— open the pager jumped to the end (newest entries).-r— reverse order, newest first.-n <N>— show only the last N lines (default 10 with-nalone).-p <priority>— filter by syslog priority, name or number:-p err(or-p 3) shows err and worse; priorities run emerg(0) through debug(7).--since/--until— time windows:--since "2026-07-25 08:00" --until "09:00", or friendly forms like--since yesterday.-x— augment entries with explanatory catalog text where available.-o <format>— output format:-o verbosedumps every structured field;-o jsonsuits scripting and log shipping.--disk-usage— report journal space consumption; pair with--vacuum-size=500Mor--vacuum-time=2weeksto prune.
Combining flags is where the value shows up. Kernel messages since the most recent boot: journalctl -k -b. Everything nginx logged this boot: journalctl -u nginx.service -b. Live errors from a unit you’re debugging: journalctl -u sshd.service -p err -f. Match-the-flag questions punish fuzzy memory — the pairs worth locking in are -f follow, -e end, -r reverse, -k kernel, -u unit, -p priority, -b boot.
Making the journal survive reboots
Here is the trap that catches admins on default installs of several distributions: journald stores the journal in /run/log/journal, and /run is a tmpfs — a RAM-backed filesystem — so every reboot erases the logs. Whether the journal persists is governed by the Storage= setting in /etc/systemd/journald.conf:
Storage= value | Behavior |
|---|---|
volatile | Journal kept only in /run/log/journal; lost at reboot |
persistent | Journal written to /var/log/journal, creating the directory if needed |
auto (default) | Persistent only if /var/log/journal already exists; otherwise volatile |
none | Nothing stored; entries only forwarded (e.g., to syslog) |
So there are two valid fixes for disappearing logs: set Storage=persistent in journald.conf and restart systemd-journald, or simply create the directory (sudo mkdir -p /var/log/journal, then systemctl restart systemd-journald) and let auto do the rest. On an exam question about a journald.conf change, Storage=persistent is the answer being fished for. Persistent journals are also a hardening and forensics concern — post-incident analysis is impossible if the evidence evaporated at reboot, which is why this lands in the security domain alongside auditd.
Rate limiting: RateLimitIntervalSec and RateLimitBurst
journald protects itself from log floods with per-service rate limiting, configured in journald.conf:
RateLimitIntervalSec=30s
RateLimitBurst=1000
The semantics: within each 30-second window, a given service may log up to 1,000 messages. Once a service exceeds the burst within the interval, journald drops that service’s further messages for the remainder of the window and records a single notice stating how many messages were suppressed. When the next interval starts, logging resumes normally. Key discriminations: the limit is enforced per service, not globally — a chatty app cannot silence other units’ logging, and journald itself keeps running; the excess messages are discarded, not queued or delayed for later delivery. Setting either value to 0 disables rate limiting entirely. If a misbehaving application emits tens of thousands of identical lines per minute, expect to see bursts of 1,000 entries punctuated by suppression notices rather than a complete flood.
How the XK0-006 exam tests this
- An identification question in a monitoring context: which component on a systemd distribution collects kernel, service, and boot messages into a binary,
journalctl-queryable store — journald, versus distractors like rsyslog, auditd, or logrotate. - A “compose the right command” scenario: kernel entries since last boot (
-k -b), or one service’s entries since last boot (-u <unit> -b), with wrong answers pairing plausible flags incorrectly. - A matching exercise pairing options with behavior — follow vs jump-to-end vs reverse vs priority filter — where transposed descriptions are the trap.
- A configuration question on
/etc/systemd/journald.conf: which change makes logs persist (Storage=), or what actually happens when a flooding service crosses theRateLimitBurstthreshold withinRateLimitIntervalSec.
Timer-driven jobs are a common source of the service logs you’ll be querying — the scheduling side is covered in systemd timers vs cron. Logging and log persistence land in the Security domain — the full XK0-006 study guide maps every domain. Filter syntax sticks fastest when you work through practice questions that force you to recall it.
Quick reference
- journald = the collector/store (structured, binary, indexed);
journalctl= the query tool. journalctl -k -b→ kernel messages from the current boot;journalctl -u nginx.service -b→ one unit, this boot.- Memorize the pairs:
-ffollow,-ejump to end,-rnewest first,-ppriority threshold,-nline count,-xadd explanations. - Time-box queries with
--since/--until; machine-readable output with-o json. - Default storage is effectively volatile on many distros (
/run/log/journal, tmpfs): logs vanish at reboot. - Fix persistence via
Storage=persistentin/etc/systemd/journald.conf, or create/var/log/journalunderStorage=auto, then restartsystemd-journald. - Rate limiting is per service: beyond
RateLimitBurstmessages inRateLimitIntervalSec, further messages from that service are dropped and one suppression notice is logged; the counter resets next interval. - Manage journal size with
journalctl --disk-usage,--vacuum-size=,--vacuum-time=.