journalctl Cheat Sheet: Tail, Filter and Follow Linux Logs

journalctl Cheat Sheet: Tail, Filter and Follow Linux Logs

journalctl cheat sheet for real work: tail logs, grab the last 100 lines, follow a live service and filter by unit or time — copy-paste commands that just work.

HUMANby @mrsaynothing54d7 min read

The cheat-sheet map

journalctl pick your situation follow a live service -u <svc> -f catch up on history -u <svc> -n 100 a time window --since "1 hour ago" only failures -p err -b crashed last boot -b -1 journal ate the disk --vacuum-size=500M 90% of why-is-this-service-down moments: journalctl -u <service> -f
fig 1 — the cheat-sheet map. Find your situation; click the branch for the exact flags.

What is journalctl and why not just read /var/log/syslog?

Old-school Linux logging wrote plain text files under /var/log — syslog, auth.log, messages. systemd replaced that with the journal: a binary, indexed log managed by systemd-journald. Plain grep cannot read it; journalctl is the only front door, and in exchange you get filtering by service, time, boot and severity without regex gymnastics.

The mental model is simple: the journal stores everything, and journalctl is the query tool. A service does not need its own log file — anything it writes to stdout/stderr while running under systemd lands in the journal automatically. That is why journalctl -u nginx works even when you have no idea where nginx configured its error log.

One caveat: on some minimal installs the journal is volatile (stored in /run, wiped on reboot) because /var/log/journal does not exist. Fix it once:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal

verify: ls /var/log/journal → directory exists — boots accumulate instead of wiping

How do I see the last 100 lines of a log?

-n limits output to the newest N lines (default is 10):

journalctl -n 100                      # last 100 lines of everything
journalctl -u nginx -n 100             # last 100 lines from one unit
journalctl -n 100 --no-pager           # print and exit — perfect for piping

--no-pager matters more than it looks: without it journalctl opens less and your script, pipe or ssh one-liner hangs waiting for a keypress. Any command you pipe onward should carry it.

How do I follow logs live, like tail -f?

The -f flag is journalctl's tail -f — it streams new entries as they happen:

journalctl -f                    # everything, live
journalctl -u sshd -f            # just the SSH daemon, live
journalctl -u ollama -f -n 50    # live, but start with the last 50 lines

This is the command to run in a second terminal while you restart a service in the first one: systemctl restart nginx in one pane, journalctl -u nginx -f in the other, and the cause of the crash usually announces itself within seconds. I run this exact loop on my homelab every time a container or service misbehaves.

How do I show logs for a specific service?

-u filters by systemd unit:

journalctl -u nginx                    # one unit, all history
journalctl -u nginx -u redis           # several units at once
journalctl _SYSTEMD_UNIT=nginx.service # the exact-match alternative
-u <service> shows nothing but the service clearly runs?

Units can spawn helper units that keep the interesting output — a failing web app sometimes logs the real error under a different unit. Find the actual unit name first:

systemctl list-units --type=service | grep -i <guess>

verify: systemctl list-units --type=service | grep -i <guess> → the real unit name

The same -u pattern works for timers (systemctl list-timers shows names) and user services — for anything running under systemd --user add --user:

journalctl --user -u pipewire -n 50

How do I filter logs by time?

Relative windows beat exact timestamps when something is down.

--since and --until take timestamps, but they also accept forgiving relative phrasing:

journalctl --since "1 hour ago"
journalctl --since "2026-09-01 09:00" --until "2026-09-01 12:00"
journalctl --since today
journalctl --since yesterday --until now -u cron

Pair a time window with a unit and you have incident triage in one line: "what did the API log between 09:00 and when it fell over?" That is faster than any log aggregator for a single box.

How do I show only errors (or warnings)?

-p filters by priority, using syslog severity names:

journalctl -p err -b              # errors only, since this boot
journalctl -p warning..alert -u nginx   # a range of severities

Priorities in descending order: emerg, alert, crit, err, warning, notice, info, debug. When a box is "acting weird", journalctl -p err -b --since today is the fastest sanity check — it answers "is anything actually failing?" without noise from routine info lines.

How do I see logs from the previous boot?

The crash you rebooted away is still in the journal.

Services that crash at startup produce log lines before your current boot, and journalctl silently shows only the current one. -b selects boots:

journalctl -b                 # current boot only
journalctl -b -1              # previous boot
journalctl -b -1 -u sshd      # why SSH died last time
journalctl --list-boots       # index of stored boots

This is the single most useful flag for "it broke and I rebooted it and now I can't see the error" — the error is still there, one boot back.

Quick reference: the flags worth memorising

all follow lines time severity boot disk output kernel
Goal Command
Follow one service live journalctl -u <svc> -f
Last 100 lines journalctl -n 100
Since an hour ago journalctl --since "1 hour ago"
Errors this boot journalctl -p err -b
Previous boot journalctl -b -1
Disk usage of the journal journalctl --disk-usage
Machine-readable output journalctl -o json-pretty
Kernel messages only journalctl -k

How do I stop the journal filling my disk?

Check what it costs, then cap it:

journalctl --disk-usage
sudo journalctl --vacuum-size=500M     # keep newest 500 MB
sudo journalctl --vacuum-time=30d      # keep newest 30 days

To make a cap permanent, set SystemMaxUse=500M under the [Journal] section in /etc/systemd/journald.conf, then sudo systemctl restart systemd-journald. Between the size cap and the boot filter above, the journal stays a tool rather than a slow disk leak.

verify: journalctl --disk-usage → total below your 500M cap

journalctl vs dmesg vs /var/log — which do I check first?

  • journalctl — application and service behaviour. Anything systemd manages is here, indexed and filterable. Default first stop.
  • journalctl -k / dmesg — kernel and hardware: OOM kills, USB resets, disk errors. If a process died mysteriously, look for the OOM killer here before blaming the app.
  • /var/log/<app>/ — only for apps that do their own file logging (nginx access logs, PostgreSQL). Even then, startup errors usually still land in the journal.

The same workflow extends to local AI services — when an ollama serve unit stalls, journalctl -u ollama -n 100 shows the model load failure immediately, as covered in the Ollama vs LM Studio comparison.

That is the whole cheat sheet: -u for unit, -f to follow, -n for lines, --since for time, -p for severity, -b for boots. Six flags cover nearly every log question a Linux box will ask you — and when the question is why a systemd service won't start, these flags are the whole investigation.