🧩 第08章 · 故障排查综合

从现象到根因的一套思路

故障排查综合

这一章给出一套可以套用到绝大多数故障的排查方法论,并用这台服务器可能遇到的真实故障做例子:网站 502、服务起不来、数据库连接失败、磁盘撑爆。故障排查的本质是"分层定位 + 基于证据下判断",而不是瞎重启。

排查心法:先分层,再切分

原则:永远从"可观察到的事实"出发,顺着系统层级往下(或往上)推,每一层用一条命令验证,而不是猜。

一层层通常是这样:

用户/浏览器 → 域名解析(DNS) → 反向代理/负载均衡(nginx) → 应用服务(node) → 依赖(redis/mysql) → 资源(CPU/内存/磁盘) → 网络(防火墙/端口)

通用排查流程(四步)

① 出问题的具体表现是什么? 什么时间、什么入口、报什么错、影响多少人。先拿事实,不拿猜测。

② 是哪一层没通过? 用一条命令快速切分。例:网站打不开——

# 这域名解析正常吗
dig +short learn.bangdream.xyz
# 443 端口通吗("连接被拒" vs "超时" 结论不同)
nc -zv 2.25.183.241 443
# 本地到 443 的 HTTP 层通吗
curl -sSI https://learn.bangdream.xyz/ | head -3
# 是 nginx 的锅还是后端的锅
curl -sSI http://127.0.0.1:3000/     # 直接打后端,绕过 nginx

③ 缩小范围到单点。 如果直接打后端 3000 也不通,说明是应用或依赖问题;如果后端通、前面不通,是 nginx/网络层问题。

④ 找到根因并修复,再验证。 修完之后用命令复验,不要口头"应该好了"。

案例 1:站点返回 502 Bad Gateway

502 表示 nginx 收到了请求,但转发时(proxy_pass)后端没正常响应。常见于后端挂了/没监听。

# 1) 后端在监听吗
ss -tlnp | grep ':3000'
# 2) 后端进程活着吗
systemctl status bangdream
# 3) 后端日志
journalctl -u bangdream -n 30 -p err
# 4) 进程满血吗
ps aux | grep node | head
  • 若 LISTEN 0.0.0.0:3000 没有 → 服务没起,systemctl start bangdream 并看为什么起不来。
  • 若起起来又立刻退 → 看 journalctl 里的报错(缺 env、端口被占、依赖 mysql 没起)。
  • 若后端转圈 → 看是不是它对 mysql 的连接超时(参考案例 3)。

案例 2:服务一启动就退出

# 看启动失败的详细报错
systemctl status bangdream
journalctl -u bangdream -b -n 40

常见根因与命令:

现象 常见根因 命令
Address already in use 端口被占用 ss -tlnp \| grep <port>
Cannot connect to MySQL 数据库没起/连不上 systemctl status mysql
Module not found node 依赖没装/路径不对 ls /var/www/<app>/node_modules
权限拒绝 目录/文件权限不足 ls -ld /var/www/<app>
OOM(Kill) 内存被吃光 dmesg -T \| grep -i oom、journalctl \| grep -i oom

案例 3:数据库连接失败

业务起不来、后端报"can't connect to MySQL":

# MySQL 服务与端口
systemctl status mysql
ss -tlnp | grep ':3306'
# 客户端连接测试(需凭据)
mysql -u root -p -e "select 1;"
# 看 MySQL 错误日志
tail -n 50 /var/log/mysql/error.log
# 表满了/连不上也查
mysql -e "show processlist;"

常见根因:MySQL 没 start、账号主机受限(只允许 localhost 但代码用了远程 IP)、密码错、skip-networking、磁盘满导致 MySQL 拒写入。

案例 4:磁盘爆满

磁盘满会引发连锁故障(日志写不进去、数据库挂、网站 502)。

df -h                 # 哪个分区满了
du -sh /var/* | sort -rh | head   # 哪拿走了空间;重点看 /var/log、/var/lib
journalctl --disk-usage
# 清理:日志轮转/压缩/截断、删过期备份、清大文件
journalctl --vacuum-time=14d
find /backups -mtime +7 -delete

提示 | 遇到"莫名奇妙全挂了",先看一眼磁盘和内存,往往就是根因。

案例 5:网络时通时断

mtr -rwc 20 2.25.183.241        # 看哪一跳丢包
curl -w "code=%{http_code} time=%{time_total}\n" https://learn.bangdream.xyz/
ping -c 100 193.112.201.1        # 长 ping 看丢包率

若只是某个平台访问不了、别的地方正常 → 多为地域/运营商/墙问题;若全丢 → 排查防火墙/安全组/链路。

排查记录表(按需填)

字段 内容
现象 一句话描述 + 错误信息截图/原文
影响范围 哪些入口/用户受影响
第一步验证 用哪条命令得到什么结论
根因 基于哪条证据确认
修复动作 执行了什么
复验 用哪条命令确认已恢复

相关命令集合

  • 服务:systemctl status <svc>、journalctl -u <svc> -n 50 -p err
  • 端口:ss -tlnp
  • 资源:df -h、free -h、uptime、top、dmesg -T | grep -i oom
  • 网络:dig、nc -zv、curl -v、mtr
  • 数据库:mysql -e "show processlist"、SHOW STATUS