4.14 运维常见故障案例分析与解决

预计阅读时间:19 分钟

📖 目录

学习目标

  • 掌握系统化故障排查方法论:日志 → 资源 → 配置 → 复现
  • 独立诊断并解决 15 个高频运维故障:磁盘满、OOM Killer、SSH 慢、inode 耗尽、Nginx 502、证书过期、Cron 失效、Docker 磁盘满、CPU 100%、内存泄漏、网络丢包、数据库连接耗尽、NTP 时钟偏移、DNS 缓存污染、磁盘 IO 瓶颈
  • 建立预防性运维思维,通过 logrotate、监控告警、配置审计减少故障复发
  • 学会用自动化手段(cron + 巡检脚本 + 定时续期)提前发现隐患

核心知识

  • 故障排查流程:数据采集(日志/指标)→ 根因分析(资源/配置)→ 修复 → 验证 → 复盘
  • 关联章节4.5:网络故障排查 网络故障排查方法论与实战(traceroute、ss、tcpdump 等底层网络诊断工具链)、 5.1:Linux 安全加固 Linux 服务器安全加固指南(证书管理、SSH 加固、文件权限审计)、 4.4:Shell 自动化实战 Shell 脚本自动化运维实战(巡检脚本编写、告警推送集成)、 3.15:Cron 定时任务 Cron 定时任务高级应用(任务调度机制、锁文件、环境变量继承)
  • 核心工具栈:journalctl / dmesg / df / du / ss / openssl / systemctl / strace / lsof

知识关联

原理讲解

系统化故障排查四步法:

  1. 查日志(What happened?) — 查看系统日志(journalctl -xe)、内核日志(dmesg -T)、应用日志(access_log、error_log)。日志是故障现场的第一手证据,务必最先查看。
  2. 查资源(What's the state?) — CPU(top / vmstat)、内存(free -h)、磁盘(df -h / df -i)、网络(ss -tlnp、iftop)。资源耗尽是最常见的故障根源之一。
  3. 查配置(What changed?) — 对比最近变更的配置文件、软件版本升级、防火墙规则。用 rpm -Vadiff -r /etc/ /etc.bak/ 对比基线。
  4. 复现(Can we trigger it?) — 在测试环境复现现象,验证修复方案。绝对避免直接在产线试错。
# 通用排查三板斧
journalctl -xe -n 50                             # 输出: -- Logs begin at ... -- (最近50条系统日志)
dmesg -T | tail -20                              # 输出: [Thu Jul 30 01:23:45 2026] ... (最近20条内核日志)
df -h && df -i && free -h && ss -tlnp            # 输出: (磁盘/内存/网络资源快照)

示例代码

4.1 磁盘空间满 — logrotate 配置修复

现象:数据库写入失败,df -h 显示 / 分区 100%。
根因:Nginx access_log 未配置 logrotate,单文件膨胀至 40 GB。
修复

# 紧急释放空间(truncate 而非 rm,避免进程句柄不释放)
sudo truncate -s 0 /var/log/nginx/access.log
# 配置 logrotate /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily    rotate 7    compress    delaycompress
    missingok    notifempty    create 640 www-data adm
    postrotate    systemctl reload nginx   endscript
}
# 验证配置
sudo logrotate -d /etc/logrotate.d/nginx  # 输出: reading config file /etc/logrotate.d/nginx

4.2 OOM Killer — MySQL 内存调优

现象:MySQL 进程无故消失,dmesg 显示 "killed process mysqld"。
根因:innodb_buffer_pool_size = 12G,但物理内存仅 8G,系统触发 OOM Killer。
修复

dmesg -T | grep -i "killed process"  # 输出: [Thu Jul 30 01:23:45 2026] Killed process 1234 (mysqld)
# 调低 MySQL 内存占用
sed -i 's/innodb_buffer_pool_size = 12G/innodb_buffer_pool_size = 4G/' /etc/mysql/my.cnf
# 保护关键进程不被 OOM 优先杀死
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj
# 或通过 systemd 固化
echo "OOMScoreAdjust=-1000" >> /etc/systemd/system/mysql.service.d/override.conf
systemctl daemon-reload && systemctl restart mysql

