Linux Logs: Architecture and Where to Look
When a server misbehaves, the first useful question is rarely "why did this happen" — it is "where do I even start looking." Almost every answer leads to the same place: the logs. A log is a running record of events that a system or program writes as it operates — who logged in and when, which service started or crashed, which request failed and why. journalctl already covered systemd's centralized, live log tool in detail. This article steps back and lays out the full picture: how many independent logging layers Linux actually has, where each one stores its data, and how they relate to each other — the map the rest of this module builds on.
Why There Is No Single Log
A newcomer often expects "the log" to be one obvious place. In practice, Linux logging is a stack of independent layers, each operating at a different level of the system:
| Layer | Who writes it | Where it lives | When you check it |
|---|---|---|---|
| Kernel | The Linux kernel itself | An in-memory ring buffer (dmesg), usually also relayed to the journal |
Hardware, driver, memory, and boot-related problems |
| systemd journal | systemd-journald |
Binary, structured storage in /run/log/journal/ or /var/log/journal/ |
Service status, boot sequence — via journalctl |
| Syslog (rsyslog) | The rsyslog service |
Plain-text files under /var/log/ |
Legacy applications, forwarding to a central log server, long-term text archives |
| The application itself | The application or service's own code | Varies — its own file, stdout/stderr relayed into the journal, or an external system |
Application-level errors, business-logic events |
These layers do not replace each other; each answers a different question. A kernel-level failure, such as a failing disk controller, will never show up in an application's log, and a bug in an application's business logic has nothing to do with the kernel at all.
Info
On a modern Ubuntu Server install these layers are not fully separate: rsyslog typically reads events from systemd-journald and writes them back out to traditional text files. That means the same event can often be found in both journalctl and /var/log/syslog — not two competing systems, but two stages of one pipeline.
What's Actually in /var/log/
-rw-r----- 1 syslog adm 812K Jul 24 11:02 auth.log
-rw-r----- 1 root adm 45K Jul 24 08:12 boot.log
-rw-r----- 1 root root 1.9M Jul 24 08:12 dmesg
-rw-r--r-- 1 root root 24K Jul 20 06:25 dpkg.log
drwxr-xr-x 2 root root 4.0K Jul 24 08:12 journal
-rw-r----- 1 syslog adm 2.1M Jul 24 11:05 kern.log
-rw-r----- 1 syslog adm 3.4M Jul 24 11:05 syslog
-rw-rw-r-- 1 root utmp 0 Jul 24 08:12 wtmp
The most frequently used files:
| File / directory | Contents |
|---|---|
syslog |
General system messages collected from most services |
auth.log |
Authentication and authorization events: logins, sudo invocations, SSH connection attempts |
kern.log |
Kernel messages only, in plain text |
dmesg |
A plain-text snapshot of the kernel ring buffer taken at boot |
dpkg.log |
History of packages installed, upgraded, or removed via APT/dpkg |
boot.log |
Messages printed during the boot sequence |
journal/ |
systemd-journald's binary data store |
wtmp, btmp, lastlog |
Structured binary login-history files, read via last, lastb, and lastlog — not plain text |
Warning
auth.log is owned by syslog:adm with mode 640 — an ordinary user cannot read it directly, only members of the adm group or root/sudo can. This is a deliberate security boundary: authentication activity is treated as sensitive. wtmp, btmp, and lastlog are not plain text either; opening them with cat produces unreadable binary noise, because they are structured binary files meant to be read only through their dedicated tools.
On the RHEL/CentOS/Rocky family, file names differ slightly — secure instead of auth.log, messages instead of syslog in most default configurations — but the underlying logic is the same.
logrotate: Why Log Files Don't Grow Forever
A busy server can write hundreds of megabytes of logs per day. If those files grew without limit, disk space would eventually run out. logrotate — a periodically run tool that automatically rotates log files — solves this.
/var/log/syslog
{
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
What this configuration means:
daily— the file is rotated once a day;rotate 7— only the last 7 rotated copies are kept; anything older is deleted;compress— old copies are compressed as.gz, saving disk space;missingok— do not error out if the file does not exist;notifempty— do not rotate an empty file, avoiding a pointless empty archive;- the command inside
postrotatetells the writing service that the file is fresh again, typically by sending it a signal.
In practice this looks like: when syslog is rotated, it is renamed to syslog.1, the previous syslog.1 is compressed into syslog.2.gz, and so on, up to the rotate 7 limit.
logrotate itself normally runs automatically through a daily cron job or a systemd timer — you don't have to trigger it by hand, but understanding its configuration is valuable when diagnosing problems such as a full disk.
Danger
Deleting a log file that a running service is still writing to, directly with rm, is a risky shortcut. The file disappears from the directory listing, but the process holding it open keeps writing into that now-invisible file, and the disk space is never reclaimed. This exact situation, and the correct way to fix it, is covered in The /proc File System. Log files should always be managed through logrotate, or by properly signaling the writing service — never by deleting the file directly.
postrotate vs copytruncate: How the Writer Keeps Up
The postrotate block above exposes the one hard problem in rotation: after the file is renamed to .1, the service is still writing to the old, renamed file until it is told the file is fresh. The postrotate signal (a HUP, or rsyslog-rotate here) is what makes it reopen the original path. A service that cannot be signaled to reopen its log needs the alternative copytruncate directive instead:
| Directive | How it rotates | Trade-off |
|---|---|---|
postrotate (rename + signal) |
Renames the file, then signals the service to reopen the original name | No data lost, but needs a service that reopens its log on signal |
copytruncate |
Copies the current file to the archive, then truncates the original in place | Works with any writer, but log lines written in the gap between copy and truncate are lost |
copytruncate is the standard answer for an application that holds its log file open and offers no reopen signal — at the cost of that small race window. Knowing why it exists, and its data-loss caveat, is a frequent interview follow-up to "how does log rotation work."
A rotation rule can be tested without waiting for the daily timer — a debug dry-run shows what would happen and changes nothing, while a force run performs it immediately:
logrotate -d /etc/logrotate.d/rsyslog # dry-run: prints decisions, writes nothing
sudo logrotate -f /etc/logrotate.d/rsyslog # force a rotation right now
Which Source to Check First
| Type of problem | Source to check first |
|---|---|
| Server won't boot, or a hardware issue is suspected | dmesg, Boot Process and GRUB |
| A specific systemd service isn't working | journalctl -u <service> — journalctl |
| Someone attempted to log in over SSH | auth.log or journalctl -u ssh.service |
| A problem tied to a recently installed package | dpkg.log — apt and Repositories |
| A generic system error with an unclear cause | syslog or journalctl -p err |
| A business-logic bug inside an application | The application's own log source — a file, or journalctl -u <app-service> |
This table is the map the next two articles fill in: System Logs and dmesg goes deeper into kernel-level logging, and Log Analysis covers turning collected logs into practical conclusions.
Common Mistakes
Checking Only One Log Source and Stopping There
journalctl surfaces service-level failures clearly, but if the root cause sits in the kernel — a network driver, for instance — the answer only exists in dmesg. Any non-trivial problem deserves at least two sources checked together: the journal and the kernel log.
Trying to Read auth.log or wtmp with cat/less
wtmp, btmp, and lastlog are binary, not text. They must be read through their dedicated tools (last, lastb, lastlog); reading them directly just prints garbage to the screen.
Assuming rm on a Log File Frees Disk Space Immediately
As shown above, deleting a file that a process still has open does not reclaim disk space until that process closes the file or restarts. The correct approach is logrotate, or a service reload.
Exercises
- From the output of
ls -lh /var/log/, pick five different files and write, in your own words, what each one is for. - Open three files inside
/etc/logrotate.d/and compare theirrotate,daily/weekly, andcompresssettings. - Run
last -n 10and, if permitted,sudo lastb -n 5, and compare the results againstauth.logorjournalctl -u ssh.service. - Pick three scenarios from the "Which Source to Check First" table above and write the exact command you would run for each.
Verification criterion: for each of the five layers introduced in this article, you should be able to name one concrete symptom that would send you specifically to that layer and no other.
References
- man7.org:
syslog(3): https://man7.org/linux/man-pages/man3/syslog.3.html - man7.org:
logrotate(8): https://man7.org/linux/man-pages/man8/logrotate.8.html - Ubuntu Server Documentation: Logs: https://ubuntu.com/server/docs/logs
- freedesktop.org:
systemd-journald.service(8): https://www.freedesktop.org/software/systemd/man/latest/systemd-journald.service.html