ARTICLE DETAIL

资讯详情

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

服务器变慢?用 lscpu、w、top、free、df 五条命令快速定位瓶颈

服务器变慢?用 lscpu、w、top、free、df 五条命令快速定位瓶颈 一台机器突然变慢SSH 进去之后你会先敲哪条命令很多人的第一反应是top因为教程里总说它能看负载、看内存、看进程。但实际上等到一台服务器已经明显卡顿top只能告诉你“现在谁在吃资源”并不能告诉你“这台机器本身的底子是什么”“整体负载是不是真的偏高”“内存是不是已经被耗光”“磁盘是不是已经写满”。我经常和人讲一个观点lscpu、w、top、free、df这五条命令不是五个孤立的工具它们合在一起其实就是一套不需要安装任何额外软件的基础体检流程。单看任何一条都只能得到一个切片连起来才能定位一台机器到底卡在哪个环节。这篇文章就把这五条命令串起来讲一遍先看它们各自回答什么问题再逐个拆关键字段最后给出一套可以直接抄走的排查顺序。你会发现真正重要的不是背下多少参数而是知道下一步该看什么。1. 一台机器变慢时这五条命令就是第一组“仪表盘”1.1 为什么不先翻日志遇到线上事故很多人的本能是去翻应用日志。但日志只能告诉你“应用自己觉得发生了什么”它回答不了系统层面的问题CPU 是不是已经被某个进程占满内存是不是早就到临界点磁盘是不是满到连日志都写不出来了更麻烦的是应用卡死的时候日志可能恰恰是最不可信的那部分。进程在等待磁盘 I/O日志写不下去你看到的最后一条记录可能停在几分钟前。这时候最可靠的判断依据是操作系统自己给出的运行指标。所以我的习惯是先看系统状态再决定要不要翻应用日志。系统层排除了资源问题日志里的报错才有分析价值。1.2 五条命令分别回答什么问题这五条命令各自对应一个最基础但最关键的问题命令回答的问题关键输出lscpu这台机器有多少核什么型号支持超线程吗CPU(s)、Core(s) per socket、Model namew系统开机多久过去 1/5/15 分钟平均负载是多少谁在登录load average、USER、WHATtop当前哪些进程在吃 CPU/内存哪个进程最可疑%CPU、%MEM、RES、%Cpu(s) 和 Mem 汇总行free物理内存还剩多少真正可用的还有多少total、used、availabledf磁盘空间够不够inode 是不是耗尽了Use%、Mounted on、IUse%你注意看这五条命令实际上覆盖了应用跑起来所依赖的全部硬件资源CPU 能力、CPU 负载、内存、磁盘空间。先把这四个维度全过一遍再往下定位具体进程整个排查逻辑才是完整的。2. lscpu先把机器本身的配置看清楚2.1 为什么用 lscpu 而不是直接读 /proc/cpuinfo/proc/cpuinfo也不是不能看但它输出很长每颗逻辑 CPU 都会重复一大段信息而且不同内核版本的字段位置不完全一致。在几千核的服务器上直接看这个文件很痛苦。lscpu是专门用来汇总 CPU 拓扑信息的工具它会把架构、型号、核数、超线程、缓存、NUMA 节点等信息整理成一张表。它本质上是读了/proc/cpuinfo和一些系统文件之后做的汇总但因为输出已经被加工过了更适合人直接看。另外lscpu支持-e以表格形式列出每颗逻辑 CPU 的详细信息也支持-p输出可解析的格式甚至支持-J输出 JSON方便脚本使用。日常排障用不带参数的输出就够了。2.2 看 lscpu 时最需要关注的几行在一台常见的 CentOS 或 Ubuntu 服务器上输出大致是下面这样Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian Address sizes: 46 bits physical, 48 bits virtual CPU(s): 8 On-line CPU(s) list: 0-7 Thread(s) per core: 2 Core(s) per socket: 4 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel Model name: Intel(R) Xeon(R) CPU E5-2682 v4 2.50GHz CPU MHz: 2494.068 L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 20480K这里最容易看迷糊的是三个概念CPU(s)是逻辑 CPU 数量也就是操作系统实际可以调度的执行单元数。Socket(s)是物理 CPU 插槽数也就是你插了几颗物理芯片。Core(s) per socket是每颗物理芯片上的物理核心数。Thread(s) per core是每个物理核心通过超线程模拟出的逻辑线程数。四个数字之间的关系可以写成CPU(s) Socket(s) * Core(s) per socket * Thread(s) per core。上面这个例子就是 1 颗 CPU、4 个物理核、每个核 2 个线程最终 8 个逻辑核。排障的时候为什么一定要先确认逻辑核数因为 load average 是拿这个数字做参考的。一个 8 核机器长期负载跑 8和一台 2 核机器负载跑 8完全是两个概念。前者已经满载后者已经严重过载。2.3 lscpu 不显示型号名多半不是命令坏了不少人会碰到一个情况lscpu输出里没有Model name这一行或者显示成一段很含糊的字符串。第一次遇到时很容易以为是命令坏了。实际上这通常有两个原因。第一种是虚拟化环境虚拟机管理器对 CPU 型号做了隐藏或改写尤其是 QEMU/KVM 默认会用一个通用的 CPU 模型此时主机真实型号不会暴露给虚拟机。第二种是部分系统对/proc/cpuinfo的读取做了限制或者内核启动参数里设置了quiet之类的选项。遇到这种情况可以退一步看cat /proc/cpuinfo | grep model name如果这里也没有就基本可以判断是虚拟化或内核层面的隐藏。此时不需要纠结具体型号重点看 CPU(s) 的逻辑核数再结合lscpu顶部的Hypervisor vendor和Virtualization type来确认这台机器是不是虚拟机。注意在云主机和容器环境里lscpu显示的逻辑核数不一定等于你真正能用的额度。容器场景下要再结合nproc或者 cgroup 配额文件确认否则负载判断会被带偏。3. w负载高不高先看这三个数字3.1 w 的输出拆开看w和uptime其实是同一族命令但w多给了当前登录用户和每个用户在跑什么命令的信息。它的输出大致是这样09:41:23 up 30 days, 4:12, 2 users, load average: 0.52, 0.34, 0.28 USER TTY FROM LOGIN IDLE JCPU PCPU WHAT root pts/0 192.168.1.100 09:10 0.00s 0.05s 0.00s w deploy pts/1 192.168.1.55 08:30 1:08 0.10s 0.10s tail -f app.log第一行包含四个信息块当前系统时间09:41:23。开机时长up 30 days, 4:12。登录用户数2 users。负载均值load average: 0.52, 0.34, 0.28。后面每一行是登录用户的信息从哪个终端登录、来源 IP、登录时间、空闲时间、累计 CPU 时间以及当前正在执行的命令。排障时第一行里的三个 load average 数字是重点第二行以后的用户信息偶尔会用比如你想确认是不是有别的人正在线上跑一个高负载任务。3.2 load average 和 CPU 核数之间的对应关系load average表示一段时间内处于可运行状态和不可中断睡眠状态的进程平均数量。简单理解就是过去这段时间里平均有多少个进程在等待 CPU 或者在等待 I/O 完成。三个数字分别对应过去 1 分钟、5 分钟、15 分钟的平均值。它们之间的关系比单个数字更重要1 分钟 5 分钟 15 分钟说明负载在上升系统正在变得更忙。1 分钟 5 分钟 15 分钟说明负载在下降之前的高峰正在过去。三个数字都比较低说明系统长期空闲。判断负载是否过高不能只看绝对数字要看 CPU 核数。一个粗略的经验是负载接近逻辑核数系统已经基本满载负载超过核数的 70% 左右就要开始关注了负载长期超过核数说明任务排队严重。举个例子8 核机器 load average 到 8说明核都被占满了。16 核机器 load average 到 8说明还有约一半空闲。这就是为什么先把lscpu跑一遍很重要不然你无法解读w的第一个数字。3.3 从 w 到 top进入实时进程视图之前w告诉你负载是多少但它不告诉你负载是谁造成的。所以实际排查时看完w就要切到top。有一条很小的实操经验先把三个负载数字记下来再进top看。因为top打开后会持续刷新你反而看不到最初那几秒的瞬时状态。用w拿到负载基线再用top找原因顺序更合理。另外有些老教程会告诉你直接用uptime替代w。如果你只想看负载和开机时间uptime输出更精简。但如果你怀疑有人登录了机器在乱跑w能多给你一层用户维度的信息。默认优先用w不会错。4. top把“负载高”定位到具体进程4.1 汇总区先于进程区top的默认界面分成上下两块。上面是系统汇总区下面是进程列表。很多人一进去就盯着进程区找红名其实应该先看汇总区。汇总区里最重要的是这两段%Cpu(s): 3.2 us, 1.0 sy, 0.0 ni, 95.4 id, 0.3 wa, 0.0 hi, 0.1 si, 0.0 st KiB Mem : 16266436 total, 184476 free, 8322956 used, 7759004 buff/cache KiB Swap: 8388604 total, 8388604 free, 0 used. 5784204 avail MemCPU 百分比这一行里us是用户态占用普通应用进程跑出来的。sy是内核态占用系统调用和内核任务。id是空闲比例。wa是等待 I/O 完成的时间占比。这个值如果长期偏高说明磁盘或网络存储可能出了问题。st是虚拟机被宿主机抢占的时间比例。云主机的st长期偏高说明宿主机超卖严重你花钱买的 CPU 被邻居挤了。进程区里默认按 CPU 使用率排序。但你至少还要知道两列RES是进程实际占用的物理内存%MEM是它占物理内存的比例。只看 CPU 不看内存容易漏掉内存泄漏。4.2 常用交互键P、M、T、u、p、1top是交互式命令进去之后不是只能干看有几个键要记住大写P按 CPU 使用率排序这是默认。大写M按内存占用排序排查内存问题常用。大写T按累计 CPU 时间排序能发现那种持续跑了很久、累计消耗很大的进程。小写u只看某个用户的进程输入用户名即可。小写p只看指定 PID 的进程常用在已经锁定目标进程之后。数字1展开或折叠每个逻辑 CPU 的独立使用率。多核机器上某个核被占满、其他核空闲时这个视图非常直观。如果你不想进入交互界面比如想在脚本里用可以这样跑top -b -n 1-b是批处理模式-n 1表示只刷新一轮后退出。这个写法适合采集一次性快照不适合做持续监控。持续监控应该用-d指定刷新间隔比如top -b -d 3。4.3 负载高但 CPU 不高时重点看什么这是排障里最容易卡住的一类问题w显示 load average 很高进了top却发现 CPU 占用只有百分之几而且id空闲很高。很多人到这里就懵了。关键在于load average 不只是“CPU 队列长度”它还包括处于不可中断睡眠状态的进程数。不可中断睡眠进程一般是在等什么资源最常见的是磁盘 I/O也可能是 NFS 挂载、锁、网络文件系统。这时候重点看wa那一列如果 iowait 很高先去看磁盘状态。用top按M或P排序后进程状态列如果是D基本可以确认进程在等待 I/O。遇到这种局面继续用top也看不出更多细节了得换成iostat、vmstat、pidstat这类命令去确认到底阻塞在哪个设备。这些不是本文重点但你至少要先知道top能够告诉你“问题在 I/O 上”然后你才知道该往哪个方向继续查。注意top里看到进程状态是D不代表进程已经死了。D是不可中断睡眠一般是在等内核 I/O 完成。直接kill可能无效优先要解决的是底层 I/O 卡住的问题。5. free内存不是只看 used还得看 available5.1 free -h 和 free -m 的区别free默认以字节为单位显示输出长且难读。所以实际使用中几乎都会加单位参数。free -h free -m free -g-h会自动选择合适的人类可读单位-m以 MB 显示-g以 GB 显示。日常看用-h最方便脚本解析用-m更稳定因为单位固定。常见输出total used free shared buff/cache available Mem: 15.5G 7.9G 180M 156M 7.4G 5.5G Swap: 8.0G 0B 8.0G注意一下不同发行版、不同 procps 版本下free的低版本可能还会多一行buffers/cache的统计高版本已经把 buff/cache 合并到 Mem 行里了。字段不完全一样是正常的不用慌重点看available这一列。5.2 buffers/cache 不是真的“可用内存为 0”这是新手最容易误读的地方。看到free列只有一两百兆立刻觉得内存快爆了其实不是。Linux 会尽量把空闲内存拿去做页缓存page cache用来缓存磁盘上的文件这样下次读同样的文件就能直接从内存里命中不用再去磁盘。这部分内存叫buff/cache。它不是进程独占的当某个应用需要更多内存时内核会回收这部分缓存给应用用。所以它属于“可以释放的可用内存”。真正要看的指标是available。它表示在不触发明显交换swap的前提下还能分配给新进程的内存估算值。判断内存够不够available比free和used都可靠得多。如果你想看内存变化趋势可以这样free -h -s 5-s 5表示每 5 秒刷新一次。CtrlC可以退出。这个用法适合在复现内存问题时挂起观察。5.3 结合 top 判断哪个进程吃内存free只能告诉你整体水位不能告诉你谁把内存吃掉的。这时候要回到top按M按内存排序然后重点看第一屏的进程。进程区里这几列要注意区分VIRT进程虚拟内存大小包含共享库、映射文件等参考价值不大。RES进程实际占用的物理内存这是看内存占用的核心。SHR共享内存大小一部分会被多个进程共用。排查内存不足时主要看RES。两个进程 RES 加起来接近 total而available又已经很低基本可以确定内存吃紧。还有一种常见情况某个进程 RES 看着不大但系统内存还是不够。这时候要怀疑是否还有很多小的缓存、内核对象或者某个进程长期堆积了不可释放的内存。可以退到free看used和buff/cache的比值再决定是查进程还是查内核参数。5.4 要不要加 swap不能只看 used看到used很高就急着加 swap这是另一种常见误判。如果available还比较高说明系统只是把内存拿去做缓存了并没有真正的内存压力加 swap 意义不大。如果available已经很低而且top里能看到大量进程处于S状态频繁切换或者dmesg里出现 OOM 相关记录那才说明内存确实吃紧。加 swap 是应急手段不是长期方案。它会掩盖部分问题也会在内存不足时带来额外的磁盘 I/O。现实环境里更稳的做法是先找到吃内存的进程确认是泄漏还是业务需要再决定是扩容、优化还是限制进程内存。6. df磁盘不是只看空间还得看 inode6.1 第一条命令是 df -h第二条是 df -idf -h是最常用的看磁盘空间的命令输出类似Filesystem Size Used Avail Use% Mounted on /dev/vda1 50G 42G 8.0G 84% / tmpfs 1.9G 0 1.9G 0% /dev/shm这里要注意不是每一行都需要紧张。tmpfs使用的是内存/dev/shm占的是共享内存它显示的容量不是真实磁盘空间。真正要看的是挂载在/或者其他业务目录上的盘。但只看df -h是不够的。Linux 文件系统除了空间还有 inode。inode 是文件系统里用来记录文件元数据的结构每个文件和目录都要占用一个 inode。磁盘明明有剩余空间但如果 inode 耗尽系统一样会报“No space left on device”而且你还创建不了任何新文件。所以排查磁盘问题时第二条命令要立刻跟上df -i输出大致如下Filesystem Inodes IUsed IFree IUse% Mounted on /dev/vda1 3276800 3276800 0 100% /当IUse%到 100% 时常见的处理方式是在对应目录下用find找出大量小文件比如日志、临时文件、缓存文件然后清理。6.2 磁盘满但找不到大文件时怎么办df -h显示磁盘满了但用du统计却发现占用对不上这是运维里很容易遇到的情况。先看一段常见思路。用du从根目录往下统计逐层找到大目录du -sh /var/log du -h --max-depth1 / 2/dev/null | sort -hr | head如果空间占用还是对不上有一个非常容易被忽略的场景某个进程打开了一个已经被删除的大文件。进程还在持续往这个文件描述符里写数据文件虽然已经从目录里“不可见”了但空间仍然被占用只有把进程停掉或重启空间才会释放。排查命令lsof L1它会列出所有被删除但仍在占用中的文件。看到这条记录的对应 PID确认是哪个进程在写再决定是重启进程还是让进程先停止写入。这种问题在日志服务、临时文件和数据库场景里尤其常见。日志轮转脚本删了文件但进程没有重新打开新文件就会一直写那个已经 unlink 的 inode 上。等到磁盘满才发现日志已经写丢了一段时间。6.3 磁盘和内存、负载之间的联动磁盘不是独立的问题源它和负载、内存之间会互相影响。磁盘 I/O 慢进程会卡在 D 状态top里wa升高w的 load average 被拉高。这说明负载高不一定就是 CPU 问题可能源头在存储。磁盘满会导致日志写不进去应用要么抛异常要么卡住。有些应用还会因为无法写临时文件而表现为“进程还在但服务异常”这时候从应用日志看是定位不到的。内存不足触发 swap 时swap 的读写落在磁盘上又会让磁盘 I/O 变高。三者互为因果所以排查顺序必须先从整体指标过一遍而不是一进去就盯某一个资源。7. 把五条命令串成一套排查流程7.1 一个先整体后局部的标准顺序这五条命令如果按一套固定顺序跑下来几乎可以覆盖“机器变慢”这个场景的第一步判断先跑w看 load average 三个数字形成负载基线。再跑lscpu确认逻辑核数把负载数字放到正确的参照系里。然后跑top看 CPU 汇总和内存汇总确认是 CPU 型负载、I/O 型负载还是内存压力。接着跑free -h看available判断内存是否真的吃紧。最后跑df -h和df -i确认空间和 inode 是否还有余量。这个顺序不是固定死的。比如你只是临时测一下机器配置可能只需要lscpu。但要回答“这台机器现在到底怎么了”这个宽问题按这个顺序扫一遍基本能得出一个初步结论CPU 瓶颈、内存瓶颈、磁盘瓶颈还是单纯某个进程异常。7.2 组合命令建议和快捷写法如果你想更快拿到所有基础信息可以一次性跑lscpu w top -b -n 1 | head -20 free -h df -h df -i这条命令会把五类信息按顺序输出到屏幕上适合手工排障时快速采集。注意top -b -n 1只取一轮快照再用head -20控制输出行数避免一次刷出整个进程列表。但我个人不建议把这套流程直接写到自动巡检脚本里因为top -b的输出格式在不同版本里不完全一样解析容易出错。如果是监控系统优先用vmstat、sar、collectd这类工具或者自己写脚本时只取明确字段不要依赖top的整屏文本。7.3 这套命令的适用边界和下一步延伸必须说清楚这五条命令适合的是“快速定位大概方向”不适合“深挖某个资源的根因”。如果确认是 CPU 型负载下一步要分析是业务高峰还是异常进程可能要上perf。如果确认是 I/O 型负载下一步要看iostat -x细化到具体磁盘设备。如果确认是内存持续下降下一步要结合应用日志和监控曲线判断泄漏。如果确认是磁盘空间问题下一步要按目录清理并优化日志轮转。所以这些命令更像是一个“分诊台”。它们不是为了替代专业监控而是让你在没有任何监控工具、或者监控数据失效的时候还能靠几条基础命令快速建立判断。这也是为什么它们值得熟练掌握而不是只背命令名。7.4 回到开头工具少而够用关键是把流程练熟回到开头的场景。服务器变慢SSH 进去之后先跑哪条命令答案不是某一个命令而是一组命令的组合。先把lscpu、w、top、free、df这五条命令的输出当成一组仪表盘过一遍机器是不是真的有问题、问题大概出在哪一层你心里基本就有数了。真正有价值的能力是把这个流程练成肌肉记忆看到 load average 数字能马上联想到核数看到wa偏高能想到磁盘看到available很低能想到去 top 里按 M 排序。每一条命令的输出都应该成为你决定下一步命令的输入。这比背下一整本命令大全有用得多。
返回列表