4.3 SSH 连接慢 — UseDNS 关闭

现象:SSH 登录等待 10-30 秒才出密码提示。
根因:sshd 默认对客户端 IP 做反向 DNS 查询,内网 DNS 超时导致阻塞。
修复

# /etc/ssh/sshd_config
sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd

4.4 inode 耗尽 — 清理小文件

现象:df -h 显示还剩 20 GB,但无法创建任何新文件。
根因:PHP session 目录堆积了百万级小文件,inode 使用率 100%。
修复

df -i  # 输出: Filesystem      Inodes  IUsed   IFree IUse% Mounted on (/dev/sda1 100%)
# 清理过期 session 文件
find /var/lib/php/sessions -type f -atime +1 -delete 2>/dev/null
# 检查邮件队列假脱机
find /var/spool/postfix/maildrop -type f -delete 2>/dev/null
# 预防:缩短 php session.gc_maxlifetime

4.5 Nginx 502 — PHP-FPM 重启调优

现象:Nginx 返回 502 Bad Gateway,半小时后自动恢复。
根因:PHP-FPM 的 pm.max_children 不足,请求队列满导致 worker 拒绝连接。
修复

systemctl status php8.3-fpm | grep -i "error"  # 输出: Jul 30 01:23:45 host php-fpm[1234]: ERROR: unable to bind listening socket
# 查看当前 worker 数量(/proc//status 无 pool 字段,用 ps 统计)
ps -C php-fpm8.3 --no-headers | wc -l  # 输出: 5
# 调整配置 /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
# 重启 PHP-FPM
systemctl restart php8.3-fpm

4.6 TLS 证书过期 — Certbot 自动续期

现象:浏览器提示 "NET::ERR_CERT_DATE_INVALID",curl 返回 SSL 错误。
根因:Let's Encrypt 证书已过期,certbot 自动续期定时器未启用。
修复

# 手动强制续期
certbot renew --force-renewal --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"  # 输出: Congratulations, all renewals succeeded.
# 检查并启用 systemd timer
systemctl list-timers | grep certbot  # 输出: Fri 2026-07-31 00:00:00 CST certbot.timer          certbot.service
systemctl enable --now certbot.timer  # 输出: Created symlink /etc/systemd/system/timers.target.wants/certbot.timer
# 备用 crontab 方案
echo "0 */12 * * * root certbot renew --quiet --post-hook 'systemctl reload nginx'" > /etc/cron.d/certbot

4.7 Cron 任务失效 — PATH + 锁文件

现象:日志备份脚本在 crontab 中从不执行,手动运行正常。
根因:cron 的最小环境 PATH 只有 /usr/bin:/bin,脚本中 /usr/local/bin/ 下的工具找不到。
修复

# crontab 中显式设置 PATH(crontab -e)
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * /opt/scripts/backup.sh

# 脚本内加锁防止重复执行(flock)
# /opt/scripts/backup.sh
#!/bin/bash
exec 200>/var/lock/backup.lock
flock -n 200 || { logger "backup already running"; exit 1; }
# ... backup logic ...

4.8 Docker 磁盘满 — Prune + 日志轮转

现象:/var/lib/docker 所在分区使用率 100%,docker ps 卡住。
根因:未限制容器日志大小,单个日志文件膨胀至 GB 级别;长期未清理悬空镜像。
修复

# 紧急清理
docker system prune -a -f --volumes  # 输出: Total reclaimed space: 1.2GB
# 定位日志最大的容器
find /var/lib/docker/containers/ -name "*-json.log" -exec du -sh {} + | sort -rh | head  # 输出: 2.3G .../container-id/container-id-json.log
# 全局限制容器日志 /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" },
  "storage-driver": "overlay2"
}
systemctl restart docker

