Server sập lúc 2 giờ sáng thì không ai đủ tỉnh để nghĩ mạch lạc. Đó chính là lý do cần một quy trình viết sẵn: làm theo thứ tự, mỗi bước một mục tiêu, không bỏ bước. Dưới đây là 7 bước đã được kiểm nghiệm qua nhiều sự cố thật, kèm lệnh cụ thể để bạn dán thẳng vào terminal.
Bước 1: Sự cố rộng đến đâu?
Trước khi SSH, xác định phạm vi trong 60 giây. Chữa sai bệnh còn tệ hơn chữa chậm.
# Website còn trả lời không, mất bao lâu?
curl -sv -o /dev/null -w 'HTTP %{http_code} sau %{time_total}s\n' https://example.vn
# Server còn tới được ở tầng mạng không?
ping -c 4 203.0.113.10
Đọc kết quả theo bảng này:
| Triệu chứng | Khả năng cao là |
|---|---|
| HTTP 502 hoặc 503, ping vẫn thông | Server sống, ứng dụng hoặc backend chết |
| Timeout hoàn toàn, ping mất | Sập tầng mạng, nghẽn tài nguyên toàn máy, hoặc nhà cung cấp có sự cố |
| HTTP 200 nhưng khách vẫn kêu lỗi | Sự cố cục bộ: DNS, CDN, hoặc chỉ một nhóm người dùng |
| Chậm bất thường nhưng vẫn trả lời | Nghẽn CPU, RAM hoặc I/O, chưa chết hẳn |
Kiểm luôn trang trạng thái của nhà cung cấp VPS và CDN. Nếu họ đang có sự cố diện rộng, việc của bạn là thông báo cho khách chứ không phải sửa server.
Bước 2: Còn vào được server không?
ssh -o ConnectTimeout=10 ops@203.0.113.10
SSH được: sang bước 3. SSH bị từ chối hoặc treo: mở console của nhà cung cấp (VNC hay serial console trong trang quản trị). Console cho bạn thấy màn hình lỗi kernel nếu có, và cho đăng nhập không cần mạng. Chỉ khi console cũng vô dụng mới cân nhắc hard reset, vì reboot sẽ xóa nhiều dấu vết chẩn đoán.
Bước 3: Tài nguyên có cạn không?
Ba thủ phạm quen mặt nhất của server “tự nhiên chết” là đĩa đầy, RAM cạn và load quá tải. Kiểm cả ba trong một phút:
df -h # đĩa: cột Use% có cái nào 100% không?
df -i # inode: đầy inode thì df -h vẫn còn chỗ mà ghi file vẫn lỗi
free -m # RAM: cột available còn bao nhiêu MB?
uptime # load average so với số core (nproc)
dmesg -T | grep -i 'out of memory' # OOM killer vừa giết tiến trình nào?
Đĩa 100% là nguyên nhân số một khiến database và ứng dụng chết mà không kịp kêu. Tìm nhanh thứ chiếm chỗ:
du -xh / --max-depth=2 2>/dev/null | sort -rh | head -15
journalctl --disk-usage # log hệ thống hay là thủ phạm
Nếu cần giải phóng gấp: journalctl --vacuum-size=200M thu gọn log hệ thống, xóa bớt file tạm và gói cache. Đừng xóa file đang được tiến trình mở giữ, vì dung lượng chỉ được trả lại khi tiến trình đóng file.
Bước 4: Dịch vụ nào đang chết?
systemctl --failed # unit nào đang ở trạng thái failed?
systemctl status nginx mysql # trạng thái chi tiết từng dịch vụ
docker ps -a # container nào Exited hoặc Restarting?
ss -tlnp # cổng nào đang thật sự lắng nghe?
Lệnh ss -tlnp trả lời câu hỏi quan trọng: tiến trình có đang nghe đúng cổng không. Ứng dụng “đang chạy” theo systemctl nhưng không nghe cổng 443 thì với người dùng vẫn là chết. Với container, để ý cột STATUS: Restarting (1) 30 seconds ago nghĩa là container rơi vào vòng lặp crash, và docker logs --tail 100 <tên> sẽ cho biết vì sao.
Bước 5: Log nói gì?
Đừng đoán khi có thể đọc. journalctl là bạn thân lúc này:
journalctl -u nginx --since '30 min ago' -p err # lỗi của riêng nginx nửa giờ qua
journalctl -k --since '1 hour ago' # log kernel: OOM, lỗi đĩa, mạng
journalctl --since '10 min ago' | tail -100 # toàn cảnh những phút cuối
Thứ cần tìm là sự kiện đầu tiên bất thường, không phải sự kiện cuối cùng. Chuỗi sự cố thường dài: đĩa đầy lúc 01:47, MySQL lỗi ghi lúc 01:52, ứng dụng mất kết nối database lúc 01:53, khách báo lỗi lúc 02:10. Sửa cái lúc 01:53 thì 2 giờ sáng mai bạn lại dậy.
Bước 6: Khôi phục thế nào cho an toàn?
Đã biết nguyên nhân thì xử lý theo thứ tự nhẹ tay trước:
systemctl restart nginx # khởi động lại đúng dịch vụ hỏng
systemctl status nginx # xác nhận nó lên thật
docker restart api # với container cũng vậy
curl -s -o /dev/null -w '%{http_code}\n' https://example.vn # kiểm từ ngoài lần cuối
Hai nguyên tắc: sửa nguyên nhân trước khi restart (đĩa còn 0 byte thì restart MySQL chỉ chết tiếp), và mỗi lần chỉ đổi một thứ để biết chính xác cái gì có tác dụng. Restart cả loạt dịch vụ cùng lúc có thể cứu được đêm nay nhưng để lại một bí ẩn cho tháng sau.
Bước 7: Làm gì để lần sau không lặp lại?
Sự cố chưa kết thúc khi website lên lại. Dành 15 phút khi còn nhớ rõ:
- Ghi timeline: phát hiện lúc nào, nguyên nhân gốc là gì, xử lý bằng gì, mất bao lâu. Ba tháng sau chính bạn sẽ cảm ơn tài liệu này.
- Vá gốc rễ: đĩa đầy vì log thì cấu hình logrotate, RAM cạn vì rò rỉ thì đặt lịch restart có kiểm soát và báo cho dev.
- Đặt cảnh báo cho đúng chỉ số vừa gây chuyện. Sự cố nào cũng có dấu hiệu trước: đĩa không nhảy từ 60% lên 100% trong một phút. Nếu chưa có giám sát, đây là lúc gắn: một agent đo tài nguyên bên trong cộng check uptime từ bên ngoài sẽ biến “khách gọi lúc 2 giờ sáng” thành “Zalo báo lúc 5 giờ chiều”. AgentWatch có gói Free cho 2 server và 10 check, cảnh báo qua Zalo và email, đủ cho đúng kịch bản này.
Quy trình 7 bước này không làm server hết sập. Nó làm những lần sập sau ngắn hơn, ít hoảng hơn, và mỗi lần đều để lại một hệ thống được vá chắc hơn trước.
