服务公告

服务公告 > 综合新闻 > Linux - Linux故障排查实战 深入理解

Linux - Linux故障排查实战 深入理解

发布时间:2026-04-30 08:01
Linux故障排查实战:系统卡顿、进程异常与性能瓶颈的诊断思路与命令详解,涵盖CentOS/RHEL与Ubuntu双发行版对比

一、前言

搞过运维的人都懂,最怕的不是服务上线,是线上突然报警说系统卡死或者进程炸了。老板在旁边盯着,业务方催着,你对着终端敲命令却不知道该先看哪一项。内存怎么又爆了?CPU怎么飙到100%?磁盘IO怎么堵死了?今天把干了10年遇到的这些烂事捋清楚,给你一套拿来就用的排查套路。

二、操作步骤

步骤1:确认系统整体状态,别盲目猜原因

刚接手一台卡住的机器,先别急着查日志,看看系统整体负载情况,心里先有个数。

CentOS/RHEL & Ubuntu通用:

$ uptime 14:32:01 up 45 days, 3:22, 2 users, load average: 8.24, 6.15, 4.32

这个输出什么意思?load average后面三个数字分别是1分钟、5分钟、15分钟的平均负载。你有4核CPU,load是8.24意味着系统已经过载了,快2倍。8核的话勉强能接受。重点看1分钟值是不是比5分钟、15分钟还在涨,涨的话说明压力在恶化。

CentOS/RHEL & Ubuntu通用:

$ cat /proc/cpuinfo | grep processor | wc -l 8

确认CPU核心数,8核机器load到8才满载,别被吓到。

步骤2:快速定位是哪个资源在打满

系统慢了,无非几种原因:CPU打满、内存不够、磁盘IO堵塞、网络阻塞。用top先扫一眼。

CentOS/RHEL & Ubuntu通用:

$ top -b -n 1 | head -20 top - 14:35:22 up 45 days, 3:25, 2 users, load average: 8.24, 6.15, 4.32 Tasks: 120 total, 3 running, 117 sleeping, 0 stopped, 0 zombie Cpu(s): 85.3%us, 10.2%sy, 0.0%ni, 4.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 16384MB total, 15890MB used, 494MB free, 120MB buffers Swap: 8192MB total, 2100MB used, 6092MB free

一眼扫过去:CPU用户态占85%,系统基本在工作;内存16G用了15.8G,空闲只剩494M,危险;Swap用了2.1G,说明内存真的不够用了,在用交换区。这是典型的内存压力问题。

交互式查看的话,直接按M(内存排序)、按P(CPU排序),能快速看到是哪个进程在抢资源。

步骤3:内存告急时,深挖谁在吃内存

确认内存紧张后,要定位是哪个进程把内存吃掉的。

CentOS/RHEL & Ubuntu通用:

$ ps aux --sort=-%mem | head -10 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND mysql 31892 2.1 45.2 8388608 7.2g ? Sl Jan10 1852:31 /usr/sbin/mysqld java 22341 12.5 30.1 53248 4.9g ? Sl Feb01 892:11 java -jar app.jar nginx 11234 0.8 8.2 2048 1.3g ? S Jan15 124:33 nginx: worker process

RSS列是实际物理内存占用,VSZ是虚拟内存。MySQL吃了45%内存,Java应用吃了30%,加起来就75%了,系统自己还要占一部分,内存能不紧张吗?如果发现某个进程RSS异常高,比如一个Java进程吃了8G内存,那要么是堆设置太大,要么是JVM在搞鬼。

如果是Java进程,快速看JVM堆设置:

$ ps aux | grep java | grep -o '\-Xmx[0-9]*[mMgG]' -Xmx4g -Xms2g

堆设置4G,加上Metaspace、DirectBuffer等,物理内存占用翻倍很正常。

步骤4:CPU飙高时,定位哪个进程和哪个核心

有些时候内存没问题,但CPU一直100%,这时候要细分是哪个进程在消耗CPU。

CentOS/RHEL & Ubuntu通用:

$ top 按1键展开各CPU核心使用率 %Cpu0: 12.5 us, 3.2 sy, 0.0 ni, 84.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1: 98.2 us, 1.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2: 95.6 us, 2.4 sy, 0.0 ni, 2.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

按1之后看到各个核心的详细状态。如果只有某个核心100%,其他核心空闲,说明是单线程搞出来的瓶颈,常见于Java应用GC、Python GIL、某些加密运算。如果是多个核心一起高,可能是高并发导致的正常负载。

进一步定位是哪个线程在消耗CPU:

CentOS/RHEL & Ubuntu通用:

$ top -Hp $(pgrep -f "java") 按P按排序,找到CPU占比最高的线程PID,记下来,转成十六进制: $ printf "%x\n" 32678 7fb6 $ jstack 22341 | grep -A 20 "nid=0x7fb6"

用jstack抓Java进程的线程堆栈,看到这个线程正在GC日志打印或者某段代码里死循环,就能定位问题代码在哪了。这个技巧在处理Java应用CPU 100%的时候特别管用。

步骤5:磁盘IO堵塞的排查方法

系统卡顿有时候不是因为CPU或内存,而是磁盘IO被堵死了。所有进程都在等磁盘响应。

CentOS/RHEL & Ubuntu通用:

$ iostat -x 1 5 Linux 3.10.0-1160.el7.x86_64 (db-server) 02/15/2025 _x86_64_ (8 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 5.23 0.00 2.15 45.32 0.00 47.30 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.00 45.00 0.50 125.00 8.00 6140.00 49.00 8.32 66.20 10.00 67.50 7.90 99.00

关键指标:%iowait是CPU等待IO的时间,45%说明CPU有快一半时间在等磁盘。avgqu-sz是请求队列长度,8.32意味着有大量IO在排队。%util 99%说明磁盘已经饱和了。

具体是哪个进程在大量读写:

CentOS/RHEL & Ubuntu通用:

$ iotop Total DISK READ: 0.00 B/s | Total DISK WRITE: 6.14 MB/s TID PRIO USER DISK READ DISK WRITE COMMAND 28934 be/4 mysql 0.00 B/s 5.89 MB/s mysqld

MySQL在大量写盘,每秒5.89MB。结合前面看到的内存压力,很可能是在做Buffer flush或者慢查询导致临时表落到磁盘。MySQL的innodb_flush_log_at_trx_commit设置、slow_query_log都要查一下。

步骤6:网络异常的排查方向

有些服务不通或者超时,不是硬件问题,是网络层面的问题。

CentOS/RHEL & Ubuntu通用:

$ ss -s Total: 186 (kernel: 243) TCP: 2840 (estab: 12, closed: 2805, orphan: 0, timewait: 3) Socket statuses: %s CLOSE-WAIT 145 ESTABLISHED 12 TIME-WAIT 3

2805个closed状态的TCP连接,145个CLOSE-WAIT。这是有问题的。大量CLOSE-WAIT说明对端已经关闭连接,但本地进程还没来得及close socket,可能是代码有bug或者连接泄漏。大量TIME-WAIT是正常的高并发场景。

查看哪些连接在CLOSE-WAIT:

CentOS/RHEL & Ubuntu通用:

$ ss -ant state close-wait | head -20 State Recv-Q Send-Q Local Address:Port Peer Address:Port CLOSE-WAIT 0 10854 0.0.0.0:3306 192.168.1.102:54321 CLOSE-WAIT 0 10854 0.0.0.0:3306 192.168.1.103:54322

本地的MySQL 3306端口,有两个外部IP的连接处于CLOSE-WAIT状态,说明应用程序没有及时关闭这些连接。看一下应用日志,是不是数据库连接池配置太小,连接用完没释放。

CentOS/RHEL:

$ netstat -anp | grep TIME_WAIT | wc -l 1523

Ubuntu:

$ ss -ant state time-wait | wc -l 1523

CentOS习惯用netstat,Ubuntu建议用ss,性能好太多。大量TIME_WAIT可以用tcp_tw_reuse优化,但核心还是要从架构上减少短连接。

步骤7:日志是最后的救命稻草

前面都排查完还找不到原因,就回到日志。内核日志、应用日志、系统日志。

CentOS/RHEL:

$ journalctl -k --since "10 minutes ago" Feb 15 14:25:01 web-server kernel: Out of memory: Kill process 22341 (java) score 892 or sacrifice child Feb 15 14:25:01 web-server kernel: java: page allocation failure. order:4, mode:0x20

OOM Killer触发了,内核杀掉了java进程。memory cgroup limit触发了,进程被系统强制结束。这就是为什么内存不够时要排查的根本原因。

Ubuntu:

$ journalctl --since "10 minutes ago" --no-pager | grep -i error

Ubuntu用journalctl统一管理日志,比CentOS的老方法方便很多。

CentOS/RHEL:

$ tail -100 /var/log/messages | grep -i error $ tail -100 /var/log/secure | grep -i "failed\|denied"

Ubuntu:

$ tail -100 /var/log/syslog | grep -i error

secure日志看有没有异常登录,messages或syslog看系统服务报错。这两个日志文件是排查系统层面问题的基本入口。

三、常见问题FAQ

Q:系统负载很高但CPU idle也高,什么情况?

这是IO等待导致的假象。load average统计的是等待资源的进程数,如果进程都在等磁盘,CPU没事干,idle看起来很高,但系统就是卡。解决方法不是加CPU,是解决IO瓶颈,看iostat里%iowait和avgrq-sz指标。

Q:top显示内存用了90%以上,但没感觉到卡,需要处理吗?

先看available而不是free。Linux会缓存磁盘数据用于buffer,这部分可回收,别一看used高就慌。但如果available也很低,swap开始大量使用,说明内存真的不够了,需要加内存或者优化应用内存使用。重点盯着:available < total * 0.2 且 swap used > 0,就要处理。

Q:应用突然挂了,日志里看不到错误信息怎么办?

先确认是被OOM Killer杀掉了:dmesg | grep -i kill。再看系统日志:CentOS看/var/log/messages,Ubuntu用journalctl。如果是被内核杀掉,日志里会有"killed byoom_score_adj"这类信息,那问题就清晰了,是内存不足。如果没有任何日志,进程直接消失,检查下是不是收到了SIGKILL信号,用strace跟踪一下。

Q:远程连不上机器,但ping得通,这时候怎么排查?

能ping通说明网络层是通的,问题在应用层。sshd服务可能挂了。先让机房的人物理登录,systemctl status sshd看下状态。journalctl -u sshd --since "30 minutes ago"看启动日志。如果sshd正常但就是连不上,检查是不是iptables规则太严格或者端口被占:ss -tlnp | grep :22。最后确认下SSH连接数是不是满了,ss -s | grep -i established

四、总结

排查Linux系统问题,核心套路就三步:先看整体状态确认资源瓶颈类型,再针对具体资源深度排查,最后用日志验证判断。每个资源类型的典型表现要记牢:CPU高看us+sy,内存高看used+swap,IO高看iowait+util,网络高看连接状态。CentOS用systemctl和journalctl,Ubuntu也用systemctl但日志管理更统一,哪个顺手用哪个。别忘了dmesg和系统日志,那里往往藏着最后的答案。

延伸阅读:想深入的话,学学perf做性能分析,bpftrace做动态追踪,这些都是高级货,学会了能定位更难的问题。

上一篇: Kong - 自动化 深入理解

已经是最后一篇啦!