4.9 CPU 100% — 线程栈定位高占用

现象:load average 飙升到 20+,服务响应变慢,但没人知道是哪个进程在烧 CPU。
排查

top -c   # 输出: PID 12345 ... 200% CPU 500:32.32 /usr/bin/java -jar app.jar(200% = 吃了两个核)
# Java 进程找出烧 CPU 的具体线程(线程级)
top -Hp 12345   # 输出: TID 12399 占 198% CPU
printf '%x\n' 12399   # 输出: 306f(转十六进制,线程栈里用这个 ID)
jstack 12345 | grep -A 30 "0x306f"
# 输出: "pool-3-thread-1" prio=5 ... at com.xxx.SlowService.doQuery(SlowService.java:88)

根因:业务代码在循环里重复查询一条没有索引的慢 SQL,无缓存。
修复:给查询加本地缓存 + 慢 SQL 加索引后,CPU 从 200% 降到 30%。
预防:上线前压测;监控里对单进程 CPU 设置告警(node_exporter 的 process_cpu_seconds 做增长率告警)。

4.10 内存泄漏 — 进程 RSS 只涨不降

现象:某个 Java/Node 进程 RES 从 500MB 慢慢涨到 4GB,服务每隔几天就卡顿一次,重启后恢复。
排查

top -o %MEM   # 输出: PID 12345 %MEM 62.3 RES 4.1g(一个进程吃掉大半内存)
# 观察趋势:每 30 分钟记录一次 RSS,看是否只涨不降
while true; do ps -p 12345 -o rss=,etime= >> /tmp/rss.log; sleep 1800; done
cat /tmp/rss.log   # 输出: 4194304 12:30:00 / 5242880 13:00:00 / 6291456 13:30:00(线性增长)
# 确认内存段分布:匿名内存段持续增大 = 应用层泄漏
pmap -x 12345 | tail -5   # 输出: total kB 5242880(anon 段占比持续走高)

根因:Java 的 ThreadLocal 使用后未 remove,或 Node 的全局缓存无淘汰策略。
修复:修掉泄漏点后重启;临时缓解:JVM 设 -Xmx 上限 + 开启 GC 日志(-Xlog:gc)便于事后分析。
预防:监控 process_resident_memory_bytes,设定"48 小时 RSS 涨幅 > 20% 告警"。

4.11 网络丢包 — ping 稳定但业务偶发超时

现象:ping 网关 1000 包只丢 2 个,但应用访问偶发 5-10 秒超时,TCP 重传频繁。
排查

ping -f -c 1000 10.0.0.1   # 输出: 1000 packets transmitted, 998 received, 0.2% packet loss
# 关键指标:网卡 dropped 持续增长 = 内核丢包(软中断处理不过来)
ip -s link show eth0   # 输出: RX: bytes packets errors dropped overrun mcast 892107 12345 0 8902 0 0
# 软中断分布是否不均(NET_RX 全压在一个 CPU 上)
cat /proc/softirqs | grep -i net_rx   # 输出: CPU0: 8901234 CPU1: 78(严重不均)
# tcpdump 确认 SYN 半连接堆积(大量 SYN 但无 ACK = 半连接/拥塞)
sudo tcpdump -i eth0 'tcp[13] & 2 != 0' -c 50   # 输出: 多条 Flags [S] 标记

根因:eth0 的中断全部落在 CPU0,流量高峰时单核中断处理不过来,网卡驱动环形缓冲区溢出丢包。
修复:开启 irqbalance 并确认网卡多队列(RSS):

sudo systemctl enable --now irqbalance
ethtool -l eth0   # 输出: Combined: 8(多队列已开,之前是没跑 irqbalance 导致中断扎堆)

预防:监控 ip -s link 的 dropped 计数,与带宽使用率联动告警;绑定调优后 24 小时观察重传率。

