, ,

Reading Linux Logs With journalctl and the systemd Journal (Linux for Beginners, Part 10)

Read Linux logs the fast way. journalctl by unit, boot, priority and time, the volatile-journal default that silently loses your logs, and how to keep the journal off your disk.

Linux for Beginners · Part 10 of 24

A server fell over at 03:00. You were asleep, the watchdog rebooted it, and by morning it was serving traffic again as if nothing happened. Now you want to know what killed it. You log in, reach for the logs from before the reboot, and the machine tells you they were never there.

$ journalctl -b -1
Specifying boot ID or boot offset has no effect, no persistent
journal was found.

That one line is the whole lesson of this part in miniature. The systemd journal was recording everything, but it was writing to memory, and memory does not survive a reboot. The tool you drive it with is journalctl, and it can slice logs by service, by boot, by priority and by time. First you learn to read the journal. Then you make sure it is still there when you need it most.

Here is the same tool working the way it should, annotated so nothing is a mystery.

$ journalctl -u ssh -b            # ssh unit, this boot only
$ journalctl -u ssh -b -p err     # only error priority and worse
$ journalctl -f                   # follow new lines live, like tail -f
$ journalctl --since '10 min ago' # time window, plain English works
$ journalctl -k -b                # kernel messages, this boot (dmesg)
$ journalctl -u nginx -e          # jump to the end, newest lines

Every one of those is a filter. -u is by unit, -b is by boot, -p is by priority, --since is by time, -k is kernel only. Stack them and you go from ten thousand lines to the five that matter.

Bottom line
On modern distros the systemd journal collects log messages from the kernel, services and everything in between into one binary store, and journalctl reads it. Learn four filters, -u, -b, -p and --since, and you can find any event fast. Then set the journal to persistent so those events outlive a reboot, and cap its size so it never fills the disk.

If you came from Windows Event Viewer or a hosting panel where logs were a scrolling web page, this is the command-line version of the same job, only faster once your fingers know it. And if you already run a fleet, the part that pays for itself is the priority and boot filtering, because it turns a blind grep through a giant file into a precise query.

Where Linux logs actually live

There are two log worlds on a typical Linux box, and knowing which one you are in saves a lot of confusion. The old world is plain text files under /var/log, written by a syslog daemon such as rsyslog. The new world is the systemd journal, a binary store that journald writes and only journalctl reads. On Debian and Ubuntu both worlds run at once: journald collects everything, and rsyslog also writes the familiar /var/log/syslog. On RHEL 9, Rocky and AlmaLinux the journal is the primary store and rsyslog is present but leans on the journal underneath.

Where a log line goesKernelServicesYour commandsjournaldcollects everythingJournal filesread by journalctl/var/log/syslogvia rsyslog, textOne collector, journald, feeds both the binary journal and, on Debian family, a text copy.

Why a binary store at all, when text files worked for decades? Because the journal keeps structured fields on every entry, so you can filter by the exact unit, the priority, the process ID or the boot, without a regular expression guessing at line shapes. A few plain text files still live on under /var/log and are worth knowing.

PathWhat it holdsFamily
/var/log/syslogGeneral system messagesDebian, Ubuntu
/var/log/messagesGeneral system messagesRHEL family
/var/log/auth.logLogins, sudo, sshdDebian, Ubuntu
/var/log/secureLogins, sudo, sshdRHEL family
/var/log/journal/Persistent binary journalBoth, when enabled

Here is where I disagree with a lot of older tutorials. Reaching for grep sshd /var/log/auth.log still works, but it is the slow path now. journalctl -u ssh -p warning -b asks a sharper question and gets a cleaner answer, because you are filtering on real fields instead of hoping a word appears on the right line. Learn the journal first. Fall back to the text files when a tool only writes there.

The journalctl flags you will use every day

Running journalctl with no arguments dumps the whole journal into a pager, oldest first, which is rarely what you want. The value is in the filters. These are the ones that carry the day.

FlagWhat it doesExample
-uFilter to one unitjournalctl -u nginx
-bThis boot; -b -1 the previous onejournalctl -b
-pPriority and worsejournalctl -p err
-fFollow live, like tail -fjournalctl -f
--since, --untilTime windowjournalctl --since '09:00'
-kKernel messages onlyjournalctl -k
-eJump to newest entriesjournalctl -u nginx -e
-rReverse, newest firstjournalctl -r

