Log Troubleshooting Cheat Sheet
A practical workflow for troubleshooting with plain-text logs in /var/log: where to look first, tailing and searching fast, correlating logs across services, log rotation and disk-full recovery.
Most incidents get solved by reading the right log, fast. This sheet covers the classic flat-file logs under /var/log and the workflow for working through them under pressure. For systemd’s binary journal specifically, see the journalctl Cheat Sheet - many distributions use both side by side.
Where to look first
/var/log/syslog # Debian/Ubuntu - general system log, most services log here
/var/log/messages # RHEL/Fedora/CentOS - equivalent general system log
/var/log/auth.log # Debian/Ubuntu - authentication, sudo, SSH login attempts
/var/log/secure # RHEL/Fedora - equivalent auth log
/var/log/kern.log # kernel messages logged to a file (dmesg is the live ring buffer)
/var/log/dpkg.log # Debian/Ubuntu package install/remove history
/var/log/nginx/access.log # nginx requests
/var/log/nginx/error.log # nginx errors
/var/log/apache2/error.log # Apache errors (Debian/Ubuntu path)
/var/log/mysql/error.log # MySQL/MariaDB errors
/var/log/cloud-init.log # cloud-init provisioning, on cloud VM images
/var/log/boot.log # boot-time service startup messages
Exact paths vary by distro and by how a package was installed - if a log isn’t where you expect, check the service’s config for a log_file/ErrorLog directive, or systemctl status <service> for a hint.
Reading logs fast
tail -n 100 /var/log/syslog # last 100 lines - the fastest first look
tail -f /var/log/nginx/error.log # follow live as new lines arrive
less +G /var/log/syslog # open a pager already scrolled to the end
# inside less:
/pattern # search forward for "pattern"
?pattern # search backward
n # jump to the next match
N # jump to the previous match
Following multiple logs at once
tail -f /var/log/nginx/error.log /var/log/mysql/error.log # tail interleaves both, prefixed by filename
multitail /var/log/nginx/error.log /var/log/auth.log # split-pane live view, if installed
multitail isn’t installed by default on most systems (apt install multitail / dnf install multitail) but is worth it once you’re regularly watching more than one log during an incident.
Searching for the interesting bits
grep -i "error\|fail\|denied\|refused" /var/log/syslog # common trouble keywords, case-insensitive
grep -i "error" /var/log/nginx/error.log | tail -50 # last 50 error lines
grep -c "Failed password" /var/log/auth.log # how many failed SSH logins, total
grep -B2 -A2 "segfault" /var/log/kern.log # a crash, with 2 lines of context each side
Filtering a plain-text log by time range
sed -n '/Sep 29 09:00/,/Sep 29 10:00/p' /var/log/syslog # everything between two timestamps (syslog's own format)
awk '$0 >= "2026-09-29 09:00:00" && $0 <= "2026-09-29 10:00:00"' /var/log/nginx/error.log # works when the log's own timestamp sorts as a string
Plain-text logs have no query language like journalctl --since - matching on the timestamp text itself (with sed/awk, see the sed & awk Cheat Sheet) is the usual workaround.
Correlating an incident across logs
# Pull the same time window from two logs, side by side, to line up cause and effect
grep "10:1[0-5]" /var/log/nginx/error.log
grep "10:1[0-5]" /var/log/mysql/error.log
The general pattern for “why did X break at time T”: find T in the log closest to the symptom (nginx, application), then check every other service’s log for the same narrow window - the actual cause is often one or two lines in a completely different log file.
Kernel and hardware issues
dmesg # kernel ring buffer - driver, hardware, OOM-killer messages
dmesg -T # same, with human-readable timestamps instead of seconds-since-boot
dmesg | grep -i "error\|fail\|oom" # filter for the usual suspects
dmesg is the first place to check for a process that died with no application-level explanation - the OOM killer and hardware errors both show up here, not in the application’s own log.
Login history
last # successful logins, most recent first
last -a # same, with the hostname/IP in its own column
lastb # failed login attempts (reads /var/log/btmp)
who # who's logged in right now
w # who's logged in, plus what they're running
Log rotation (logrotate)
cat /etc/logrotate.conf # global defaults
ls /etc/logrotate.d/ # per-service configs (nginx, apache2, mysql, ...)
cat /etc/logrotate.d/nginx # see how a specific service rotates
logrotate -d /etc/logrotate.d/nginx # dry run - show what WOULD happen, changes nothing
sudo logrotate -f /etc/logrotate.d/nginx # force rotation right now
cat /var/lib/logrotate/status # when each log was last rotated
When logs fill the disk
du -sh /var/log/* | sort -rh | head -10 # largest logs, biggest first
df -h /var/log # confirm /var/log's filesystem is actually the one that's full
sudo truncate -s 0 /var/log/nginx/access.log # safely empty a log a process is actively writing to
sudo systemctl reload nginx # reload so nginx reopens a rotated/truncated log file
> file.log and truncate -s 0 file.log both work, but truncate doesn’t require the shell to have write access to the directory the same way redirection does, and makes the intent explicit in scripts.
Common recipes
# Was this an SSH brute-force attempt?
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
# What changed right before a service crashed - broad net across the usual logs
grep -h "$(date '+%b %e %H:%M')" /var/log/syslog /var/log/kern.log /var/log/auth.log
# Package install/remove history around a suspected regression
grep " install \| remove " /var/log/dpkg.log | tail -30
Safety notes
- Deleting a log file a process still has open doesn’t free the disk space until that process closes or reopens its file handle (usually via
logrotate’spostrotaterestart/reload, or a manualsystemctl reload) -truncate -s 0is safer thanrmfor a log you need to shrink right now. /var/log/auth.logand/var/log/securecan contain usernames typed into the password field by mistake during a failed login - treat their contents as sensitive before pasting them anywhere.logrotate -frotates immediately regardless of the configured schedule/size threshold - fine for testing a config, but running it repeatedly in a short window can leave you with many near-empty rotated files.- A log that suddenly stops updating is itself a symptom - check the service is still running and that its log directory has enough free disk space and correct write permissions, before assuming nothing is happening.