Monitoring and Troubleshooting
Introduction
When a server feels slow or a deploy fails, you need a repeatable way to see CPU, memory, disk, logs, and ports. This chapter covers live resource checks, log locations, and a troubleshooting map for errors you already met in earlier chapters—so production issues become boring checklists.
Prerequisites
- Chapters on processes, disk, and networking
Quick Health Snapshot
# Uptime and load averages (1, 5, 15 minutes)
uptime
# Memory summary
free -h
# Disk usage
df -h
# Who is using CPU/memory right now
top -bn1 | head -20Install htop for interactive view:
sudo apt install -y htop
htopLoad average on a 4-core box: sustained above 4.0 suggests CPU saturation—investigate with top / htop.
CPU and Memory Deeper Look
# One-line CPU stats every 2 seconds, 5 times
vmstat 2 5
# Per-process memory sort
ps aux --sort=-%mem | head
# Java heap is inside JVM — use app metrics or jcmd when needed
ps aux | grep javaiostat (package sysstat) helps disk bottlenecks—high %util on a disk with slow response points to storage limits.
systemd and journalctl
# Boot messages and recent errors
sudo journalctl -p err -b --no-pager | tail -50
# Follow all logs
sudo journalctl -f
# Specific service since last hour
sudo journalctl -u nginx --since "1 hour ago"Kernel OOM killer messages appear in journal when RAM is exhausted—apps die mysteriously without app-level stack traces.
Classic Log Files
| File | Often contains |
|---|---|
/var/log/syslog | General system messages (Ubuntu) |
/var/log/auth.log | SSH login success/failure |
/var/log/nginx/access.log | HTTP requests |
/var/log/nginx/error.log | Nginx errors |
/var/log/mysql/error.log | Database issues |
Tail practice:
sudo tail -f /var/log/auth.log
sudo tail -f /var/log/nginx/error.logApplication logs may live under /opt/myapp/logs/ or only in journalctl -u myapp—document your team’s paths in runbooks.
Troubleshooting Playbook
command not found
echo $PATH
which javaFix: install package, fix ~/.bashrc, or use full path /usr/bin/java.
Permission denied
ls -l /path/to/file
idFix: chown/chmod, run as correct user, or sudo for system paths—not for routine app data.
Address already in use
sudo ss -tlnp | grep :8080Fix: stop duplicate service, change app port, or fix stale process after crash.
Disk full / no space left on device
df -h
sudo du -sh /var/* 2>/dev/null | sort -hr | head
sudo journalctl --vacuum-time=7dFix: rotate logs, remove old releases, expand volume on cloud console.
Cannot SSH
From provider console (VNC/serial):
- Is
sshdrunning?sudo systemctl status ssh - Firewall allows 22?
sudo ufw status - Keys correct?
~/.ssh/authorized_keyspermissions 600, directory 700 - Wrong IP or security group rule
HTTP works locally but not from internet
- App listens
127.0.0.1only vs0.0.0.0 - Nginx
proxy_passmisconfigured - Cloud firewall vs UFW
- DNS not pointing to server
Database connection refused
- MySQL running:
systemctl status mysqlordocker ps - Port open on
127.0.0.1:3306only (good) vs firewall blocking wrong host - JDBC URL host/port typo—see JDBC track
Scripted Checks
Combine tools from shell scripting:
Run after deploy or from cron for a poor man’s monitoring.
When to Escalate Beyond CLI
| Signal | Action |
|---|---|
| Repeated OOM | More RAM, fix leak, JVM -Xmx tuning |
| Disk growth daily | Log rotation, separate volume |
| SSL expiry soon | Certbot renew, calendar reminder |
| Need history graphs | Hosted monitoring (Prometheus, cloud vendor metrics) |
This course stays CLI-first; SaaS APM is optional at scale.
FAQ
Load average 8 on 2 CPU machine?
Overloaded—reduce traffic, optimize code, or scale vertically/horizontally.
Logs empty in /var/log/myapp?
App may log only to stdout—check journalctl -u myapp. Configure logging.file.path in Spring Boot if files are required.
dmesg: read permission denied?
Use sudo dmesg | tail for hardware and OOM kernel lines.
Restart fixes everything?
Intermittent resource leak or race—capture logs before restart next time.