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
知识关联
- 前置知识:2.7:日志与故障排查 日志与故障排查(journalctl/dmesg 基础)、4.5:网络故障排查 网络故障排查(traceroute/ss/tcpdump)、3.15:Cron 定时任务 Cron 高级定时任务(任务调度机制)
- 后续影响:4.8:集中式日志管理 集中式日志管理(故障数据持久化)、5.13:auditd 审计 auditd 审计(审计日志辅助根因分析)
- 配套技术:故障复盘四步法贯穿全章,logrotate + cron + 巡检脚本形成预防体系,监控告警工具链(Prometheus + Alertmanager)
原理讲解
系统化故障排查四步法:
- 查日志(What happened?) — 查看系统日志(journalctl -xe)、内核日志(dmesg -T)、应用日志(access_log、error_log)。日志是故障现场的第一手证据,务必最先查看。
- 查资源(What's the state?) — CPU(top / vmstat)、内存(free -h)、磁盘(df -h / df -i)、网络(ss -tlnp、iftop)。资源耗尽是最常见的故障根源之一。
- 查配置(What changed?) — 对比最近变更的配置文件、软件版本升级、防火墙规则。用
rpm -Va或diff -r /etc/ /etc.bak/对比基线。 - 复现(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、应用容器均配置 logrotate | logrotate -d 不报错,日志不超过 90 天 |
| 磁盘使用率告警 | 部署 node_exporter + Prometheus 或巡检脚本,>80% 预警 >90% 紧急 | 通信工具收到告警消息 |
| 关键进程内存保护 | MySQL / Redis / Nginx 配置 oom_score_adj = -1000 | OOM 时 dmesg 不再出现关键进程被 kill |
| 定期巡检证书 | certbot renew --dry-run 每周执行,剩余 < 30 天通知 | 无证书过期相关告警 |
| 变更管理 | 所有配置变更前备份,变更后记 changelog | 可通过 diff 回滚最近一次变更 |
| 自动化恢复 | systemd Restart=always 或自愈脚本覆盖关键服务 | 故障后 60 秒内自动恢复 |
| 定期压测 | 每季度用 stress / sysbench / ab 压测,提前发现容量瓶颈 | 压测期间无 OOM / 502 / 延迟陡增 |
故障处理流程方法论
先恢复后定位原则
生产故障的第一目标不是找根因,而是止血。按优先级行动:
- 恢复服务(分钟级):重启服务、切流量到备用节点、回滚最近发布——先让用户可用;
- 保留现场:恢复动作前先抓快照(
journalctl -b、dmesg -T | tail -50、top 记录),否则恢复后无法复盘; - 定位根因(小时级):用四步法分析现场资料,确认是代码、配置还是容量问题;
- 长期修复:写补丁、加监控告警、更新 runbook,确保同类故障不再发生。
两个常见错误:服务一恢复就急着复盘,跳过了"保留现场"导致根因永远找不到;或者坚持"先查清原因再动手",把 10 分钟能恢复的故障拖成 2 小时。记住:用户可用性优先,根因分析是第二战场。
变更回滚
| 变更类型 | 回滚方式 | 最佳时机 |
|---|---|---|
| 应用发布 | 保留上一版本包,重启回退 | 发布后 30 分钟内发现异常立即回 |
| 配置文件 | 改前 cp 备份,diff 后还原 + reload | reload 报错或指标异常 |
| 数据库 DDL | 只做向后兼容的增量变更(先加列、再迁数据、最后删旧列) | DDL 无法直接回滚,靠设计规避 |
| 内核/驱动 | grub 保留旧内核条目,重启时选择 | 开机自检后 10 分钟内 |
| 云资源(Terraform) | git revert 后 terraform apply 自动回退 | plan 显示异常变更时 |
升级机制
故障处理超时或影响面扩大时按级升级,避免"一个人死磕 3 小时":
- 一线(值班/基础运维):处理常规故障,15 分钟无进展升级;
- 二线(业务运维/研发):带 root 权限和应用代码定位,30 分钟无进展升级;
- 三线(专家/厂商):内核、数据库引擎、云厂商工单;
- 同时通知业务负责人同步影响面,必要时启动 War Room:专人指挥、专人记录时间线、专人对外沟通,其他人只干活不发声。
SRE 事件管理
事件分级表
| 级别 | 定义 | 响应时限 | 上报范围 |
|---|---|---|---|
| P0(灾难) | 核心服务完全不可用,影响全部用户 | 立即响应 | 全公司 + 管理层 |
| P1(严重) | 主要功能受损,影响部分用户或造成资金损失 | 15 分钟 | 技术负责人 + 业务方 |
| P2(一般) | 非核心功能异常,有绕行方案 | 2 小时 | 运维团队 |
| P3(轻微) | 体验问题,不影响功能 | 次日 | 记录工单即可 |
on-call 流程
- 告警接收:监控平台(Prometheus + Alertmanager / 云监控)按级别路由到电话、短信、IM;
- 确认:值班人在告警后 5 分钟内 ack,超时自动升级到下一人(告警必须绑定 on-call 排班表);
- 处理:按 runbook 操作,关键动作(kill、回滚、重启)记录到事件系统;
- 沟通:P0/P1 事件建立专用群,每 30 分钟同步一次进展,禁止静默处理;
- 复盘:事后 24-48 小时内出 Postmortem:时间线、根因、改进项(每项带负责人和截止日期),改进项跟踪闭环才算结束。
练习题
- 磁盘满模拟:
dd if=/dev/zero of=/tmp/fill bs=1M count=4096填满测试分区,执行恢复流程:定位大文件 → 清理 → 配置 logrotate。记录每一步命令和输出。 - SSH 慢连接诊断:在两台虚拟机之间执行
time ssh user@host true测耗时。关闭 UseDNS 和 GSSAPI,对比优化前后连接时间差异。 - OOM 复现与防护:用
stress --vm 2 --vm-bytes 2G在 1 GB 内存容器中制造 OOM,观察 dmesg。设置 oom_score_adj 后再次测试,验证保护效果。 - Cron 环境变量调试:写一个依赖 /usr/local/bin 工具的脚本,分别通过交互终端和 crontab 执行,对比失败现象。修复后验证 crontab 正确执行。
- 证书续期模拟:用 openssl 自签一个 1 天后过期的测试证书,搭建 Nginx HTTPS 站点,编写脚本模拟 certbot 续期流程并验证浏览器信任链。
点击查看答案
df -h找到满的分区 →du -sh /tmp/fill确认文件 →rm /tmp/fill释放空间 → 配置 logrotate 覆盖相关日志目录。记录每步命令输出。- 优化前
time ssh user@host true可能耗时 10-30 秒。关闭 UseDNS 和 GSSAPIAuthentication 后应降至 1-3 秒。对比输出中的 real 时间差异。 stress --vm 2 --vm-bytes 2G在 1GB 内存容器中触发 OOM,dmesg -T | grep -i kill显示 "Killed process"。设置oom_score_adj = -1000后 stress 应优先被 kill,受保护进程存活。- 交互终端正常执行 crontab 中报错。修复:crontab 顶部加
SHELL=/bin/bash和PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,或脚本内用绝对路径。 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 Killer | dmesg -T | grep -i kill |
| SSH 登录慢 | UseDNS / GSSAPI | ssh -vvv user@host |
| Nginx 502 | PHP-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 统一日志平台)。
延伸阅读
- logrotate(8) — 日志轮转配置语法详解
- Linux Kernel /proc 文档 — oom_score_adj、oom_adj 的含义与调优
- Certbot 官方文档 — 证书自动续期最佳实践
- Docker 日志驱动配置 — 容器日志大小限制标准
- journalctl(1) — systemd 日志查询高级用法
- Google SRE 运维最佳实践 — 故障事后复盘(Postmortem)文化
- 本书章节:2.7:日志与故障排查 日志与故障排查 · 3.12:系统监控与告警 系统监控方案 · 5.1:Linux 安全加固 Linux 安全加固 · 4.5:网络故障排查 网络故障排查 · 4.6:Linux 性能调优 Linux 性能调优 · 4.8:集中式日志管理 集中式日志管理 · 3.15:Cron 定时任务 Cron 高级定时任务 · 4.13:服务器初始化规范 服务器初始化规范 · 5.13:auditd 审计 auditd 审计