Điều tra hệ thống (System Investigation)
Đây là bộ lệnh thiết yếu khi troubleshoot vấn đề trên server production. Nguyên tắc cơ bản: quan sát trước, hành động sau.
Quy trình điều tra chung
Quan sát tổng quan (First 60 seconds)
Khi SSH vào server có vấn đề, chạy ngay bộ lệnh này:
# 1. Server đã uptime bao lâu? Load thế nào?
uptime
# 10:30:00 up 15 days, 2:31, 1 user, load average: 4.23, 3.80, 2.10
# ↑1m ↑5m ↑15m
# load average > số CPU cores → hệ thống đang bị quá tải
nproc # số CPU cores để so sánh với load average
# 2. Ai đang login và làm gì?
w
who
# 3. Top-level resource usage
top -bn1 | head -30
# 4. Memory
free -h
# Output: total / used / free / buff/cache / available
# "available" là số thực sự dùng được, không phải "free"
# 5. Disk
df -h
df -i # kiểm tra inode (đôi khi hết inode dù còn dung lượng)
# 6. Disk I/O
iostat -x 1 3 # 3 lần, mỗi giây (cần sysstat)
# 7. Network
ss -s # tóm tắt connections
Khi server chậm (High CPU / Load)
# === Bước 1: Tìm process ngốn CPU ===
top -bn1 | sort -k 9 -rn | head -20 # sort theo %CPU
ps aux --sort=-%cpu | head -20 # tương tự
# Xem CPU từng core
top # nhấn '1' để xem breakdown từng core
mpstat -P ALL 1 3 # CPU stats từng core (cần sysstat)
# === Bước 2: Điều tra process cụ thể ===
# Giả sử PID 1234 đang ăn 99% CPU
ls -la /proc/1234/exe # binary nào?
cat /proc/1234/cmdline # lệnh khởi chạy (xdotool để đọc dễ hơn)
cat /proc/1234/status # state, memory...
lsof -p 1234 | head -20 # file nào process đang mở?
strace -p 1234 -c # system call nào đang gọi? (cẩn thận với overhead)
# === Bước 3: Kiểm tra có phải D state (Disk Wait) không? ===
ps aux | awk '$8 ~ /D/ {print}' # process đang chờ I/O disk
# D state thường do disk I/O chậm hoặc NFS hanging
# === Bước 4: Xem lịch sử load ===
sar -u 1 60 # CPU usage 60 giây qua (cần sysstat)
sar -q # load average historical
Khi hết Memory / Swap
# === Xem tổng quan ===
free -h
vmstat -s
cat /proc/meminfo
# === Tìm process ngốn RAM ===
ps aux --sort=-%mem | head -20
top -bn1 | sort -k 6 -rn | head -20 # sort theo RSS
# === OOM Killer ===
# Khi hết RAM, kernel kill process để cứu hệ thống
dmesg | grep -i "out of memory"
dmesg | grep -i "oom"
grep "Out of memory" /var/log/syslog
# Output:
# kernel: Out of memory: Kill process 12345 (java) score 800
# → java process đã bị kill
# Xem OOM score của process (càng cao càng dễ bị kill)
cat /proc/$(pgrep nginx)/oom_score
cat /proc/$(pgrep sshd)/oom_score
# Bảo vệ process quan trọng khỏi OOM killer
echo -1000 > /proc/$(pgrep sshd)/oom_score_adj # SSH không bị kill
# === Xem memory leak ===
# Theo dõi RSS của process theo thời gian
watch -n 5 "ps -p 1234 -o pid,rss,vsz,cmd"
# RSS tăng liên tục → có thể memory leak
# === Giải phóng page cache (khi cần khẩn cấp) ===
sync # flush disk writes
sudo echo 3 > /proc/sys/vm/drop_caches # xoá cache (không xoá data!)
Khi ổ đĩa đầy
# === Tìm thủ phạm ===
df -h # filesystem nào đầy?
df -i # kiểm tra inode
# Tìm thư mục lớn từ trên xuống
du -sh /var/* | sort -rh | head -10
du -sh /var/log/* | sort -rh | head -10
du -sh /home/* | sort -rh
du -sh /opt/* | sort -rh
# Tìm file lớn
find /var -size +500M -type f 2>/dev/null | sort
find /var/log -name "*.log" -size +100M 2>/dev/null
# File lớn đang được ghi (process chưa close)
lsof | grep deleted # file đã xoá nhưng process còn giữ fd
# → kill hoặc restart process đó để giải phóng
# === Xử lý ===
# Log cũ
sudo journalctl --vacuum-time=7d # giữ log 7 ngày
sudo journalctl --vacuum-size=500M # giới hạn 500MB
find /var/log -name "*.gz" -mtime +30 -delete # xoá log gz cũ hơn 30 ngày
find /var/log -name "*.log" -empty -delete # xoá log rỗng
# Package cache
sudo apt clean # xoá cache apt (Ubuntu)
sudo dnf clean all # xoá cache dnf (RHEL)
# Docker cleanup
docker system prune -af # xoá image/container không dùng
docker volume prune # xoá volume không dùng
# Core dump files
find / -name "core" -type f 2>/dev/null
find / -name "*.core" -type f 2>/dev/null
Khi không SSH được vào server
# Từ máy local — kiểm tra từng bước
ping server_ip -c 4 # Server còn sống không?
traceroute server_ip # Network path đến đâu bị chặn?
nc -zv server_ip 22 # Port 22 có open không?
telnet server_ip 22 # Raw connect — thấy SSH banner không?
# Debug SSH verbose
ssh -vvv user@server_ip 2>&1 | head -50
# Từ server (nếu có console access)
sudo tail -50 /var/log/auth.log | grep -i "ssh\|fail"
sudo journalctl -u sshd -n 50
sudo systemctl status sshd
sudo sshd -t # kiểm tra config sshd syntax
Khi ứng dụng web không phản hồi
# === Kiểm tra web server ===
systemctl status nginx # nginx có chạy không?
systemctl status apache2 # hoặc apache?
curl -v http://localhost/ # kết nối từ localhost
curl -v https://localhost/ -k # HTTPS
# Check log ngay lập tức
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log
# === Port binding ===
ss -tulpn | grep :80 # ai đang dùng port 80?
ss -tulpn | grep :443 # port 443?
# === Connection flood / DDoS? ===
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# → liệt kê IP kết nối nhiều nhất
# Số connection hiện tại
ss -s
netstat -s | grep -i "failed\|reset\|overflow"
# === Application level ===
# Nếu dùng PHP-FPM
systemctl status php8.1-fpm
tail -f /var/log/php8.1-fpm.log
# Nếu dùng gunicorn (Python)
journalctl -u gunicorn -f
# Nếu dùng PM2 (Node.js)
pm2 logs
pm2 status
Điều tra Network
# === Xem connection hiện tại ===
ss -tn state ESTABLISHED # TCP connections đang active
ss -tn state TIME-WAIT | wc -l # TIME-WAIT connection (sau khi close)
ss -tn state CLOSE-WAIT | wc -l # CLOSE-WAIT (có thể báo hiệu connection leak)
# === Theo dõi traffic ===
sudo tcpdump -i eth0 -n port 80 # capture traffic port 80
sudo tcpdump -i eth0 -n host 1.2.3.4 # traffic từ/đến IP
sudo tcpdump -w /tmp/capture.pcap -i eth0 -n # lưu file để phân tích
# === Bandwidth ===
sudo iftop -i eth0 # bandwidth real-time theo connection (cần cài)
sudo nethogs eth0 # bandwidth theo process (cần cài)
cat /proc/net/dev # bytes in/out raw data
# === DNS issue ===
dig google.com +short # DNS lookup thành công không?
time dig google.com # DNS query mất bao lâu?
dig @8.8.8.8 google.com +short # bypass local DNS, dùng 8.8.8.8
cat /etc/resolv.conf # DNS server đang dùng là gì?
Xem lịch sử hệ thống
# === Khi nào server reboot? ===
last reboot # lịch sử reboot
uptime # đã uptime bao lâu
who -b # lần boot gần nhất
# === Kernel message quanh thời điểm sự cố ===
dmesg -T | grep "Jan 15 10:"
journalctl --since "2024-01-15 10:00" --until "2024-01-15 10:30"
# === Ai đã làm gì trên server? ===
last # lịch sử login
lastlog # lần login cuối của từng user
grep "sudo" /var/log/auth.log | tail -50 # sudo history
cat ~/.bash_history # lệnh đã gõ (của user hiện tại)
history # tương tự nhưng trong session
Checklist Troubleshoot nhanh
# === Server chậm — chạy ngay ===
uptime && nproc && echo "---"
ps aux --sort=-%cpu | head -5 && echo "---"
ps aux --sort=-%mem | head -5 && echo "---"
free -h && echo "---"
df -h && echo "---"
ss -s
# === Service lỗi — chạy ngay ===
systemctl status <service>
journalctl -u <service> -n 50 --no-pager
ls -la /var/log/<service>/
| Triệu chứng | Điều tra đầu tiên | Lệnh |
|---|---|---|
| Server chậm | CPU hay I/O? | top, iostat -x 1 |
| OOM / hết RAM | Process nào? | ps aux --sort=-%mem |
| Disk đầy | Thư mục nào? | du -sh /var/* | sort -rh |
| Không SSH được | Network hay SSH? | nc -zv host 22 |
| Web không phản hồi | Web server chạy không? | systemctl status nginx |
| Port bị chiếm | Process nào? | lsof -i :80 |
| Reboot đột ngột | Kernel panic? OOM? | dmesg -T | tail -50 |
| Login thất bại | Auth log | grep "Failed" /var/log/auth.log |