By Tux Harlow — Solnyxus editorial voice. Drafted with AI assistance; reviewed by the team.
You know the ritual. A service misbehaves, you type journalctl, the pager opens on a wall of text from three weeks ago, you mash G to reach the end, and then you squint at the screen like it owes you money. It works the way a phone book works for finding a plumber. Technically. These journalctl tips are the cure.
The systemd journal isn't a text file. It's an indexed, structured store, and journalctl is its query tool. Quit treating it like cat /var/log/messages with extra steps and it gets pleasant fast. Here are the flags I reach for daily, and what each one does.
Start with the unit
The single most useful filter is the unit name:
journalctl -u nginx.service
-u limits output to one systemd unit. Repeat it (-u nginx -u php-fpm) and you get two services interleaved in time order, which is perfect for spotting who fell over first. Blame is half the fun.
Add -f to follow new lines as they arrive, like tail -f:
journalctl -u nginx.service -f
And -n 50 shows only the last 50 lines instead of the entire history:
journalctl -u nginx.service -n 50 --no-pager
--no-pager prints straight to the terminal. You want that when you're piping into other tools or pasting into a ticket.
Slice by boot
The journal tags every entry with the boot it belongs to. List them:
journalctl --list-boots
Then ask for the current boot with -b, or the previous one with -b -1:
journalctl -b -1 -p err
That second one is my go-to for "it crashed overnight and rebooted." Errors from the boot before this one, right there. One catch, and it's a nasty one: if the journal only lives in memory, the previous boot is gone. More on that below.
Filter by priority
Syslog priorities run from 0 (emerg) to 7 (debug). -p shows the level you name and everything more severe:
journalctl -p warning -b
You can also give a range:
journalctl -p warning..err -b
On a noisy machine, -p err -b is usually the fastest way to find out whether anything is genuinely on fire. I'd start there every single time, and I'll defend that on any mailing list you like.
Filter by time
--since and --until take timestamps and friendly words:
journalctl --since "2 hours ago"
journalctl --since "2026-10-12 22:00" --until "2026-10-13 01:00"
journalctl --since yesterday --until today -u sshd.service
Stack this with -u and -p and you've got a proper query: which unit, how bad, and when. Scrolling can't compete with that.
Search inside messages
-g (long form --grep) filters message text with a regular expression:
journalctl -b -g 'timeout|refused'
Matching is case-insensitive when your pattern is all lowercase, and case-sensitive the moment it contains an uppercase letter. The man page says so. Everybody forgets, usually while wondering why -g Error found nothing. (Side note: this is the sort of thing you only learn by getting burned once. Consider this your free burn.)
Kernel messages, minus dmesg
-k shows kernel messages, the journal's version of dmesg, but with the boot and time filters you already know:
journalctl -k -b -1
It's handy for the "what did the disk say before it died" investigation, as long as the previous boot was kept.
Get structured with JSON
Every entry is a set of fields, not just a line. See them all with verbose output:
journalctl -u sshd.service -n 1 -o verbose
And export machine-readable output for scripts with -o json (one JSON object per line) or -o json-pretty:
journalctl -u sshd.service --since today -o json | jq -r '.MESSAGE'
That assumes you have jq installed. The real prize is working with fields like _SYSTEMD_UNIT, _PID or PRIORITY instead of regexing text and hoping. I get a little giddy about this one.
You can match on fields directly, too, without -u:
journalctl _SYSTEMD_UNIT=sshd.service _PID=1234
Make the journal remember
On many distributions the journal lives only in /run/log/journal, which vanishes at reboot. Whether yours persists depends on the distro's defaults and the Storage= setting in /etc/systemd/journald.conf. The default, auto, persists only if the directory /var/log/journal exists. So the classic fix is:
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
Or set Storage=persistent in journald.conf. After the next reboot, journalctl --list-boots should show more than one entry. If it still shows one, that blinking cursor is telling you something.
Keep it from eating the disk
Check how much space the journal uses:
journalctl --disk-usage
And trim it by size or age:
sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=30d
--vacuum-size deletes the oldest archived files until the total fits; --vacuum-time removes entries older than the period. For a permanent ceiling, set SystemMaxUse= in journald.conf and stop vacuuming by hand every quarter like it's a chore on a rota.
The ten-second incident routine
Something's wrong and you've no idea what. Run this:
journalctl -b -p err --no-pager | tail -n 40
journalctl -u the-suspect.service --since "1 hour ago" --no-pager
journalctl -k -p warning -b --no-pager
First, anything that errored this boot. Second, the suspect's recent history. Third, whether the kernel has complaints. Ten seconds, three commands, and you're working from evidence instead of vibes.
The journal's been quietly indexing everything the whole time. It was waiting for a better question. Go ask one, then read man journalctl, which is genuinely good, and check the companion knowledge-base article for the step-by-step persistence setup.