Linux Troubleshooting: A Practical First-Response Guide
A repeatable first-response method for Linux problems: read the error carefully, query journalctl, isolate the triggering change, search precisely, and ask for help effectively.
Before you start
- ▸A systemd-based Linux system
- ▸Terminal access with sudo or root privileges
- ▸Basic familiarity with running commands in a shell
Systems break. The difference between a sysadmin who fixes things quickly and one who spirals for hours is usually method, not knowledge. This guide gives you a repeatable first-response process: where to look, what to capture, how to isolate the cause, and how to get useful help when you're stuck.
Step 1: Read the Error Message Fully
This sounds obvious, but most people skim the first line and start Googling before they finish reading. Error messages are dense on purpose. The actionable detail is often in the middle or at the end.
When a command fails, read the full output. Look for:
- The specific error code or string —
Permission denied,No such file or directory,Connection refused,Exit code 1 - The file or path named — which config file, socket, or binary triggered the failure
- The service or process involved — especially in multi-component stacks
Copy the exact error text before doing anything else. Paraphrasing it later will cost you search accuracy.
Step 2: Check the Journal
On any systemd-based distro, journalctl is your first stop for deeper context. It captures kernel messages, service output, and application stderr in one place.
Most recent boot, high-priority messages first
journalctl -p err -b
The -p err flag filters to error-level and above. -b means this boot only. This cuts noise dramatically on a busy system.
Follow a specific service live
journalctl -u nginx.service -f
Replace nginx with whatever unit is misbehaving. The -f flag tails output in real time — useful when you're restarting a service to watch what happens.
Check a service's status and recent log tail together
systemctl status sshd.service
This gives the active/failed state, the last few log lines, the PID, and the memory footprint in one compact view. Always run this before diving into the full journal.
Jump to just before a crash
journalctl -b -1 -p err
-b -1 looks at the previous boot — valuable when the system crashed and rebooted before you could check.
Step 3: Isolate the Change
Almost every breakage has a trigger. Something changed: a package updated, a config was edited, a cron job ran, a disk filled up, a user was added. Identifying that change is faster than debugging blindly.
What changed recently on the filesystem?
find /etc -newer /etc/hostname -type f 2>/dev/null
This lists files in /etc modified more recently than /etc/hostname (a file that changes rarely). Adjust the reference file to a known-stable timestamp anchor.
Check recent package activity
On Debian/Ubuntu:
grep " install \| upgrade \| remove " /var/log/dpkg.log | tail -30
On Fedora/RHEL/Rocky:
dnf history list | head -20
On Arch:
grep -E 'installed|upgraded|removed' /var/log/pacman.log | tail -30
Check disk and inode usage
A full disk causes strange, misleading failures. Check it early.
df -h
df -i
df -h shows disk space; df -i shows inode usage. A filesystem can be 0% full by space but 100% full by inodes, which breaks file creation just as hard.
Check for OOM kills
journalctl -k -b | grep -i 'oom\|killed process'
The kernel OOM killer terminates processes without much warning. If a service vanished without a clean exit, this is often why.
Step 4: Reproduce and Narrow Down
Once you have a hypothesis, test it deliberately. Run the failing command manually. Restart the failing service and watch the journal simultaneously in a second terminal. Strip the problem to its smallest reproducible form.
A few practical patterns:
- Run a service in the foreground or in debug mode if it supports it (e.g.,
nginx -tto test config,sshd -dfor debug output) - Use
straceon short-lived processes to see every syscall:strace -e trace=file mycommandreveals missing files and permission errors at the kernel level - Use
lsof -p <PID>to see what files and sockets a running process has open - Check
/tmpand/var/tmppermissions if setuid or sticky-bit behavior is involved
Step 5: Search Effectively
When you need to search for an error, quality of input determines quality of results.
What to include in a search:
- The exact error string in quotes:
"failed to connect to bus: no such file or directory" - The distro and version if the error is likely distro-specific
- The specific service or package name
What to remove from the search:
- Paths or usernames unique to your system (they won't match others' reports)
- Timestamps and PIDs
- Anything that looks like a session or transaction ID
Check the project's issue tracker directly (GitHub, GitLab, Bugzilla) for errors from actively developed software — forum posts go stale, but issues track resolutions. For package-specific bugs on Debian/Ubuntu, bugs.debian.org and Launchpad are authoritative.
Step 6: Ask for Help Well
When you post a question on a forum, mailing list, or chat, the quality of your report determines the quality of answers. A good report has five things:
- What you were trying to do — the goal, not just the failing command
- What you expected to happen
- What actually happened — the exact error, verbatim, as text (not a screenshot)
- What you've already tried — saves everyone from suggesting dead ends
- Your environment — distro, version, kernel, relevant package versions
Collect your environment details quickly:
uname -r
cat /etc/os-release
systemctl --version
For a specific package version:
Debian/Ubuntu:
dpkg -l packagename
Fedora/RHEL/Rocky:
rpm -q packagename
Arch:
pacman -Q packagename
Verification: Did the Fix Hold?
After applying a fix, verify it properly rather than just checking the immediate outcome.
- Restart the affected service and confirm it stays up:
systemctl is-active servicename - Check the journal for new errors in the minutes after the fix:
journalctl -u servicename --since "5 minutes ago" - If you edited a config file, validate it before restarting when a validator exists (
nginx -t,sshd -t,named-checkconf,postfix check) - Reboot if the fix involved kernel parameters, kernel modules, or system-wide paths — some changes only fully take effect at boot
Troubleshooting Common Dead Ends
"It works as root but not as my user"
This is almost always permissions (file, socket, or capability) or a missing group membership. Check ls -la on the relevant path, and verify group membership with id username. Remember that group changes require a new login session to take effect.
"The service starts then immediately stops"
Run journalctl -u servicename -b --no-pager and look for the exit code. An exit-code=1 usually means a config error or missing dependency. An exit-code=2 or higher often signals a usage error in the unit file's ExecStart line.
"It was working yesterday and nobody changed anything"
Something changed. Check package update logs (above), check cron jobs that run nightly (cat /etc/cron.daily/*), check for certificate expiry (openssl x509 -in cert.pem -noout -dates), and check disk usage. Automatic updates, logrotate, and certificate rotations are frequent silent triggers.
Frequently asked questions
- Which log should I check first — journalctl or /var/log files?
- Start with journalctl on any systemd distro. It aggregates kernel, service, and application messages in one searchable stream. Traditional /var/log files are still written by some applications and are worth checking if journalctl shows nothing useful, but journalctl covers the majority of cases.
- How do I check logs from before a system crash or reboot?
- Use 'journalctl -b -1' to view the previous boot's journal. If the system crashed hard and the journal wasn't flushed, you may need persistent journal storage: set Storage=persistent in /etc/systemd/journald.conf and restart systemd-journald.
- strace output is overwhelming — how do I focus it?
- Use '-e trace=file' to limit output to filesystem-related calls, which covers most 'missing file' and permission problems. Add '-o output.txt' to write to a file instead of the terminal, then grep for ENOENT or EACCES.
- How do I find which package owns a broken file?
- On Debian/Ubuntu run 'dpkg -S /path/to/file'. On Fedora/RHEL/Rocky run 'rpm -qf /path/to/file'. On Arch run 'pacman -Qo /path/to/file'. This is useful when a binary or library has unexpected permissions or is missing.
- My fix works but I'm not sure why — should I leave it?
- Understand it before moving on. A fix you don't understand is a future mystery failure. Check the change against the documentation, confirm it is intentional rather than coincidental, and note it in your change log or ticket.
Related guides
Back Up Linux with Borg or restic
Set up encrypted, deduplicated backups with BorgBackup or restic: local and remote repos, retention pruning, restoring files, and systemd timer scheduling.
How to Check Disk Health with SMART
Learn to use smartctl to read SMART attributes, run drive self-tests, and identify early warning signs of HDD and SSD failure before data loss occurs.
Debug systemd Units that Won't Start
Learn a repeatable workflow to debug systemd services that won't start: status output, journalctl, systemd-analyze verify, and safe override.conf patches.
Linux Server Disaster Recovery Checklist
A practical Linux server disaster recovery checklist: what to back up, RTO/RPO planning, immutable off-site copies, automated restore drills, and verification.