Journal and Logging | Linux - Wyatt's Notes
systemd-journald Architecture
Section titled “systemd-journald Architecture”systemd-journald is the central logging daemon in systemd-based systems. It collects log messages From multiple sources and stores them in a structured, indexed binary format.
flowchart LR A["Kernel<br />(dmesg)"] --> J["journald"] B["Services<br />(stdout/stderr)"] --> J C["syslog()"] --> J D["Audit subsystem"] --> J J --> S["/run/log/journal/<br />(volatile)"] J --> P["/var/log/journal/<br />(persistent)"] J --> F["Forward to<br />rsyslog/syslog"]Log Sources
Section titled “Log Sources”| Source | Description |
|---|---|
| stdout/stderr | All service output captured by systemd |
| Kernel messages | printk() messages (equivalent to dmesg) |
| syslog() | Traditional syslog calls |
| Audit events | Kernel audit subsystem |
| /dev/kmsg | Kernel log device |
| Internal journal | Journal”s own diagnostic messages |
Storage Modes
Section titled “Storage Modes”Volatile (/run/log/journal/): - Stored in tmpfs (RAM) - Lost on reboot - Default when /var/log/journal/ does not exist - Size limited by RuntimeMaxUse (default: 10% of RAM)
Persistent (/var/log/journal/): - Stored on disk - Survives reboots - Created with: mkdir -p /var/log/journal && systemd-tmpfiles --create --prefix /var/log/journal - Size limited by SystemMaxUse (default: 10% of filesystem)## Check current storage modejournalctl --header | grep "Storage"
## Enable persistent storagesudo mkdir -p /var/log/journalsudo systemd-tmpfiles --create --prefix /var/log/journalsudo systemctl restart systemd-journald
# Verifyls -la /var/log/journal/# drwxr-xr-x 2 root systemd-journal 4096 ...journalctl
Section titled “journalctl”Basic Usage
Section titled “Basic Usage”# Show all journal entries (newest first)journalctl
# Show boot log (current boot)journalctl -b
# Show previous bootjournalctl -b -1
# Show specific boot by boot IDjournalctl --list-bootsjournalctl -b <boot-id>
# Follow live outputjournalctl -f
# Show kernel messagesjournalctl -kjournalctl -k -f
# Show since a specific timejournalctl --since "2026-04-01"journalctl --since "2026-04-01 09:00:00"journalctl --since "2 hours ago"journalctl --since yesterdayjournalctl --since today
# Show until a specific timejournalctl --until "2026-04-01 10:00:00"journalctl --since "1 hour ago" --until "now"Filtering
Section titled “Filtering”# By unit (service)journalctl -u nginxjournalctl -u nginx -u postgresql # multiple units
# By PIDjournalctl _PID=12345
# By executablejournalctl _COMM=sshd
# By systemd unitjournalctl _SYSTEMD_UNIT=nginx.service
# By priority (0=emerg, 1=alert, 2=crit, 3=err, 4=warning, 5=notice, 6=info, 7=debug)journalctl -p errjournalctl -p warning..err # rangejournalctl -p 3 # error
# By facility (syslog facility codes)journalctl -f FACILITY=daemon
# By message contentjournalctl --grep="connection refused"journalctl --grep="OutOfMemory"
# By bootjournalctl -b 0 # current bootjournalctl -b -1 # previous boot
# By user sessionjournalctl _UID=1000
# Combine filtersjournalctl -u nginx --since "1 hour ago" -p errjournalctl -u sshd _COMM=sshd --grep="Failed"Output Formats
Section titled “Output Formats”# Default (human-readable)journalctl
# Short (default, but without legend)journalctl -o short
# Verbose (show all fields)journalctl -o verbose
# JSON (one entry per line)journalctl -o json
# JSON pretty-printedjournalctl -o json-pretty
# Export format (for journalctl --import)journalctl -o export
# Cat (show message only, no metadata)journalctl -o cat
# With field valuesjournalctl -o with-unitUseful Fields
Section titled “Useful Fields”# Common journal fields_SYSTEMD_UNIT # systemd unit name_COMM # executable name_PID # process ID_UID # user ID_GID # group ID_HOSTNAME # hostname_TRANSPORT # source: journal, syslog, kernel, etc._PRIORITY # syslog priority (0-7)_MESSAGE # log message_MESSAGE_ID # structured message ID_EXE # executable path_CMDLINE # command line_SOURCE_REALTIME # timestamp (microseconds since epoch)_BOOT_ID # unique boot identifier_MACHINE_ID # unique machine identifier
# Show all fields for recent entriesjournalctl -o verbose -n 5
# Filter by specific fieldjournalctl _HOSTNAME=server01journalctl _TRANSPORT=syslogPractical Examples
Section titled “Practical Examples”# Find all failed service starts in the last 24 hoursjournalctl --since yesterday -p err --grep="Failed"
# Track all SSH login attemptsjournalctl -u sshd -o cat | grep -E "Accepted|Failed"
# Show nginx access logs with timestampsjournalctl -u nginx --since "1 hour ago" -o cat
# Find OOM killer eventsjournalctl -k --grep="Out of memory"journalctl --grep="invoked oom-killer"
# Show the last 100 lines of a service's logjournalctl -u myapp -n 100
# Export logs for analysisjournalctl -u nginx --since "2026-04-01" -o json-pretty > nginx_april.json
# Pipe to jq for analysisjournalctl -u nginx --since "1 hour ago" -o json | \ jq -r 'select(.PRIORITY >= 4) | .__REALTIME_TIMESTAMP + " " + .MESSAGE'journald Configuration
Section titled “journald Configuration”[Journal]
# Storage mode: auto, volatile, persistent, noneStorage=auto
# Maximum disk space for persistent storageSystemMaxUse=500M# Minimum disk space to keep (before vacuuming)SystemKeepFree=1G# Maximum size of individual journal fileSystemMaxFileSize=50M# Maximum time to keep journal filesMaxFileSec=1month
# Maximum disk space for volatile storage (in RAM)RuntimeMaxUse=100MRuntimeKeepFree=50MRuntimeMaxFileSize=10M
# Compress journal files (default: yes)Compress=yes
# Split journal files by UID (one per user)SplitMode=uid
# Forward to traditional syslog daemonForwardToSyslog=yes
# Forward to wall (broadcast to logged-in users)ForwardToWall=no
# Maximum rate of messages from a single serviceRateLimitIntervalSec=30sRateLimitBurst=10000
# Line rate limit (per-service)LineRateLimitIntervalSec=30sLineRateLimitBurst=1000
# File sealing (prevent tampering)Seal=yes
# ReadKMsg (kernel messages)ReadKMsg=yes
# TTYPath (console output)TTYPath=/dev/console# After changing configurationsystemctl restart systemd-journald
# Verify configurationjournalctl --headerLog Rotation
Section titled “Log Rotation”systemd-tmpfiles
Section titled “systemd-tmpfiles”systemd-tmpfiles manages temporary files and directories, including journal file rotation.
# Systemd's built-in journal cleanup# Automatically cleans up journal files based on SystemMaxUse/SystemKeepFree
# Manual vacuumjournalctl --vacuum-size=500M # keep at most 500Mjournalctl --vacuum-time=7d # keep at most 7 daysjournalctl --vacuum-files=10 # keep at most 10 journal files
# Check disk usagejournalctl --disk-usagelogrotate
Section titled “logrotate”logrotate is the traditional log rotation tool, still widely used for application-specific logs.
/var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx adm sharedscripts postrotate [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid) endscript}/var/log/myapp/*.log { daily rotate 30 compress delaycompress missingok notifempty create 0644 myapp myapp size 100M maxsize 200M dateext dateformat -%Y%m%d}# Test configurationlogrotate -d /etc/logrotate.conf # debug mode (dry run)
# Force rotationlogrotate -f /etc/logrotate.conf
# Verify a specific configlogrotate -d /etc/logrotate.d/nginxIntuition
Section titled “Intuition”Processes are programs in execution, each with its own memory space and priority. Systemd manages the lifecycle of services, starting them at boot and restarting them if they fail. Understanding process states (running, sleeping, stopped, zombie) helps you diagnose why a service is not responding. Signals like SIGTERM and SIGKILL provide graceful and forceful ways to control processes.