Chuyển tới nội dung chính

Đ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ênLệnh
Server chậmCPU hay I/O?top, iostat -x 1
OOM / hết RAMProcess nào?ps aux --sort=-%mem
Disk đầyThư mục nào?du -sh /var/* | sort -rh
Không SSH đượcNetwork hay SSH?nc -zv host 22
Web không phản hồiWeb server chạy không?systemctl status nginx
Port bị chiếmProcess nào?lsof -i :80
Reboot đột ngộtKernel panic? OOM?dmesg -T | tail -50
Login thất bạiAuth loggrep "Failed" /var/log/auth.log