Linux性能故障排查实战指南

📅 2026/7/21 5:45:06
Linux性能故障排查实战指南
目录一、Top各个指标含义1.1 主要关注的核心指标二、故障场景解决思路与命令2.1 场景一us飙高 (70%) ——“应用代码暴走”2.1.1 场景描述2.1.2 排查思路2.2 场景二sy飙高(30%) —— “内核被拖垮”2.2.1 场景描述2.2.2 排查思路2.3 场景三wa飙高20%——“磁盘拖后腿”2.3.1 故障场景2.3.2 排查思路2.4 场景四端口被占用服务起不来2.4.1 故障场景2.4.2 排查命令2.5 场景五磁盘空间满了但找不到大文件2.5.1 故障场景2.5.2 排查命令2.6 场景六 某个目录无法卸载2.6.1 故障场景2.6.2 排查命令一、Top各个指标含义指标含义load average0.00,0.04,0.071 分钟/5 分钟/15 分钟的平均负载。这 3 个数分别表示过去 1 分钟、5 分钟、15 分钟内系统正在运行或等待运行的进程数包括正在 CPU 上执行的 等待 I/O 的。Tasks: 90 total, 2 running, 87 sleeping, 1 stopped, 0 zombie90个进程任务2运行87休眠或等待1停止0僵尸%Cpu(s): 0.8 us, 0.3 sy, 0.0 ni, 98.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stus用户态进程sy:内核态进程ididel:cpu空闲比例ni被调整过优先级nice进程wa等待磁盘I/O时间hi处理硬件中断si处理软件中断st虚拟机被宿主机偷走的 CPU 时间。0代表宿主机没有超售挤压你KiB Mem : 3733340 total, 1771012 free, 214136 used, 1748192 buff/cachetotal:物理内存总量free:完全空闲的内存used已使用的内存(不包括缓存和缓冲区)buff/cache:用来做磁盘缓存和文件缓存的内存KiB Swap: 0 total, 0 free, 0 used. 3230516 avail Mem没有swap所有都为0avail Mem:真正可用的内存free可以回收的buff/cache1.1 主要关注的核心指标指标正常范围危险阈值load averagecpu核心数cpu核心数*2us50%70%sy20%30%wa5%20%id20%10%二、故障场景解决思路与命令2.1 场景一us飙高 (70%) ——“应用代码暴走”2.1.1 场景描述618刚开始10分钟用户反馈APP下单转圈客服电话被打爆2.1.2 排查思路找CPU最高进程 -- 看该进程最忙线程 -- 转16进制 -- 定位到具体代码行 -- 重启# 第1步找到吃 CPU 的进程 ps aux --sort-%cpu | head -10 # 得到 PID假设是 1234 # 第2步查看该进程的线程 top -Hp 1234 # 按 P 键按 CPU 排序 # 得到最忙的 TID假设是 12345 # 第3步如果是 Java 应用定位代码 # 转 TID 为 16 进制nid printf %x\n 12345 # 输出 0x3039 # 第4步打印线程堆栈 jstack 1234 | grep -A 30 nid0x3039 # 看到具体代码行OrderService.java:156 # 第5步重启 systemctl restart order-service2.2 场景二sy飙高(30%) —— “内核被拖垮”2.2.1 场景描述某个微服务上线后30min所有服务器响应变慢ssh登录都卡2.2.2 排查思路查看上下文切换 -- 看每个进程切换次数 -- 跟踪进程系统调用 -- 看线程是否太多# 第1步查看上下文切换频率 # 每秒刷新看上下文切换cs和中断in vmstat 1 5 # 第2步确认是哪个应用导致 # 看系统调用统计按进程 strace -c -p PID # 对多个进程分别执行 # 或者全局看 pidstat -w 1 5 # 第3步查看该进程的系统调用 # 跟踪进程的系统调用采样 30 秒只看汇总 strace -c -p 1234 -f # 按 CtrlC 停止后显示汇总 # 第4步查看线程数是否过多 # 查看进程的线程数 ps -Lf 1234 | wc - # 或者看系统总线程数 ps -eLf | wc -l # 第5步紧急止血 # 方案1重启有问题的服务 systemctl restart service-name # 方案2如果无法重启先限制其 CPU 使用率 cpulimit -p 1234 -l 50 -b # 限制到 50% # 方案3如果是有问题的批量任务直接停止 pkill -f batch_script.sh2.3 场景三wa飙高20%——“磁盘拖后腿”2.3.1 故障场景每天凌晨 2 点定时任务执行时业务查询超时页面加载极慢2.3.2 排查思路看磁盘I/O -- 找I/O进程 -- 看磁盘空间 -- 找大文件 -- 查MySQL# 第1步确认磁盘 I/O 整体情况 # 查看磁盘 I/O 统计每秒刷新持续 3 次 iostat -x 1 3 # 第2步找出谁在疯狂写磁盘 # 实时显示正在 I/O 的进程需要 root 权限 sudo iotop -o # 第3步检查磁盘空间是否满了 df -h # 第4步找大文件所占空间 # 查看根目录下各目录大小排序 du -sh /* 2/dev/null | sort -rh | head -10 # 或进入 /var/log 查看日志文件 cd /var/log du -sh * | sort -rh | head -10 # 第5步检查是什么导致 MySQL 大量写 # 登录 MySQL查看当前执行的查询 mysql -e SHOW PROCESSLIST\G # 查看 InnoDB 状态看脏页比例、写入量 mysql -e SHOW ENGINE INNODB STATUS\G | grep -A 10 BUFFER POOL AND MEMORY # 看 binlog 写入量 mysql -e SHOW MASTER STATUS; # 第6步紧急止血 # 止血方案1如果是日志占满直接清理 /var/log/mysql/slow.log # 清空慢查询日志不删除文件 /var/log/nginx/access.log # 清空访问日志 # 止血方案2kill 掉 I/O 大户 sudo iotop -o # 按 k 键输入要杀的 PID # 止血方案3如果是 MySQL 在重建索引先取消 mysql -e KILL process_id; # 止血方案4降低 MySQL 写入压力临时 # 调整 sync_binlog 0风险断电可能丢数据 # 调整 innodb_flush_log_at_trx_commit 2 ​2.4 场景四端口被占用服务起不来2.4.1 故障场景systemctl start nginx # 报错Address already in use: AH00072: make_sock: could not bind to address [::]:802.4.2 排查命令# 第1步查看谁占用了 80 端口 lsof -i :80 # 第2步 :杀掉占用端口的进程 kill -9 1234 # 或者如果是自己的服务停掉它 systemctl stop httpd2.5 场景五磁盘空间满了但找不到大文件2.5.1 故障场景df -h # /dev/sda1 50G 50G 0G 100% / du -sh /* # 加起来远小于 50G #故障原因有文件被rm删除了但进程还在打开它空间未释放2.5.2 排查命令# 找到所有被删除但未释放的文件 lsof | grep deleted # 看具体哪几个文件占用了空间按大小排序 lsof | grep deleted | awk {print $7, $9} | sort -n -r | head -10 # 重启进程 systemctl restart java-service2.6 场景六 某个目录无法卸载2.6.1 故障场景umount /data # 报错target is busy2.6.2 排查命令# 查看谁在使用 /data 目录 lsof /data # 递归查看目录下所有被打开的文件 lsof D /data kill -9 进程号 # 然后再 umount umount /data