4.12 数据库连接耗尽 — too many connections

现象:应用报 Can't connect to MySQL server (111),连 DBA 自己 ssh 上去执行 mysql 也进不去。
排查

# 绕过连接数限制:用 socket 方式以 root 登录
mysql -uroot -p -S /var/run/mysqld/mysqld.sock
mysql> SHOW STATUS LIKE 'Threads_connected';   # 输出: 498(上限 500)
mysql> SHOW PROCESSLIST;                       # 输出: 大量 Sleep 连接占满连接池
mysql> SELECT user, host, db, COUNT(*) FROM information_schema.processlist
       GROUP BY user, host, db;                # 输出: 谁占的最多一目了然

根因:应用连接池 max 配得比 MySQL 的 max_connections(500)还大,且空闲连接不回收。
修复

# 应用侧:连接池 max 降到 200,设置 connectionMaxIdleTime=10 分钟主动回收
# 数据库侧:my.cnf
[mysqld]
max_connections = 800
wait_timeout = 60
interactive_timeout = 120
# 紧急处理:杀掉空闲连接(只杀 Sleep 的,别杀正在执行的)
mysqladmin -uroot -p processlist | awk '$5 == "Sleep" {print $1}' | \
  xargs -r -I{} mysqladmin -uroot -p kill {}
# 最后手段才是 restart mysql —— 会断开所有业务连接,造成二次事故

预防:监控 Threads_connected / max_connections 比值,> 80% 告警;应用连接池必须配健康检查与空闲回收。

4.13 NTP 时钟偏移 — 认证与日志时间错乱

现象:某台机器上 JWT 登录一会儿就失效,MySQL 主从报 "Slave I/O error: clock skew",日志时间线对不上。
排查

date; date -u   # 输出: 2026年07月31日 10:23:45 CST / Fri Jul 31 02:23:45 UTC
timedatectl status   # 输出: NTP service: inactive(NTP 被关了!)
# 与权威时间源对比偏差
chronyc tracking   # 输出: System time : 312.184 seconds slow of NTP time(慢 5 分钟)

根因:虚拟机的模板快照回滚后 NTP 服务被禁用,机器时间比真实时间慢 5 分钟。
修复

sudo timedatectl set-ntp true          # 启用 systemd-timesyncd(基础方案)
# 企业环境建议统一用 chrony
sudo apt install chrony
sudo systemctl enable --now chrony
chronyc makestep   # 立即跳变校时(跳过渐进式微调)
# 修完时钟后:JWT 等时效性服务重启一遍即可恢复

预防:chrony.conf 配 makestep 1 3(启动后前 3 次偏差大直接跳变);K8s、数据库集群统一同一组 NTP 服务器;监控 chronyc tracking 的 offset > 500ms 告警。

4.14 DNS 缓存污染 — 域名指向错误 IP

现象:用户反馈域名打不开,运维 dig 解析结果正确,但 curl 实际访问的是旧服务器 IP。
排查

dig +short example.com     # 输出: 1.2.3.4(权威解析正确)
getent hosts example.com   # 输出: 1.2.3.5(与本机实际解析结果不一致!)
nslookup example.com       # 输出: Server: 127.0.0.53(systemd-resolved 本地缓存)
systemd-resolve --statistics   # 输出: Current Cache Size: 1234
cat /etc/hosts             # 输出: 1.2.3.5 example.com(有人手工加过测试记录忘了删!)

根因:有人曾为测试在 /etc/hosts 手工添加 example.com 指向,事后忘记删除,优先级高于 DNS 服务器。
修复

# 删除 hosts 中的错误行
sudo sed -i '/example.com/d' /etc/hosts
sudo resolvectl flush-caches   # 清空 systemd-resolved 缓存
# 若问题出在内网 DNS 服务器缓存:在权威源把 TTL 调小等自然过期,或 rndc flush
# 排查顺序固定为:hosts → 本地 resolver → 内网 DNS → 权威 DNS,逐层排除

