ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Linux服务器故障排查实战:从CPU到内存与磁盘的完整指南

Linux服务器故障排查实战:从CPU到内存与磁盘的完整指南 简介一份聚焦Linux服务器常见故障排查的PDF资料面向系统运维人员、Linux初学者及需要应急排障的技术支持者。内容以CentOS、RHEL、FreeBSD等系统为背景整理了RAID分区挂载异常、依赖库文件缺失导致root无法登录、GRUB引导分区误删、移除硬盘后进入紧急模式、/usr目录被写满等典型案例并给出从定位到恢复的完整排障思路。每个案例都涉及/etc/fstab配置、fsck修复文件系统、单用户模式、网络引导和MBR修复等关键操作可帮助读者在真实生产环境中快速应对同类问题。整个压缩包为单个PDF文件大小仅367KB便于下载后离线阅读或打印。目前已有92人学习下载。内容预览显示资料采用故障实录方式包含具体命令和处置步骤并结合“胆大心细、谨慎操作”的运维经验总结既适合对照练习也能作为团队内部故障案例参考。通过阅读可掌握文件系统挂载、引导修复、依赖库管理等核心技能降低服务器宕机带来的业务风险。1. 明明白白你的Linux服务器故障篇到底在讲什么带过几年服务器的人都有这种经历业务半夜告警ssh 上去看到 load average 30 起步free 显示内存还剩 200Mdmesg 刷出来一堆 Page alloc 报错你连“先看哪条命令”都要犹豫三秒。这就是《明明白白你的Linux服务器-故障篇[收集].pdf》这类资料想解决的痛——把散落在各处的排查经验收集成一张能照着走的清单而不是让你在 man 手册里现翻。这份文档本质是运维故障场景的实战笔记汇编覆盖 cpu、内存、磁盘、网络、进程、系统日志这一类最常见的服务器故障。适合刚接手服务器的新手也适合被“玄学故障”折腾过的中级运维。它能给你的不是修好某个故障的运气而是一套“先定性、再定位、后处置”的通用流程以及每个环节里该敲的命令和该看的输出。2. 故障定性先行四象限排查法与证据链留存2.1 为什么一上来不能直接重启新手最容易犯的错是看到服务异常就 service xxx restart。重启确实能恢复业务但也把现场毁了进程内存里的状态、TCP 连接表、临时文件的占用关系、/proc 下的实时指标全部归零。等下次再翻车你依然不知道根因。常见的做法是先做“故障定性”把当前问题映射到资源四象限CPU、内存、磁盘IO、网络。方法很简单登录服务器后先花 30 秒跑一遍基础采集把现场固化到文件里再动手处置。# 故障现场快照先留存再排查 TS$(date %Y%m%d_%H%M%S) mkdir -p /tmp/fault_collect_$TS cd /tmp/fault_collect_$TS uptime uptime.txt # 负载与运行时长 free -h free.txt # 内存总量/使用量/Swap df -hT df.txt # 文件系统容量与类型 df -i inode.txt # inode 占用经常被漏 ps aux --sort-%cpu -头两行 top10_cpu.txt # top 10 CPU 进程 ps aux --sort-%mem -头两行 top10_mem.txt # top 10 内存进程 ss -s ss_summary.txt # TCP 连接状态汇总 dmesg -T dmesg.txt # 内核环形缓冲OOM/IO error 都在这 journalctl -p err -n 200 --no-pager journal_err.txt # 最近系统错误日志 echo 现场已保存到 /tmp/fault_collect_$TS这里的思路是每一行采集都对应一个故障维度后续排查时先看这一批文件而不是在终端里反复敲命令。dmesg.txt 尤其关键OOM killer、磁盘 I/O error、NMI watchdog 这类内核级故障都会留痕。journalctl 只取 -p err 是为了过滤掉每天必现的噪音200 条控制在可读范围内。采集完再做处置哪怕最后必须重启你手里也有一条可回放的时间线。这一步对服务器集群排障同样适用——多台一起出问题时每台都留一份快照拿来做横向对比远比逐台 ssh 进去看更省时间。2.2 排查路径怎么定从负载曲线到进程画像定完四象限后下一步是结合业务“已知变化”找切入点。比如压测刚结束就负载高大概率是残留进程mysql 刚部署完 CPU 飙高先看慢查询和线程数crontab 整点跑脚本卡住先对时间线。常见做法是先看 uptime 的负载曲线再落到进程画像# 第一步负载趋势 uptime # 输出示例12:30:01 up 3 days, 4:11, 2 users, load average: 8.02, 5.31, 2.47 # 第二步进程维度归因 ps aux --sort-%cpu | awk NR1 || NR11 {printf %-10s %-8s %-8s %-8s %s\n, $1, $3, $4, $6, $11} # 第三步线程级热点配合 top -H 使用 top -Hb -n 1 -o %CPU | head -25load average 的三个数值分别代表 1、5、15 分钟负载。如果 1 分钟远高于 15 分钟说明故障是最近才发生的往前找半小时内的变更操作反之说明已经持续很久别指望自动恢复。ps 的结果里重点关注 CPU% 和 RSS命令列只取第 11 列是为了避免参数把行撑爆。top -H 是必须养成的习惯。CPU 高是进程级表象具体是哪条线程烧的单看 ps 看不出来。对 Java 应用可以用 jstack 导线程栈对 C/C 程序用 top -H 拿到 TID 后再看 /proc/ /task/ /status 里的 Name或者用 gdb attach 看调用栈。这一步能把问题从“某个进程失控”精确到“某个函数在死循环”。3. CPU与内存故障从负载高到OOM的完整追查路径3.1 CPU 飙高算力瓶颈还是进程失控常见做法是先用 vmstat 看整体再逐层下探。vmstat 1 5 只看五秒钟既能看上下文切换也能确认 CPU 到底是被用户态消耗还是被内核态消耗这一步能省掉很多无用功。# 每1秒采样5次观察 us/sy/id/wa 的变化趋势 vmstat 1 5 # 输出关键字段说明 # r 运行队列长度持续大于CPU核数说明计算密集 # us/sy 用户态/内核态CPU占比sy异常升高先查内核参数与驱动 # wa I/O等待占比长期30%说明磁盘已成瓶颈 # cs 上下文切换次数每秒几十万次能直接拖垮业务 # in 中断次数网络高吞吐时该值会同步升高如果 us 高说明业务进程在做计算往进程画像走如果 sy 高常见诱因是系统调用频繁比如小包高并发网络读写、文件锁竞争、频繁创建线程如果 wa 高问题就转移到了磁盘章节排查。r 列持续大于核数说明 CPU 真正饱和这时候要靠扩容或限流解决单纯调代码收益有限。CPU 故障里最值得记录的一类“伪故障”是软中断softirq打满单核多见于网卡多队列没开或者 RSS 哈希不均匀的场景。排查命令是 cat /proc/interrupts对比各 CPU 的中断分布如果全部落在 CPU0 上说明网卡多队列没有启用需要在网卡驱动层打开 RSS而不是盲目调进程优先级。3.2 内存不足与 OOM谁被杀了为什么是它内存类故障远比 CPU 复杂因为 Linux 的内存分配是“过度承诺”的进程申请 8G物理内存只有 4G 也可能申请成功真正分配时才触发 OOM。所以看到 free 里 available 都快没了不要急着下“加内存”的结论先把 OOM 的判定逻辑搞清楚。# 一、确认内核是否发生过OOM dmesg -T | grep -i -E out of memory|oom-killer|killed process # 典型输出 # Out of memory: Killed process 12345 (java) total-vm:8388608kB, anon-rss:4194304kB # 后面会跟着一段 oom_score 排序表列出候选进程分数 # 二、查看当前各进程内存水位 ps aux --sort-rss | awk NR11 {printf %-10s %-8s %-8s %s\n, $1, $4, $6/1024MB, $11} # 三、查 swap 使用与回写压力 free -h cat /proc/sys/vm/swappinessOOM 发生时内核不会杀“占用内存最大的进程”而是按 oom_score 排序。这个分数由两部分组成进程实际内存占用以及 oom_score_adj 的调整值默认 0可设置 -1000 到 1000。很多 mysql、redis 重启后被杀就是因为没有给关键进程设置 oom_score_adj比如 MySQL 官方便建议设为 -800 到 -1000避免被 OOM killer 当作首选目标。处理 OOM 的原则是“保核心业务弃缓存类进程”。可以在服务的 systemd unit 里配置 OOMScoreAdjust比改内核参数更直接[Service] OOMScoreAdjust-500另外一个排查 OOM 时必须瞄一眼的值是 vm.swappiness。默认 60 表示内存压力下内核倾向于回收匿名页到 swap但对于跑数据库的服务器常见做法是降到 10 甚至 1让回收逻辑优先处理页缓存而不是换出进程内存。注意这只是缓解策略真正的内存黑洞还是要靠 ps 和监控曲线定位。4. 磁盘与IO故障空间、inode和延迟的三角关系4.1 磁盘空间明明是满的为什么 df 和 du 说的不一样磁盘故障是典型的“看起来简单踩坑很深”的一类。df -h 显示 / 已用 100%但 du -sh / 一算实际文件加起来只有一半。新手这时候会怀疑 du 算错了其实两个命令统计的维度本来就不同df 看文件系统块分配du 遍历目录统计文件实际大小。真正的元凶通常是有进程打开了已删除的文件文件还在被写入但目录项已经消失所以 du 看不到df 却算着空间。# 找到“已删除但被占用的文件” lsof -nP | grep (deleted) # 如果数量太多只看当前占用最大的前20个 lsof -nP | grep (deleted) | awk {print $7, $1, $2, $10} | sort -rn | head -20 # 确认后重启对应进程或用 : /proc/pid/fd/fd编号 清空该文件描述符典型的现场是 logrotate 把 access.log 轮转后Java 进程或 nginx 的 worker 还握着旧文件句柄老文件不断增大直到把盘写满。还有一种隐藏较深的场景是删除的 socket 文件或临时文件被某个长驻进程持续使用lsof 输出里能看到 deleted 标记但进程名是个系统服务这时候别瞎 kill先搞清楚它是谁拉起的用 systemctl status 查依赖。inode 也是同类故障的高发区。df -i 显示 inode 100% 时即使 df -h 还有空间系统也建不了新文件。常见原因就两类一是小文件数量爆炸比如临时目录每秒写几百个锁文件二是邮件队列 /tmp 被恶意刷产生了海量零字节文件。排查用 find / -xdev -type f | wc -l 统计文件总数再配合 du -sh --inodes 按目录下钻定位。4.2 I/O 延迟高怎么量化瓶颈在哪一层磁盘 I/O 慢的排查顺序是先看是“所有读写都慢”还是“特定文件慢”再看 “%util” 高不高、await 长不长最后用 iostat 落到具体设备。这里的坑在于 %util 在某些 SSD 上高达 100% 但延迟很低不能单看这一个指标。# 逐秒采样观察设备和分区的读写延迟 iostat -x 1 5 # 关键列 # %util 设备忙占比接近100%说明排队严重NVMe常见虚高 # await I/O平均响应时间机械盘20ms、SSD2ms就算异常 # svctm 实际服务时间与await差值越大说明排队越长 # w_await 写延迟数据库场景重点看这个值 # 定位是哪个进程在产生I/O iotop -bot -d 1 -n 5iotop 输出里关注 TID、IO 读速率和 IO 写速率三列。多数时候你会发现罪魁祸首是备份进程、日志压缩任务或者数据迁移脚本。如果 I/O 压力来自业务进程本身比如 mysql 的 innodb 刷盘优先看 buffer pool 的脏页刷盘策略和 redo log 的组提交设置而不是急着加 SSD。压测磁盘时用 fio 做基准测试不要用 dd。dd 只测顺序写吞吐不能反映随机读写下的真实延迟分布。一个可复用的验证命令是# 随机读写混合场景模拟OLTP应用 fio --namerandrw_test \ --filename/tmp/fio_testfile \ --size2G --rwrandrw --rwmixread70 \ --ioenginelibaio --iodepth32 \ --numjobs4 --direct1 \ --runtime30 --group_reporting # 关注输出的两个指标 # lat (usec) 延迟分布p99 是核心 # IOPS 随机读写能力上限参数说明rwmixread70 模拟 70% 读 30% 写的业务特征iodepth32 控制队列深度直接决定压力大小direct1 绕过页缓存测的是真实磁盘性能而不是内存回写。跑完记得删除测试文件这类大文件常被运维漏掉成为下一次“磁盘写满”事故的隐患。5. 故障排查避坑四类高频误判与处理实录5.1 现象load average 高居不下top 里却看不到CPU占用高的进程排查过程最容易翻车的就是这个场景。uptime 显示 load 20进 top 一看所有进程的 %CPU 加起来都没超过 50%你会怀疑是不是命令看错了。原因通常是不可中断睡眠D 状态进程堆积。这些进程在等待磁盘或网络 I/O不消耗 CPU但会持续计入 load average。处理方法是先 ps -eo state,pid,cmd | grep ^D 找到 D 状态进程再用 cat /proc/ /stack 查看内核栈确认阻塞点。多数情况是 NFS 挂载点失效、磁盘损坏或 FUSE 文件系统卡死。解决要先恢复底层存储而不是反复重启业务进程——重启后新进程继续排队业务照样超时。5.2 现象内存还剩很多业务却报“无法分配内存”free -h 明明显示还有 2G availableJava 应用却抛 OutOfMemoryError或者调用 malloc 返回 NULL。这种误判容易让人直接怪到 JVM 参数头上。原因是进程级的地址空间限制或虚拟内存耗尽而不是物理内存不足。先查 ulimit -v 是否被设置再确认 cgroup 内存上限——docker 容器里 free 看到的是宿主机内存cgroup 限制是另一套账。处理方式是核对容器 spec 里的 memory.limit_in_bytes以及进程实际的 /proc/ /limits用这两者的较小值作为真实可用内存。有些公司内部对 /etc/security/limits.conf 做过统一收紧慢查询、大排序跑起来就会带出这个坑。5.3 现象nginx 频繁 502后端连接被 reset502 的排查路径容易一上来就查后端代码其实是系统层参数把连接断了。用 dmesg 能看到 nf_conntrack: table full 的刷屏日志说明连接跟踪表被打满。原因是 Linux 对每个 TCP 连接都有一条 conntrack 记录默认 nf_conntrack_max 只有几万条。高并发、短连接多的场景下表一满新连接直接被丢弃表现为大量 timeout 和 reset。解决路径分两步先调大参数缓解再优化业务连接复用。# 查看当前连接跟踪使用量 cat /proc/sys/net/netfilter/nf_conntrack_count cat /proc/sys/net/netfilter/nf_conntrack_max # 临时调大重启失效 sysctl -w net.netfilter.nf_conntrack_max524288 # 永久生效 echo net.netfilter.nf_conntrack_max 524288 /etc/sysctl.d/99-conntrack.conf sysctl --system注意不要只调这个参数还要检查 tcp_max_tw_buckets 和 timeout 参数。最稳妥的方向是让业务改用连接池减少新建连接频率。这类问题在服务器集群规模大了之后特别明显一台机器打开的中转连接多了conntrack 表也会被打爆。5.4 现象时间对不上日志顺序错乱证书校验失败日志排查时经常出现另一个“黑匣子”场景同一台机器的两份日志时间线对不上A 应用记录的报错时间比 B 应用早 8 小时查了半天发现是系统时区被改过或者 NTP 同步失败导致时钟漂移。解决方法是先看 timedatectl status 确认时间同步状态再看 /var/log/messages 或 journalctl 里有无 ntp 相关的报错。如果服务器处于内网隔离环境就需要配置内网时间服务器常见做法是指定国内时间服务器先做一次手动校准再写入 chrony 配置。# 手动触发校准适用于临时救急 chronyd -q server ntp.aliyun.com iburst # 落地为持久配置 cat /etc/chrony.conf EOF server ntp.aliyun.com iburst server ntp.tencent.com iburst driftfile /var/lib/chrony/drift makestep 1 3 EOF systemctl restart chronyd chronyc sources -vchrony 的 makestep 1 3 表示前三次同步时允许步进调整时间之后只做微调避免时间跳变导致数据库事务错乱。排查时间问题时要记住先确认硬件时钟RTC和系统时钟是否一致很多虚拟机宿主机重启后会用自己的时间覆盖客户机这是虚拟化场景下的高发坑。6. 事后补救技巧把故障复盘做进日常工具箱故障处理完最后一步不是庆祝而是把现场和处置过程固化成可复用的脚本。我习惯把每次事故的命令序列存成一个 shell 函数放进 ~/.bashrc 或 /usr/local/bin/fault-diag下次再出问题直接一行命令拉出全套上下文。# 故障三件套一次调用一键留存 function fault-snapshot() { local tagfault_$(date %F_%H%M%S) mkdir -p /var/log/fault/$tag uptime /var/log/fault/$tag/uptime.txt dmesg -T --levelemerg,alert,crit,err /var/log/fault/$tag/dmesg.txt 21 ss -s /var/log/fault/$tag/ss.txt ps aux --sort-%cpu /var/log/fault/$tag/ps.txt free -h /var/log/fault/$tag/memory.txt df -hT /var/log/fault/$tag/disk.txt # 对比5分钟前记录的基线判断变化方向 if [ -f /var/log/fault/last.txt ]; then diff /var/log/fault/last.txt /var/log/fault/$tag/uptime.txt || true fi echo 快照已写入 /var/log/fault/$tag }这个脚本的价值在于“把判断沉淀成默认动作”。故障发生的那几分钟里人的紧张情绪会让大脑短路照着清单执行比临时想命令可靠得多。另外建议每次事故处理后用三句话记录什么现象、什么命令定位到了根因、哪个参数或配置避免下次复发。语音转文字记下来也行存成 txt 放到故障目录里。我自己的规矩是同一类故障出现两次就把它写进上面的函数出现三次就做自动巡检脚本。比如上面的 conntrack、时间同步、OOM 这类“高频翻车故障”都可以做成开机自检项。让服务器自己提前报警而不是等用户先发现。希望这份排查思路在你的服务器上同样管用愿你没有机会用到它。本文还有配套的精品资源点击获取
返回列表