How to read logs with journalctl
Find the log lines you need with journalctl, by service, time, priority and boot, keep logs across reboots, and cap how much disk the journal uses.
Tested on Ubuntu 24.04 LTS, Debian 13 Stable, AlmaLinux 10
Before you start
- A Linux server with systemd
- Root or a user with sudo (or in the systemd-journal or adm group)
journalctl reads the systemd journal, which collects the logs of every service, the kernel and anything else that writes to syslog. The commands you'll use most are journalctl -u nginx (one service), journalctl -f (follow live), journalctl -p err -b (errors since boot) and journalctl --since "1 hour ago"; you can combine them freely.
This tutorial covers the filters in the order you're likely to need them, then making logs survive a reboot and capping their size. Everything was run on Ubuntu 24.04, Debian 13 and AlmaLinux 10.
The basics
sudo journalctl # everything, oldest first, in a pager
sudo journalctl -e # jump to the end
sudo journalctl -n 50 # the last 50 lines
sudo journalctl -f # follow new lines live (Ctrl+C to stop)
sudo journalctl -r # newest firstThe pager is less: / searches, G goes to the end, q quits. Add --no-pager when you pipe the output to another command or copy it into a ticket.
Without sudo, you only see your own user's logs, unless your user is in the systemd-journal group (or adm on Ubuntu and Debian).
Filter by service
sudo journalctl -u nginx
sudo journalctl -u ssh -u nginx -n 100 # several at onceThe SSH service is ssh on Ubuntu and Debian and sshd on AlmaLinux and Rocky Linux. systemctl list-units --type=service shows the names, and journalctl -F _SYSTEMD_UNIT lists every unit that has logged something.
For a script that logs with logger -t myscript "message", filter on the tag:
sudo journalctl -t myscriptFilter by time
sudo journalctl --since "1 hour ago"
sudo journalctl --since today
sudo journalctl --since "2026-10-21 09:00" --until "2026-10-21 10:30"
sudo journalctl -u nginx --since yesterday --until todayTimes are in the server's time zone (see set the time zone and NTP). --utc shows them in UTC instead.
Filter by priority
Every line has a priority from 0 (emerg) to 7 (debug). -p shows that level and everything more serious:
sudo journalctl -p err -b # errors and worse, this boot
sudo journalctl -p warning..err # a range| Level | Name | Typical use |
|---|---|---|
| 0-2 | emerg, alert, crit |
The system or a service is unusable |
| 3 | err |
Something failed |
| 4 | warning |
Something odd that didn't fail |
| 5-6 | notice, info |
Normal operation |
| 7 | debug |
Detail for developers |
journalctl -p err -b on a healthy server is short. Reading it after a deploy or an update is a quick way to catch a problem.
Filter by boot, and the kernel
sudo journalctl -b # this boot
sudo journalctl -b -1 # the boot before
sudo journalctl --list-boots
sudo journalctl -k # kernel messages (like dmesg), this boot-b -1 is how you find out why a server rebooted or what it was doing just before it hung. It only works if the journal is kept on disk; see the next section.
The kernel log is where the out-of-memory killer reports itself:
sudo journalctl -k | grep -i -E 'out of memory|oom-kill'Search and change the output
sudo journalctl -u ssh --grep "Failed password"
sudo journalctl -u nginx -o short-iso # full ISO timestamps
sudo journalctl -u myapp -o cat # the messages only, no prefix
sudo journalctl -n 1 -o json-pretty # every field of an entry--grep takes a regular expression and is case-insensitive when the pattern is all lower case. json-pretty shows the fields you can filter on directly, such as _PID=1234, _UID=1000 or _COMM=sudo:
sudo journalctl _COMM=sudo --since today # who used sudo todayKeep logs after a reboot
The journal is kept on disk if /var/log/journal exists, and only in memory (lost at reboot) if it doesn't. That's the Storage=auto default. Check which you have:
journalctl --header | grep -m1 'File path'A path under /var/log/journal means persistent; /run/log/journal means in memory. On Ubuntu and Debian the directory exists out of the box. On AlmaLinux and Rocky Linux it often doesn't, because rsyslog writes the classic text files in /var/log instead.
To make it persistent everywhere, say so in a drop-in file:
sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/50-storage.conf <<'EOF'
[Journal]
Storage=persistent
EOF
sudo systemctl restart systemd-journald
sudo journalctl --flushCheck it worked
journalctl --header | grep -m1 'File path'The path now starts with /var/log/journal/. After the next reboot, journalctl --list-boots lists more than one boot.
Limit how much disk the journal uses
journalctl --disk-usageBy default the journal stops growing at 10% of the file system (and at most 4 GB). On a small disk you may want less. Add the limits to the same drop-in file:
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1monthSystemMaxUse caps the total; MaxRetentionSec drops entries older than that. Apply it with sudo systemctl restart systemd-journald, and check the combined result with:
systemd-analyze cat-config systemd/journald.confTo free space right now, without changing the settings:
sudo journalctl --vacuum-size=200M
sudo journalctl --vacuum-time=2weeksVacuuming removes only archived journal files, never the one being written, so it may free less than you expect until the active file is rotated (sudo journalctl --rotate does that first).
Troubleshooting
-- No entries --. Nothing matched. The unit name may be wrong (ssh vs sshd), or the time window too narrow. Drop the filters one at a time.
Hint: You are currently not seeing messages from other users and the system. You ran it without sudo. Add sudo, or add your user to the systemd-journal group.
Specifying boot ID or boot offset has no effect, no persistent journal was found. The journal is in memory only, so earlier boots are gone. Make it persistent as above; it helps from the next boot on.
Journal file ... is truncated, ignoring file. Usually left from a crash or a full disk. sudo journalctl --verify lists the damaged files; deleting those files from /var/log/journal/ is safe.
Next steps
- Free disk space when the journal or anything else has grown: find and free disk space.
- Turn your own app into a service whose output lands here: write a systemd service.
- Track down a process that's slowing the server: troubleshoot high CPU and memory.
Doing it on VPSNine
If a VPSNine server won't boot far enough to let you in over SSH, the serial console shows the boot messages as they happen, and rescue mode lets you read the journal files from outside with journalctl -D /mnt/var/log/journal. Available on Ubuntu 24.04, Debian 13, AlmaLinux 10 and every other image, on all plans.