预防:/etc/hosts 修改纳入变更管理(参考 4.13:服务器初始化规范 服务器初始化规范);内网 DNS 变更后先降 TTL 再切换,避免 8 小时缓存黑洞。

4.15 磁盘 IO 瓶颈 — 应用慢但 CPU/内存都空闲

现象:web 服务响应从 100ms 涨到 2s,top 看 CPU 只有 20%、内存充足,直觉上"不是资源问题"。
排查

top   # 输出: %wa 45.2(iowait 高是 IO 瓶颈的最强信号)
iostat -x 2 5   # 输出: sda %util 99.3 await 412.35(util≈100% 且 await 高 = 队列堆积)
iotop -o   # 输出: TID 12345 100% disk read /var/lib/mysql/ibdata1(谁在读写一目了然)
# 数据库层面:慢查询日志
mysqldumpslow /var/lib/mysql/slow.log | head -10
# 输出: Count: 120 Time=8.4s ... SELECT * FROM orders WHERE user_id=? AND status=?

根因:orders 表全表扫描,每秒上千次随机读,单块 SATA HDD 的随机 IOPS 上限只有 ~200,完全打满。
修复

# 加联合索引消除全表扫描(先用 EXPLAIN 验证执行计划)
mysql> EXPLAIN SELECT * FROM orders WHERE user_id=1 AND status='paid';  # 输出: type=ALL → 加索引后 type=ref
mysql> ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
# 容量级方案:热数据迁到 SSD,或调大 innodb_buffer_pool 让热点页驻留内存
sed -i 's/innodb_buffer_pool_size = 4G/innodb_buffer_pool_size = 8G/' /etc/mysql/my.cnf

预防:上线前用 EXPLAIN 审查慢查询;监控 iostat 的 %util 与 await 并设阈值;IO 型扩容提前做容量规划(参考 4.6:Linux 性能调优 性能调优)。

常见错误

错误模式典型表现根本原因正确做法
直接 rm 日志文件磁盘空间未释放进程仍持有已删除文件的句柄truncate -s 0 或 kill -HUP 进程
遇错就重装系统同类故障反复发生未分析根因,只解决了症状保留日志记录,定位根因再修复
生产环境直接跑高危命令docker prune -a 误删在用镜像未理解 --volumes / -a 的副作用先用 --dry-run 预览,在维护窗口执行
crontab 中写相对路径cron 报 "command not found"cron 的 PATH 仅 /usr/bin:/bin脚本内用绝对路径,或 crontab 设 PATH
修改配置后不 reload配置改了但问题依旧服务未重新加载配置systemctl reload / restart 确认生效
单凭感觉调参数MySQL OOM 不降 innodb_pool 却加 swap未理解内存架构,盲目试错先看 free -h / dmesg,再按预算约束调整

最佳实践

实践具体方案验收标准
日志轮转全覆盖为 Nginx、MySQL、PHP、应用容器均配置 logrotatelogrotate -d 不报错,日志不超过 90 天
磁盘使用率告警部署 node_exporter + Prometheus 或巡检脚本,>80% 预警 >90% 紧急通信工具收到告警消息
关键进程内存保护MySQL / Redis / Nginx 配置 oom_score_adj = -1000OOM 时 dmesg 不再出现关键进程被 kill
定期巡检证书certbot renew --dry-run 每周执行,剩余 < 30 天通知无证书过期相关告警
变更管理所有配置变更前备份,变更后记 changelog可通过 diff 回滚最近一次变更
自动化恢复systemd Restart=always 或自愈脚本覆盖关键服务故障后 60 秒内自动恢复
定期压测每季度用 stress / sysbench / ab 压测,提前发现容量瓶颈压测期间无 OOM / 502 / 延迟陡增

故障处理流程方法论

先恢复后定位原则