They combine. The single query I type more than any other, when a service just died, is this:

$ journalctl -u myapp -b -p err --no-pager
Jul 03 03:07:12 web01 myapp[1834]: FATAL: could not connect to
                                   database: connection refused
Jul 03 03:07:12 web01 systemd[1]: myapp.service: Main process
                                   exited, code=exited, status=1/FAILURE
Jul 03 03:07:12 web01 systemd[1]: myapp.service: Failed with result
                                   'exit-code'.

That is the crash from the opening scenario, and it took one line to find. The application could not reach its database, exited with status 1, and systemd marked the unit failed. No scrolling, no grep. The --no-pager flag prints straight to the terminal instead of opening a pager, which is what you want when you are copying output into a ticket or a script.

Priority levels, and why -p err is your friend

Every journal entry carries a priority, a number from 0 to 7 borrowed straight from the old syslog standard. Lower numbers are more severe. When you pass -p err you are saying show me priority 3 and everything worse, so errors, criticals, alerts and emergencies, and drop the routine chatter. On a busy box that filter alone cuts the noise by an order of magnitude.

NumberNameMeans
0emergSystem is unusable
1alertAct immediately
2critCritical condition
3errSomething failed
4warningMight become a problem
5noticeNormal but notable
6infoRoutine information
7debugVerbose detail

You can name the level or use the number, so -p 3 and -p err are the same. A pair I lean on when triaging a fresh incident:

$ journalctl -p err -b               # everything that errored this boot
$ journalctl -p warning..err -b      # just warnings through errors

The range form with two dots is the one most people never learn, and it is the sharpest of the lot. It hides the emergencies you probably already know about and the info noise you do not care about, leaving the middle band where the early signs of trouble usually hide.

The default that loses your logs

This is the part that bites real people, so it gets the most room. Whether your logs survive a reboot comes down to one setting, Storage, in /etc/systemd/journald.conf, and its behaviour is not obvious. The value that ships on most systems is auto, and auto means the journal is persistent only if the directory /var/log/journal already exists. If it does not, the journal writes to /run/log/journal, which is memory, and memory is wiped on reboot.

Why the default catches Ubuntu users out

On many minimal and cloud Ubuntu images the /var/log/journal directory does not exist, so Storage=auto quietly resolves to volatile, and your logs live only until the next reboot. RHEL 9 ships Storage=persistent in its config, which creates the directory for you, but even there a bare install may not have it populated until the setting takes effect. The honest rule is to not trust the default. Check it, and make it persistent on purpose.

What Storage=auto decidesDoes /var/log/journalexist?No: /run/log/journalmemory, gone on rebootYes: /var/log/journaldisk, survives rebootnoyes

Making it persistent is two commands. Set Storage=persistent, then tell journald to pick it up.

$ sudo mkdir -p /var/log/journal
$ sudo sed -i 's/^#Storage=auto/Storage=persistent/' 
       /etc/systemd/journald.conf
$ sudo systemctl restart systemd-journald

$ journalctl --list-boots        # now shows more than one line
 -1 8f3c... Thu 2026-07-02 22:10:04 UTC ... Fri 2026-07-03 03:00:11 UTC
  0 a17d... Fri 2026-07-03 03:00:44 UTC ... Fri 2026-07-03 09:31:52 UTC

The moment journalctl --list-boots shows a boot with a -1 next to it, you have history that survives a restart, and journalctl -b -1 will hand you the logs from before the last reboot instead of that flat refusal at the top of this article. My verdict is plain: on any machine you will ever need to investigate after a crash, which is all of them, set Storage=persistent the day you build it. The volatile default trades away exactly the logs you reach for at the worst moment.

Where this breaks in the real world
A junior admin swears a service logged an error before the box rebooted, but journalctl -b -1 comes up empty and they start doubting themselves. Nothing is broken. The journal was volatile, the reboot wiped it, and there was never anything to find. The tell is a single line at the top of any boot query: no persistent journal was found. See that once and the first fix is always the same, create /var/log/journal and restart journald, before you chase a ghost.

Keeping the journal off your disk

