Logging in systemd: working with journalctl¶
In modern Linux distributions (Ubuntu ≥ 16.04, Debian ≥ 8, RHEL/CentOS ≥ 7, Alma/Rocky ≥ 8), systemd not only manages services—it also provides centralized logging through journald and the utility *****journalctl******.
The systemd journal collects: - kernel messages dmesg), - logs from services such as nginx, sshd, docker, and others), - standard stdout/stderr streams from daemons, - audit events (if integrated with auditd).
Note
journald can operate in parallel with syslog (e.g., rsyslog or syslog-ng)—logs may be duplicated. However, journald often fully replaces the classic syslog.
Quick start: core commands¶
| Task | Command |
|---|---|
| View all logs (with pager) | journalctl |
| Last 10 entries | journalctl -n |
| Tail logs in real time | journalctl -f (analog of tail -f) |
| Logs since the last boot | journalctl -b |
| Logs for a specific service | journalctl -u nginx |
| Kernel logs | journalctl -k |
| Disk space used by the journal | journalctl --disk-usage |
Time and time zones¶
By default, journalctl displays local time. Verify that it’s configured correctly:
Check the output for lines like:
Managing the time zone¶
# List all available time zones
timedatectl list-timezones
# Set (e.g., for Moscow)
sudo timedatectl set-timezone Europe/Moscow
Viewing logs in UTC¶
Boot history¶
By default, logs from previous boots are not retained (they’re stored only in /run/log/journal/, which is cleared on reboot). To keep them, enable persistent storage:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
Or edit the configuration manually:
Uncomment and modify:
Working with boots¶
# List all saved boots
journalctl --list-boots
# Output:
# -2 abc123... Wed 2025-11-05 10:00:00 MSK—Wed 12:30:45 MSK
# -1 def456... Thu 2025-11-06 09:15:22 MSK—Thu 18:44:10 MSK
# 0 xyz789... Fri 2025-11-07 08:20:05 MSK—running
# Logs from the previous boot
journalctl -b -1
# Logs by boot ID
journalctl -b xyz789...
Log filtering¶
By time¶
# From a specified point until now
journalctl --since "2025-11-07 14:00:00"
# For a period
journalctl --since "2025-11-06" --until "2025-11-07 09:00:00"
# Convenient keywords
journalctl --since today
journalctl --since yesterday
journalctl --since "2 hours ago"
journalctl --until now
Note
Supported formats: YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, today, yesterday, 1 hour ago, 5min ago.
By service (unit)¶
# Nginx logs
journalctl -u nginx
# With .service extension (optional but correct)
journalctl -u nginx.service
# Multiple services at once
journalctl -u nginx -u php-fpm --since today
# Only nginx errors from the last 2 hours
journalctl -u nginx -p err --since "2 hours ago"
By process, user, group¶
# By PID (e.g., nginx master process)
journalctl _PID=12345
# By UID of a user
journalctl _UID=33 # e.g., www-data
journalctl _UID=$(id -u nginx)
# List all UIDs with entries
journalctl -F _UID
# Similarly for GID
journalctl -F _GID
By priority level (severity)¶
| Level | Code | Description |
|---|---|---|
emerg | 0 | System is unusable |
alert | 1 | Immediate action required |
crit | 2 | Critical errors |
err | 3 | Errors |
warning | 4 | Warnings |
notice | 5 | Significant events |
info | 6 | Informational messages |
debug | 7 | Debugging |
Examples:
# Only errors and higher (err, crit, alert, emerg)
journalctl -p err
# Same via numeric code
journalctl -p 3
# Nginx errors for the current boot
journalctl -u nginx -p err -b
Output formatting¶
Core options¶
--no-pager # output to stdout (for grep, tee, redirection)
--no-full # do not truncate long lines (default is truncated)
-n 50 # last 50 entries
-f # follow (live view of new entries)
Formatting Output¶
Formats (-o)**¶
| Format | Usage |
|---|---|
short (default) | Classic syslog style |
short-iso | Time in ISO 8601: 2025-01-07T15:30:45+03:00 |
short-precise | Time with microseconds |
cat | Only message text (without metadata) — handy for scripts |
json | JSON, one entry per line (machine‑readable) |
json-pretty | Human‑readable JSON (for debugging/analysis) |
verbose | All fields, including hidden _SOURCE_REALTIME_TIMESTAMP, _BOOT_ID, etc.) |
Examples:
# Human‑readable JSON for nginx
journalctl -u nginx -o json-pretty --since today
# Only message text
journalctl -u nginx -p err -o cat
# Export to a file for analysis
journalctl -b -u docker --no-pager > docker_boot.log
Managing journal size¶
Current size¶
Log cleanup¶
By size¶
By time¶
Note
Supported suffixes: s, m, h, days, weeks, months, years.
Persistent limits (in config)¶
Edit /etc/systemd/journald.conf:
After changes:
Note
Changes to journald.conf do not affect already accumulated logs — use --vacuum-* to clean up.
Advanced techniques¶
Search by content (with grep)¶
Event frequency analysis¶
Export and backup¶
Frequently Asked Questions¶
Q: Why does journalctl not show logs from previous reboots? A: Check whether Storage=persistent is enabled and whether /var/log/journal/ exists. Without this, logs are kept only in RAM /run.
Q: How do I disable journald and revert to rsyslog? A: You cannot completely disable journald (it's part of systemd), but you can: - Redirect logs to rsyslog via /etc/systemd/journald.conf or by using systemd-journald with SystemMaxUse=0 to disable logging. - Or disable journald as a source for rsyslog, leaving only it.
Q: Can logs be encrypted? A: journald does not support encryption out of the box. For this, use: - logrotate + gpg, - Or third‑party SIEM systems (Graylog, ELK, Loki + Promtail).