}

journalctl: Filter and Search System Logs (2026 Guide)

journalctl: Filter and Search System Logs (2026 Guide)

Last updated: March 2026

journalctl is the command-line tool for reading logs collected by systemd's journald. Every service managed by systemd writes its stdout and stderr to the journal automatically — no log file configuration needed. journald also collects kernel messages, boot logs, and audit records in one unified, binary-indexed store. This guide covers every important filter, output format, and maintenance command.


Basic Usage

# Show all journal entries (opens in a pager like less)
journalctl

# Disable the pager and print all output
journalctl --no-pager

# Show the most recent entries first (reverse order)
journalctl -r

# Last 50 lines
journalctl -n 50

# Follow live output (like tail -f)
journalctl -f

By default, journalctl opens logs in less. Navigation keys: - G — jump to end - g — jump to beginning - /pattern — search forward - ?pattern — search backward - q — quit


Filter by Unit (-u)

The most common filter: show logs for a specific service.

# All logs for a unit
journalctl -u nginx
journalctl -u sshd
journalctl -u myapp.service

# Follow live
journalctl -u nginx -f

# Last 100 lines
journalctl -u nginx -n 100

# Multiple units
journalctl -u nginx -u php-fpm

For services you manage directly, see the systemd service file guide on how to ensure logs go to journald.


Filter by Time (--since / --until)

Absolute timestamps

journalctl --since "2026-03-26"
journalctl --since "2026-03-26 10:00:00"
journalctl --until "2026-03-26 12:00:00"

# Time range
journalctl --since "2026-03-26 10:00:00" --until "2026-03-26 11:30:00"

Timestamp format: YYYY-MM-DD HH:MM:SS. The time portion is optional.

Relative timestamps

journalctl --since "1 hour ago"
journalctl --since "30 minutes ago"
journalctl --since "2 days ago"
journalctl --since yesterday
journalctl --since today

Combined with unit filter

journalctl -u nginx --since "1 hour ago"
journalctl -u postgresql --since "2026-03-25" --until "2026-03-26"

Filter by Priority (-p)

journald uses syslog priority levels 0–7:

Number Name Meaning
0 emerg System unusable
1 alert Action must be taken immediately
2 crit Critical conditions
3 err Error conditions
4 warning Warning conditions
5 notice Normal but significant
6 info Informational
7 debug Debug-level messages
# Show errors and above (0, 1, 2, 3)
journalctl -p err
journalctl -p 3

# Show warnings and above (0-4)
journalctl -p warning

# Priority range: warnings through errors only
journalctl -p warning..err

# Show only info messages
journalctl -p info -p info   # exact level (not range)

Combine with unit:

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

Filter by Boot (-b)

# Current boot
journalctl -b
journalctl -b 0    # same as above

# Previous boot
journalctl -b -1

# Two boots ago
journalctl -b -2

# List available boots
journalctl --list-boots

--list-boots output:

-2 a1b2c3d4... Mon 2026-03-24 08:00:00 UTC—Mon 2026-03-24 18:00:00 UTC
-1 e5f6a7b8... Tue 2026-03-25 09:00:00 UTC—Tue 2026-03-25 20:00:00 UTC
 0 c9d0e1f2... Wed 2026-03-26 08:30:00 UTC—Wed 2026-03-26 10:00:00 UTC

Combine with unit to see why a service was failing after last reboot:

journalctl -u myapp -b -1

Kernel Messages (-k)

# All kernel messages (equivalent to dmesg)
journalctl -k

# Kernel messages since last boot
journalctl -k -b

# Recent kernel messages, follow
journalctl -k -f

# Kernel errors
journalctl -k -p err

Useful for diagnosing hardware issues, driver errors, OOM kills, and filesystem errors.


Output Formats (-o)

Format Description
short Default. Timestamp, hostname, unit, message
short-precise Like short but with microsecond precision
short-iso ISO 8601 timestamps
short-monotonic Monotonic timestamps (seconds since boot)
verbose All metadata fields
json One JSON object per line
json-pretty Multi-line indented JSON
cat Message text only (no metadata)
export Binary export format
# JSON output (useful for log processing with jq)
journalctl -u nginx -o json | jq '.MESSAGE'

# Pretty JSON for readability
journalctl -u myapp -n 5 -o json-pretty