Once the journal is persistent, the obvious worry is that it grows without bound. It does not. journald caps itself, and the default cap is SystemMaxUse set to 10 percent of the filesystem the journal lives on, with that calculated value capped at 4 GB. It also keeps 15 percent of the disk free by default through SystemKeepFree. So on a 100 GB root, the journal will use at most about 4 GB, not 10, because the 4 GB ceiling wins. Check what it is using now with one command.

$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.
Journal size against its default capIn use now1.2 GBSystemMaxUse cap4 GB10 percent of 100 GB10 GB, but capped to 4The 4 GB ceiling wins, so the journal never reaches the full 10 percent here.

When you want to reclaim space now, or trim history before archiving a box, vacuum does it by size or by age.

$ sudo journalctl --vacuum-size=500M   # keep at most 500 MB
$ sudo journalctl --vacuum-time=2weeks  # drop anything older than 2 weeks
Vacuuming done, freed 712.3M of archived journals.

To make a smaller cap permanent, set SystemMaxUse=500M in journald.conf and restart journald, the same edit-and-restart pattern as the storage change. On a small VPS with a 20 GB disk, I set an explicit cap rather than trust the percentage, because 10 percent of a tiny disk is still enough log to matter when the disk fills.

Real interview question
"A service failed to start after the last reboot and you need to know why. Walk me through it." The answer they want, in order: systemctl status name for the summary, then journalctl -u name -b -1 -p err to read that unit’s errors from the previous boot. The follow-up trap is whether -b -1 even works. If the journal was volatile, it does not, and naming that failure mode out loud is what separates a real operator from someone reciting flags.
Try it on your own box
Make your journal persistent and prove it. Run sudo mkdir -p /var/log/journal then sudo systemctl restart systemd-journald. Reboot the machine, log back in, and run the exact verify command:

journalctl --list-boots | wc -l

If that number is 2 or more, your logs now cross reboots. Before the change it would have printed 1, because only the current boot existed.

Questions I actually get

Do I still need rsyslog if I have the journal? Not for most single servers. The journal covers you. Keep rsyslog when something depends on the text files, or when you forward logs to a central collector that speaks syslog. Otherwise the journal is enough on its own.

What does the -x flag actually add? journalctl -xe attaches catalog text with suggested explanations to some messages. It helps on unfamiliar errors and becomes noise once you know the system. Useful when you are stuck, skippable when you are not.

Why does journalctl open a pager and how do I stop it? It pipes through less so long output is scrollable. Add --no-pager for a straight dump, which is what you want in scripts, or set -e to jump to the end and keep the pager.

Can a normal user read the journal? A user sees their own messages. To read the full system journal, either use sudo or add the account to the systemd-journal group, which grants read access without full root. Groups came up back in Part 5.

How do I watch two services at once? Repeat the flag: journalctl -u nginx -u php-fpm -f follows both live in one stream, which is how you catch a web server and its backend failing in the same instant.

Logs stop being a wall of text once you filter them. You ask for one unit, one boot, one priority, one time window, and the journal answers. Set it persistent on day one, cap it so it never fills the disk, and the next 03:00 incident leaves you a trail to follow instead of an empty prompt. Part 11 moves from reading the system to the disks underneath it, partitions, filesystems and mounting. Following the whole path? The Linux for Beginners complete guide lists every part in order, and the same investigate-after-the-fact instinct shows up in the VMware for Beginners and Cloud for Beginners guides.

Linux for Beginners · Part 10 of 24
« Previous: Part 9  |  Complete Guide  |  Next: Part 11

References

journalctl(1) manual page
journald.conf, Storage and SystemMaxUse
systemd-journald service
Red Hat: enable persistent journal logging

About The Author


Discover more from Journal of Intelligent Infrastructure – By Dr Pranay Jha

Subscribe to get the latest posts sent to your email.

Leave a Reply

Your email address will not be published. Required fields are marked *

Architect’s Toolkit

About the Author

Dr. Pranay Jha is a Cloud and AI Consultant with 18+ years of experience in hybrid cloud, virtualization, and enterprise infrastructure transformation. He specializes in VMware technologies, multi-cloud strategy, and Generative AI solutions. He holds a PhD in Computer Applications with research focused on Cloud and AI, has published multiple research papers, and has been a VMware vExpert since 2016 and a VMUG Community Leader.

Discover more from Journal of Intelligent Infrastructure - By Dr Pranay Jha

Subscribe now to keep reading and get access to the full archive.

Continue reading