生产故障的第一目标不是找根因,而是止血。按优先级行动:

  1. 恢复服务(分钟级):重启服务、切流量到备用节点、回滚最近发布——先让用户可用;
  2. 保留现场:恢复动作前先抓快照(journalctl -bdmesg -T | tail -50、top 记录),否则恢复后无法复盘;
  3. 定位根因(小时级):用四步法分析现场资料,确认是代码、配置还是容量问题;
  4. 长期修复:写补丁、加监控告警、更新 runbook,确保同类故障不再发生。

两个常见错误:服务一恢复就急着复盘,跳过了"保留现场"导致根因永远找不到;或者坚持"先查清原因再动手",把 10 分钟能恢复的故障拖成 2 小时。记住:用户可用性优先,根因分析是第二战场

变更回滚

变更类型回滚方式最佳时机
应用发布保留上一版本包,重启回退发布后 30 分钟内发现异常立即回
配置文件改前 cp 备份,diff 后还原 + reloadreload 报错或指标异常
数据库 DDL只做向后兼容的增量变更(先加列、再迁数据、最后删旧列)DDL 无法直接回滚,靠设计规避
内核/驱动grub 保留旧内核条目,重启时选择开机自检后 10 分钟内
云资源(Terraform)git revert 后 terraform apply 自动回退plan 显示异常变更时

升级机制

故障处理超时或影响面扩大时按级升级,避免"一个人死磕 3 小时":

  1. 一线(值班/基础运维):处理常规故障,15 分钟无进展升级;
  2. 二线(业务运维/研发):带 root 权限和应用代码定位,30 分钟无进展升级;
  3. 三线(专家/厂商):内核、数据库引擎、云厂商工单;
  4. 同时通知业务负责人同步影响面,必要时启动 War Room:专人指挥、专人记录时间线、专人对外沟通,其他人只干活不发声。

SRE 事件管理

事件分级表

级别定义响应时限上报范围
P0(灾难)核心服务完全不可用,影响全部用户立即响应全公司 + 管理层
P1(严重)主要功能受损,影响部分用户或造成资金损失15 分钟技术负责人 + 业务方
P2(一般)非核心功能异常,有绕行方案2 小时运维团队
P3(轻微)体验问题,不影响功能次日记录工单即可

on-call 流程

  1. 告警接收:监控平台(Prometheus + Alertmanager / 云监控)按级别路由到电话、短信、IM;
  2. 确认:值班人在告警后 5 分钟内 ack,超时自动升级到下一人(告警必须绑定 on-call 排班表);
  3. 处理:按 runbook 操作,关键动作(kill、回滚、重启)记录到事件系统;
  4. 沟通:P0/P1 事件建立专用群,每 30 分钟同步一次进展,禁止静默处理;
  5. 复盘:事后 24-48 小时内出 Postmortem:时间线、根因、改进项(每项带负责人和截止日期),改进项跟踪闭环才算结束。

练习题

  1. 磁盘满模拟dd if=/dev/zero of=/tmp/fill bs=1M count=4096 填满测试分区,执行恢复流程:定位大文件 → 清理 → 配置 logrotate。记录每一步命令和输出。
  2. SSH 慢连接诊断:在两台虚拟机之间执行 time ssh user@host true 测耗时。关闭 UseDNS 和 GSSAPI,对比优化前后连接时间差异。
  3. OOM 复现与防护:用 stress --vm 2 --vm-bytes 2G 在 1 GB 内存容器中制造 OOM,观察 dmesg。设置 oom_score_adj 后再次测试,验证保护效果。
  4. Cron 环境变量调试:写一个依赖 /usr/local/bin 工具的脚本,分别通过交互终端和 crontab 执行,对比失败现象。修复后验证 crontab 正确执行。
  5. 证书续期模拟:用 openssl 自签一个 1 天后过期的测试证书,搭建 Nginx HTTPS 站点,编写脚本模拟 certbot 续期流程并验证浏览器信任链。
