journalctl & systemd Journal
Quick Reference
# Basic viewing
journalctl # All logs (oldest first)
journalctl -r # Reverse (newest first)
journalctl -f # Follow (like tail -f)
journalctl -n 50 # Last 50 entries
# Filter by time
journalctl --since "1 hour ago"
journalctl --since "2024-01-15 10:00" --until "2024-01-15 12:00"
journalctl -b # Current boot only
journalctl -b -1 # Previous boot
# Filter by unit/service
journalctl -u nginx # Specific service
journalctl -u nginx -u php-fpm # Multiple services
# Filter by priority
journalctl -p err # Errors and above
journalctl -p warning..err # Warning to error range
# Output formats
journalctl -o json # JSON output
journalctl -o json-pretty # Pretty JSON
journalctl -o short-iso # ISO timestamps
Understanding the Journal
Journal vs Traditional Syslog
| Feature | syslog/rsyslog | systemd-journald |
|---|---|---|
Storage |
Plain text files |
Binary indexed database |
Structure |
Line-based, parsed |
Structured fields (key=value) |
Metadata |
Limited |
Rich (PID, UID, unit, boot ID) |
Integrity |
None |
Optional FSS sealing |
Boot Isolation |
Manual |
Automatic boot ID tracking |
Querying |
grep/awk |
Native filtering |
Performance |
Good for writes |
Better for reads/queries |
Basic Viewing
Paging and Navigation
# Default pager (less)
journalctl
# Navigation in less:
# g - go to beginning
# G - go to end
# / - search forward
# ? - search backward
# n - next match
# N - previous match
# q - quit
# No pager (direct output)
journalctl --no-pager
# Specific number of lines
journalctl -n 100
journalctl --lines=100
Time-Based Filtering
Relative Time
# Last N time units
journalctl --since "5 minutes ago"
journalctl --since "2 hours ago"
journalctl --since "1 day ago"
journalctl --since "1 week ago"
# Combined relative
journalctl --since "1 hour ago" --until "30 minutes ago"
Absolute Time
# Specific date/time
journalctl --since "2024-01-15 10:00:00"
journalctl --since "2024-01-15" --until "2024-01-16"
# Date only (midnight)
journalctl --since "2024-01-15"
# Time shortcuts
journalctl --since today
journalctl --since yesterday
journalctl --since "yesterday" --until "today"
Boot-Based Filtering
# Current boot
journalctl -b
journalctl -b 0
# Previous boot
journalctl -b -1
# Two boots ago
journalctl -b -2
# List available boots
journalctl --list-boots
# Output:
# -2 abc123... Sat 2024-01-13 09:00:00 UTC—Sat 2024-01-13 18:30:00 UTC
# -1 def456... Sun 2024-01-14 10:00:00 UTC—Sun 2024-01-14 22:00:00 UTC
# 0 ghi789... Mon 2024-01-15 08:00:00 UTC—Mon 2024-01-15 15:30:00 UTC
# Specific boot by ID
journalctl -b abc123
# Combined with time
journalctl -b -1 --since "10:00" --until "12:00"
Filtering by Source
By Systemd Unit
# Specific service
journalctl -u nginx.service
journalctl -u nginx # .service is implied
# Multiple units
journalctl -u nginx -u php-fpm -u mysql
# Unit with wildcard
journalctl -u "docker*"
journalctl -u "systemd-*"
# User units
journalctl --user -u myapp.service
journalctl --user-unit myapp.service
By Process
# By PID
journalctl _PID=1234
# By executable path
journalctl _EXE=/usr/bin/nginx
journalctl /usr/bin/nginx # Shorthand
# By command name
journalctl _COMM=sshd
# Current shell's PID
journalctl _PID=$$
By User
# By UID
journalctl _UID=1000
# By username (resolve to UID)
journalctl _UID=$(id -u username)
# By GID
journalctl _GID=1000
# Root user
journalctl _UID=0
By System Component
# Kernel messages (dmesg equivalent)
journalctl -k
journalctl --dmesg
# Kernel for current boot
journalctl -k -b
# By syslog identifier
journalctl -t sudo
journalctl -t sshd
journalctl --identifier=sudo
# By transport
journalctl _TRANSPORT=kernel # Kernel messages
journalctl _TRANSPORT=syslog # Syslog protocol
journalctl _TRANSPORT=journal # Native journal
journalctl _TRANSPORT=stdout # Stdout capture
journalctl _TRANSPORT=audit # Audit messages
Priority Filtering
Priority Levels
| Level | Name | Description |
|---|---|---|
0 |
emerg |
System is unusable |
1 |
alert |
Immediate action required |
2 |
crit |
Critical conditions |
3 |
err |
Error conditions |
4 |
warning |
Warning conditions |
5 |
notice |
Normal but significant |
6 |
info |
Informational messages |
7 |
debug |
Debug-level messages |
Filter by Priority
# Specific level and above (<=)
journalctl -p err # err, crit, alert, emerg
journalctl -p 3 # Same as above
journalctl -p warning # warning and above
journalctl -p crit # crit, alert, emerg
# Priority range
journalctl -p warning..err # warning, err only
journalctl -p 4..3 # Same as above
# Emergency only
journalctl -p emerg
journalctl -p 0
Output Formats
Available Formats
| Format | Description |
|---|---|
|
Default syslog-like format |
|
ISO 8601 timestamps |
|
Microsecond precision |
|
Monotonic timestamps |
|
Unix epoch timestamps |
|
All fields shown |
|
Binary format for backup |
|
JSON (one object per line) |
|
Pretty-printed JSON |
|
Server-sent events format |
|
JSON sequences (RFC 7464) |
|
Message only (no metadata) |
Format Examples
# Default short format
journalctl -n 1
# Jan 15 10:30:15 myhost sshd[1234]: Accepted publickey for user...
# ISO timestamps
journalctl -o short-iso -n 1
# 2024-01-15T10:30:15+0000 myhost sshd[1234]: Accepted publickey...
# Verbose (all fields)
journalctl -o verbose -n 1
# Mon 2024-01-15 10:30:15.123456 UTC [...]
# _TRANSPORT=syslog
# _UID=0
# _GID=0
# _PID=1234
# _COMM=sshd
# MESSAGE=Accepted publickey...
# ...
# JSON output
journalctl -o json -n 1
# {"__CURSOR":"...","_PID":"1234","MESSAGE":"Accepted..."}
# Pretty JSON
journalctl -o json-pretty -n 1
# Message only (for processing)
journalctl -o cat -n 1
# Accepted publickey for user from 192.168.1.100 port 54321
JSON Processing
# Parse with jq
journalctl -o json -n 10 | jq '.MESSAGE'
# Filter JSON fields
journalctl -o json -n 10 | jq '{time: .__REALTIME_TIMESTAMP, msg: .MESSAGE}'
# Count messages by unit
journalctl -o json --since today | jq -r '._SYSTEMD_UNIT' | sort | uniq -c | sort -rn
# Extract specific field
journalctl -u nginx -o json | jq -r 'select(.PRIORITY == "3") | .MESSAGE'
Field Filtering
Show Available Fields
# List all field names
journalctl --fields
# Show values for specific field
journalctl -F _SYSTEMD_UNIT
journalctl -F _COMM
journalctl -F PRIORITY
journalctl -F _UID
Field Matching
# Match specific field value
journalctl PRIORITY=3 # Errors
journalctl _SYSTEMD_UNIT=nginx.service
journalctl _COMM=sshd
journalctl SYSLOG_FACILITY=10 # authpriv
# Multiple field matches (AND)
journalctl _SYSTEMD_UNIT=nginx.service PRIORITY=3
# Multiple values same field (OR)
journalctl _SYSTEMD_UNIT=nginx.service + _SYSTEMD_UNIT=php-fpm.service
# Combine with other filters
journalctl _SYSTEMD_UNIT=sshd.service -p warning --since today
Common Fields
| Field | Description |
|---|---|
|
Log message text |
|
Syslog priority (0-7) |
|
Process ID |
|
User ID |
|
Group ID |
|
Command name |
|
Executable path |
|
Full command line |
|
Systemd unit name |
|
Cgroup path |
|
Hostname |
|
Machine ID |
|
Boot ID |
|
How log was received |
|
Syslog facility |
|
Syslog tag/identifier |
|
Source file (if available) |
|
Source line number |
|
Function name |
Cursor-Based Navigation
Understanding Cursors
Cursors are unique identifiers for journal entries, useful for: - Resuming from a specific point - Bookmarking positions - Reliable log shipping
# Show cursor for each entry
journalctl --show-cursor -n 5
# Output includes:
# -- cursor: s=abc123...;i=1234;b=xyz789...;m=...;t=...;x=...
# Start after specific cursor
journalctl --after-cursor="s=abc123...;i=1234;..."
# Start at specific cursor (inclusive)
journalctl --cursor="s=abc123...;i=1234;..."
Journal Configuration
Main Configuration File
# View current config
cat /etc/systemd/journald.conf
# Or with drop-ins
systemd-analyze cat-config systemd/journald.conf
Key Configuration Options
[Journal]
# Storage mode: volatile, persistent, auto, none
Storage=persistent
# Compress stored journals
Compress=yes
# Forward to syslog (rsyslog compatibility)
ForwardToSyslog=no
# Forward to kmsg
ForwardToKMsg=no
# Forward to console
ForwardToConsole=no
# Max disk usage (default: 10% of filesystem)
SystemMaxUse=500M
# Max size per journal file
SystemMaxFileSize=50M
# Keep at least this much free
SystemKeepFree=1G
# Max retention time
MaxRetentionSec=1month
# Max file retention time
MaxFileSec=1week
# Rate limiting (per-service)
RateLimitIntervalSec=30s
RateLimitBurst=10000
# Audit forwarding
Audit=yes
Storage Locations
# Volatile (lost on reboot)
/run/log/journal/
# Persistent (survives reboot)
/var/log/journal/
# Create persistent directory (enables persistence)
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
# Check current storage mode
journalctl --disk-usage
Journal Maintenance
Check Disk Usage
# Show journal disk usage
journalctl --disk-usage
# Output:
# Archived and active journals take up 256.0M in the file system.
# Show file details
ls -lh /var/log/journal/*/
Vacuum (Clean Up)
# Reduce to specific size
sudo journalctl --vacuum-size=100M
# Remove entries older than duration
sudo journalctl --vacuum-time=2weeks
sudo journalctl --vacuum-time=30d
# Remove old archived files (keep N)
sudo journalctl --vacuum-files=5
# Combine limits
sudo journalctl --vacuum-size=500M --vacuum-time=1month
# Verify after vacuum
journalctl --verify
Advanced Features
FSS (Forward Secure Sealing)
# Set up sealing
sudo journalctl --setup-keys
# Output provides key to store securely:
# Sealing key fingerprint: abc123...
# Store this securely for verification
# Verify sealed journals
journalctl --verify-key=abc123...
Catalog Messages
# Show catalog entries (explanations)
journalctl -x
journalctl --catalog
# Example with error explanation
journalctl -xe
# Update catalog database
sudo journalctl --update-catalog
Scripting and Automation
Log Monitoring Script
#!/bin/bash
# Monitor for errors and alert
journalctl -f -p err -o json | while read -r line; do
message=$(echo "$line" | jq -r '.MESSAGE')
unit=$(echo "$line" | jq -r '._SYSTEMD_UNIT // "unknown"')
echo "ERROR in $unit: $message"
# Add alerting logic here
done
Daily Error Report
#!/bin/bash
# Generate daily error report
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
TODAY=$(date +%Y-%m-%d)
echo "=== Error Report for $YESTERDAY ==="
echo -e "\n--- Errors by Service ---"
journalctl --since "$YESTERDAY" --until "$TODAY" -p err -o json \
| jq -r '._SYSTEMD_UNIT // "_no_unit_"' \
| sort | uniq -c | sort -rn | head -20
echo -e "\n--- Recent Errors ---"
journalctl --since "$YESTERDAY" --until "$TODAY" -p err -n 50 --no-pager
Log Export for Analysis
# Export to binary format (for backup/transfer)
journalctl --since "1 week ago" -o export > journal-export.bin
# Import on another system
journalctl --file=journal-export.bin
# Export to JSON for external analysis
journalctl --since today -o json > /tmp/today.json
# Filter and export
journalctl -u nginx --since today -o json | gzip > nginx-today.json.gz
Troubleshooting Scenarios
Service Won’t Start
# 1. Check recent service logs
journalctl -u myservice -n 50 --no-pager
# 2. Check with errors highlighted
journalctl -xe -u myservice
# 3. Check since last restart attempt
journalctl -u myservice --since "5 minutes ago"
# 4. Full verbose output
journalctl -u myservice -o verbose -n 20
System Boot Issues
# 1. Check previous boot (if current boot fails)
journalctl -b -1
# 2. Kernel messages during boot
journalctl -b -k
# 3. Critical messages during boot
journalctl -b -p crit
# 4. Boot timing
systemd-analyze blame
systemd-analyze critical-chain
Authentication Issues
# PAM/auth logs
journalctl -t sudo
journalctl -t sshd
journalctl _COMM=login
journalctl SYSLOG_FACILITY=10 # authpriv
# Failed auth in last hour
journalctl --since "1 hour ago" | grep -iE "fail|denied|invalid"
Disk/Storage Issues
# All kernel storage messages
journalctl -k | grep -iE "sd[a-z]|nvme|scsi|ata|disk"
# Filesystem errors
journalctl -k | grep -iE "ext4|xfs|btrfs|error|warning"
# SMART issues
journalctl | grep -i smart
Integration with Other Tools
Quick Command Reference
# Viewing
journalctl # All logs
journalctl -r # Newest first
journalctl -f # Follow
journalctl -n 50 # Last 50 lines
# Time filters
journalctl --since today
journalctl --since "1 hour ago"
journalctl -b # Current boot
journalctl -b -1 # Previous boot
# Source filters
journalctl -u nginx # By unit
journalctl -k # Kernel only
journalctl _PID=1234 # By PID
journalctl /usr/bin/nginx # By executable
# Priority filters
journalctl -p err # Errors and above
journalctl -p warning..err # Range
# Output formats
journalctl -o json # JSON
journalctl -o verbose # All fields
journalctl -o cat # Message only
# Maintenance
journalctl --disk-usage # Show size
journalctl --vacuum-size=100M # Reduce to size
journalctl --vacuum-time=2w # Remove old
journalctl --verify # Check integrity