# Just the message text, no timestamps
journalctl -u myapp -o cat

# Verbose: all fields
journalctl -u sshd -n 1 -o verbose

Processing with jq

# Extract specific fields
journalctl -u nginx -o json --no-pager | jq '{time: .__REALTIME_TIMESTAMP, msg: .MESSAGE}'

# Filter by message content
journalctl -u nginx -o json --no-pager | jq 'select(.MESSAGE | contains("error"))'

# Count errors per hour
journalctl -u myapp -o json --no-pager --since "24 hours ago" \
  | jq -r '.SYSLOG_TIMESTAMP' | cut -c1-14 | sort | uniq -c

Adding Timestamps (--timestamps)

When following logs, timestamps are shown by default. For piped output, they may be suppressed:

journalctl -u myapp -f --output=short-precise

Filtering by Field

journald stores structured fields. You can filter by any of them:

# Filter by systemd unit (same as -u)
journalctl _SYSTEMD_UNIT=nginx.service

# Filter by PID
journalctl _PID=1234

# Filter by executable path
journalctl _EXE=/usr/sbin/sshd

# Filter by user ID
journalctl _UID=1000

# Filter by hostname (useful in centralized logging)
journalctl _HOSTNAME=webserver1

# Container logs (if using systemd-nspawn or similar)
journalctl CONTAINER_NAME=mycontainer

Persistent Logs

By default, on many distributions journald stores logs only in memory (/run/log/journal/) and they are lost on reboot. To keep logs across reboots, enable persistent storage.

Enable persistence

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

Or set it in the journald configuration:

sudo nano /etc/systemd/journald.conf

Set:

[Journal]
Storage=persistent

Then restart:

sudo systemctl restart systemd-journald

With persistent storage, logs are written to /var/log/journal/ and retained across reboots. The journalctl -b -1 (previous boot) command only works if logs are persistent.

Verify storage mode

journalctl --disk-usage
# Archived and active journals take up 512.0M on disk.
ls /var/log/journal/

Disk Usage and Log Rotation

Check disk usage

journalctl --disk-usage

Limit log retention

Set limits in /etc/systemd/journald.conf:

[Journal]
Storage=persistent
# Keep at most 1 GB
SystemMaxUse=1G
# Always keep at least 100 MB free
SystemKeepFree=100M
# Maximum size of a single journal file
SystemMaxFileSize=50M
# Maximum age of journal files
MaxRetentionSec=1month

Restart journald after editing:

sudo systemctl restart systemd-journald

Vacuum (manual cleanup)

# Reduce to 500 MB total
sudo journalctl --vacuum-size=500M

# Remove entries older than 30 days
sudo journalctl --vacuum-time=30d

# Keep at most 5 journal files
sudo journalctl --vacuum-files=5

These commands remove archived (rotated) journal files. They do not touch the active journal file.


Useful One-Liners

# See all failed services
journalctl -p err -b --no-pager | grep "Failed"

# Find OOM kills
journalctl -k --no-pager | grep -i "out of memory\|oom"

# SSH authentication failures
journalctl -u sshd --no-pager | grep "Failed password\|Invalid user"

# All logs from the last 5 minutes
journalctl --since "5 minutes ago" --no-pager

# Export logs to a file
journalctl -u myapp --since "2026-03-25" --until "2026-03-26" --no-pager > myapp.log

# Show logs from all units that mention a specific string
journalctl --grep="connection refused" --since "1 hour ago"

FAQ

Q: journalctl shows "No entries" or very few entries. Why?

Logs may not be persistent. Check journalctl --disk-usage. If it shows /run/log/journal/ (not /var/log/journal/), persistence is not enabled. See the "Persistent Logs" section above.

Q: How do I search for a specific string in logs?

journalctl --grep="pattern"
# Or pipe to grep
journalctl -u myapp --no-pager | grep "ERROR"
# Case-insensitive
journalctl --grep="error" --case-sensitive=false

Q: Can I send application logs to journald without systemd managing the process?

Yes. Use systemd-cat:

echo "Manual log entry" | systemd-cat -t myapp -p info

# Or pipe a command's output
/usr/local/bin/myscript.sh | systemd-cat -t myscript

Or write directly to the journal socket using the sd_journal_print() C API or its Python binding systemd.journal.


Related Articles