点击查看答案
  1. df -h 找到满的分区 → du -sh /tmp/fill 确认文件 → rm /tmp/fill 释放空间 → 配置 logrotate 覆盖相关日志目录。记录每步命令输出。
  2. 优化前 time ssh user@host true 可能耗时 10-30 秒。关闭 UseDNS 和 GSSAPIAuthentication 后应降至 1-3 秒。对比输出中的 real 时间差异。
  3. stress --vm 2 --vm-bytes 2G 在 1GB 内存容器中触发 OOM,dmesg -T | grep -i kill 显示 "Killed process"。设置 oom_score_adj = -1000 后 stress 应优先被 kill,受保护进程存活。
  4. 交互终端正常执行 crontab 中报错。修复:crontab 顶部加 SHELL=/bin/bashPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,或脚本内用绝对路径。
  5. openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 1 -nodes 生成 1 天证书。Nginx 配置引用后用 openssl s_client -connect localhost:443 验证有效期。续期脚本执行 openssl 相同命令替换证书并 reload nginx。

学习检查点

学完本章后,请检验自己是否掌握以下内容:

检查项自测问题验证方法
概念理解能用自己的话解释常见运维故障的分类和特点尝试向他人讲解
命令操作能不查文档完成故障排查工具使用、问题定位在终端实际执行
原理掌握能说出故障排查的系统性方法和思维流程画出流程图
故障排查能独立排查服务器宕机、服务不可用、性能下降问题模拟故障并修复
最佳实践能说明为什么需要为故障建立知识库和复盘机制对比不同方案

本章总结

速查表

症状可能原因第一诊断命令
磁盘写失败磁盘满 / inode 满df -h && df -i
进程无故消失OOM Killerdmesg -T | grep -i kill
SSH 登录慢UseDNS / GSSAPIssh -vvv user@host
Nginx 502PHP-FPM 宕 / 队列满systemctl status php*-fpm
HTTPS 报错证书过期 / 链不完整openssl s_client -connect host:443
Cron 没执行PATH 缺失 / 锁冲突journalctl -u cron -S today
Docker 空间满日志 / 悬空镜像docker system df
服务器负载高内存泄漏 / 死循环top -o %MEM && vmstat 1

学习路径

学完本章后,建议依次阅读: 4.5:网络故障排查 网络故障排查方法论与实战(掌握 tcpdump / ss 等底层网络诊断工具)→ 4.6:Linux 性能调优 Linux 系统性能调优实战(深入 CPU/内存/IO 调优指标)→ 4.8:集中式日志管理 集中式日志管理方案(ELK / Loki 统一日志平台)。

延伸阅读

常见问题

日志切割把磁盘写满了怎么办?
紧急处理:du -sh /var/log/* 找到最大日志文件,echo "" > /var/log/xxx.log 清空(不要用 rm,进程仍在写入)。根因:logrotate 配置中的 copytruncate 或 create 权限问题导致旧日志未被删除。在 /etc/logrotate.d/ 中配置 rotate 保留数量、compress 压缩旧日志、size 阈值触发轮转。
CPU 100% 导致 SSH 连不上怎么处理?
通过云控制台的 VNC/串行控制台登录(大多数云厂商提供)。找到 CPU 高占用进程:top 或 ps aux --sort=-%cpu | head。如果是系统进程(如 kswapd0)则内存不足,如果是应用进程则检查应用日志。紧急时 kill -9 或 systemctl restart 重启服务。
域名解析到了旧服务器怎么办?
检查 DNS TTL 设置(迁移前应将 TTL 降到 60 秒,提前 48 小时操作)。dig +short example.com 看当前解析结果。dig +trace example.com 跟踪解析链路。清空本地 DNS 缓存:systemd-resolve --flush-caches。如果使用 CDN(Cloudflare),注意 CDN 的缓存时间。
↑ 回到顶部