
先聊点实际的。我见过太多人一进服务器就敲free -m看到 used 特别高就开始紧张觉得内存不够了。其实这个命令看着简单里面藏着不少门道特别是那几列 buff/cache、available 的含义绝大多数人都没完全搞明白。这篇就把“Linux 查看内存使用情况”这件事从头到尾捋一遍从最基础的 free 命令到 top、vmstat、ps 这些配套工具再到真正排查内存问题时的判断思路和避坑经验全部写清楚。如果你刚接触 Linux或者被free的输出搞得很困惑又或者你已经在用但总担心判断得对不对——这篇文章就是为你准备的。Linux 上的内存管理和 Windows 差别很大它天生愿意把空闲内存用来做缓存所以“空闲内存很少”不代表“内存不够用”这里面的逻辑如果没理顺后面排查问题很容易走弯路。1. 先搞清楚命令在“看”什么free 输出的每一列都代表什么意思很多人上来就执行free -m然后只看两列total 和 used。这样做不是不行但太浪费了而且容易误判。以我自己的服务器为例执行free -h之后输出大概是这样的$ free -h total used free shared buff/cache available Mem: 31Gi 9.2Gi 142Mi 87Mi 21Gi 21Gi Swap: 4.0Gi 0B 4.0Gi1.1 六列数据逐个拆开讲total是物理内存总量这个不多说。used是系统当前已经使用的内存但你得注意这个数值包含了分配给 buff/cache 的那部分。free是完全没有被使用的内存不过在很多内存充足的服务器上你会发现这个数字很小甚至只有几百兆这其实是 Linux 的正常操作——它把内存拿来干活而不是让它闲着。shared这一列主要是 tmpfs 这类共享内存占用的空间一般不太用管它。buff/cache是最容易让人误会的部分它代表被内核用于缓冲和缓存的内存。available这一列最重要的参考价值在于它是“在不触发 swap 的情况下还能启动多少程序”的真实估算值。这个值才是你应该关心的“可用内存”。1.2 为什么说 used 高不代表内存不够我遇到很多新手看到 used 超过 90% 就开始慌了觉得是不是内存泄漏了。其实在 Linux 上这个逻辑不对。Linux 会主动把空闲内存拿去当缓存用来缓存文件读取、磁盘写入等等这样下次访问速度更快。而这些缓存在程序真正需要内存的时候是会被内核快速回收的。所以你看used的时候最好把它理解成“已经被分配出去的内存”其中很大一部分是可回收的缓存。真正要看的是 last 列available。如果 available 还比较宽裕比如剩余 20% 以上那这个系统内存状态基本是健康的。反过来如果 available 一直很低而且 swap 的 si、so 数值持续跳动那才说明内存真的吃紧了。建议你记住一条经验日常判断内存是否够用看available不要看used。这是一个在很多 Linux 老手之间也容易被混淆的细节。1.3 关于 free 命令的几个实用参数我实际用的时候几乎不会裸敲free因为默认单位是字节看起来太费劲。最常用的组合是free -h # 以人类易读的G/M为单位显示 free -h -s 3 # 每隔3秒输出一次适合观察变化趋势 free -h -s 2 -c 5 # 每隔2秒输出一次总共输出5次后自动结束如果你在写脚本希望一次性拿到 available 的数值去做判断那可以直接靠awk解析后面我专门写一段脚本示例。2. 别只守着 freetop、vmstat、ps 这些命令要配合使用free 适合快速看一眼整体情况但如果你要定位“到底是谁把内存吃掉了”那 free 是不够的。至少要把 top、vmstat、ps 这几样东西用起来。2.1 top 是实时观察内存和 CPU 的好帮手很多人打开 top 只看 CPU 那一块其实内存信息也在顶部展示只是被忽略了。top 输出的前几行里有KiB Mem、KiB Swap这两行含义和 free 差不多。但 top 真正的价值是进程列表每个进程的%MEM列直接告诉你这个进程占用了物理内存的百分比。在 top 界面里按一下M键进程列表会按内存占用从大到小排序这是排查内存大户最快的方法。不过要提醒一句进程列表里的VIRT列是虚拟内存大小这个数字通常比实际物理内存占用大得多。你要看的是RES这才是这个进程实际占用的物理内存大小单位是 KiB。有时候一个 Java 进程的 VIRT 能显示到几十个 G但 RES 可能只有几个 G这两者别搞混了。如果你想在脚本里用 top 输出可以配合批处理模式top -b -n 1 | head -30这样 top 会直接输出一次结果然后退出不会进入交互界面。加上head可以只抓前三十行。2.2 vmstat 看的是内存使用趋势而不是瞬间值free 给的是一个快照vmstat 给的是趋势。我排查内存问题的时候常用vmstat 2 5连续采样几次观察si和so这两列。这两列代表从 swap 换入换出的内存大小如果持续大于 0说明系统内存已经不够用了内核正在频繁地把内存页换到磁盘上再换回来这个过程非常消耗性能。vmstat 输出里free列显示的空闲内存也会随着采样变化。buff和cache列对应 free 命令里的 buff/cache。你连续观察几次如果发现 cache 忽高忽低说明系统在缓存和回收之间动态调整这是正常的。如果si、so一直有数字在跳那你得警惕了这是内存压力的信号。2.3 按进程排查内存占用ps、pidstat、smemps 命令可以直接查出进程的内存占用排行榜ps aux --sort-%mem | head -20这个命令会把当前所有进程按内存占用比例排序前 20 个进程就是你重点排查的对象。还有个更精细的工具叫pidstat属于 sysstat 工具包可以看某个进程实时的内存变化pidstat -r 2 10输出里会有 minflt/s、majflt/s、VSZ、RSS 等字段RSS是实际物理内存占用。如果你想分析一个进程里面到底是什么模块吃了内存可以用pmappmap -x PID这个命令会把进程的每一块内存映射都列出来虽然信息很碎但定位内存泄漏或者堆内存增长的时候非常有用。另外如果你的系统里装了smem也可以试试它能输出更准确的 PSS按比例分摊的内存对判断多个进程共享内存的情况有帮助不过大部分基础排查用 ps 和 top 已经够了。3. 从现象到结论判断“内存不够用”的通用方法和真实案例看命令输出只是第一步真正有价值的是你会不会解读这些输出。很多人执行完free -h后还是不知道接下来该干嘛这是因为缺少一套完整的判断思路。下面我把自己排查内存问题时常用的套路完整拆给你看。3.1 三分钟判断内存是否够用的实用步骤第一步看整体。执行free -h重点看 available。如果 available 只剩下总量的 10% 以下说明系统可用内存大幅减少了需要继续往下排查。第二步看趋势。用vmstat 2 5连续采样观察 si、so 是否持续非零。如果是说明系统正在靠 swap 硬撑性能一定会受影响。第三步看进程。用ps aux --sort-%mem找出占用最高的几个进程确认到底是哪个程序在吃内存。如果 available 还比较充足但你发现机器响应慢那问题大概率不在内存上可能是 CPU、磁盘 I/O 或者其他方面。这时候盲目清缓存、加内存方向就错了。还有个小技巧如果你发现 buff/cache 特别高别着急去清理。理解成 Linux 是用这部分内存来加速文件读写和磁盘缓存程序一旦有需要内核会自动回收。我以前见过有人迷信echo 3 /proc/sys/vm/drop_caches这种清缓存操作天天跑其实在大多数场景下只会让缓存失效反而降低性能。真正有用的时机是你刚做完内存相关的性能测试需要清理缓存让结果更准确那才适合手动清。3.2 OOM 风险到底怎么看内存不够用的极端结果是 OOM Killer也就是系统内存耗尽时内核会挑一个进程把它杀掉腾出空间。要检查系统是否发生过这种事件可以执行dmesg | grep -i oom journalctl -k | grep -i oom如果输出里有 “Out of memory: Killed process”那说明这台机器确实出现过内存耗尽的情况。这种情况一般有两种诱因要么是某个进程申请了大量内存超过了物理内存加 swap 的总量要么是系统配置的 overcommit 策略允许进程超额申请内存结果真到用到的时候内存不够了。预防 OOM 的思路有几种调整进程的内存限制比如 JVM 的-Xmx优化程序本身的内存使用或者适当调整vm.overcommit_memory策略。这里有个我踩过的坑事到临头才抄起 free 去查内存已经晚了。正确的做法是提前监控多观察 available 的变化趋势发现问题早处理。3.3 一次真实排查Web 服务频繁重启背后的内存真相去年我处理过一台测试服务器的问题现象是一个 Web 服务每隔几小时就自动挂掉重启后又正常过一阵子又挂。一开始大家都怀疑是程序 bug后来我看了一眼free -havailable 只剩不到 1G而 total 是 8G。接着用vmstat 2 5采样发现 si、so 频繁跳动说明内存早就吃紧了。再执行ps aux --sort-%mem排在第一的是一个 Java 进程占用超过 5G。问题是这台服务器本身只有 8G 内存还跑着 MySQL、Redis 这些服务空间自然不够。我再用pmap -x 进程PID看了下 Java 进程的内存分布发现堆内存占了绝大部分于是把 JVM 的-Xmx从 4G 调低到 3G并且设置了-XX:HeapDumpOnOutOfMemoryError方便下次有问题时留存现场。调整之后服务稳定多了内存 available 保持在三四个 Gswap 也不怎么动了。这个案例想说的是排查内存问题光看一个命令不够要结合系统整体状况和进程详情综合判断。而且很多“程序不稳定”的问题根源是内存资源不足不是业务代码的锅。4. 实操细节与避坑技巧这些经验和表格值得收藏到了这个部分分享一些我在实际使用中总结出来的细节。很多内容属于“命令文档里不会写但运维和生产环境下一定会碰到”的规则。4.1 常见问题速查表现象可能原因处理建议free 显示 used 超过 90%内存被正常使用或缓存占用需看 available 判断用 available 判断不要只看 usedbuff/cache 占了好几个 GLinux 自动用空闲内存做缓存属于正常行为不需要清理程序需要时内核会自动回收swap 的 si/so 一直有数值物理内存不足系统在反复换页定位占用高的进程优化或扩容内存available 持续走低有进程在持续申请内存可能存在泄漏用 ps、pidstat、pmap 找具体进程查看不到 available 这一列系统版本较旧free 输出没有该字段切换用free -w或读取/proc/meminfo的MemAvailabletop 中 VIRT 特别大进程申请了虚拟地址空间不代表真占内存看 RES 列那才是实际物理内存占用遇到上面这些情况别再凭感觉操作先对照这个表定位一下问题方向。4.2 buffer 和 cache 到底有什么区别我经常被人问到这个问题这里用最简单的话说清楚。buffer是用来缓冲块设备读写的比如磁盘数据cache更偏向于页面缓存用来缓存文件内容。更细的区分可以看/proc/meminfo里面分别有Buffers、Cached、Dirty、Writeback这些字段。Dirty表示待写的脏页Writeback表示正在写入磁盘的页面数量。如果你发现 Dirty 数值持续偏高说明磁盘写入压力大这时候直接看iostat可能比盯 free 更有效。实际运维里你不需要把 buffer 和 cache 分得那么细致只要记住一件事这两块都是内核为了加快文件磁盘读写而设置的可回收缓存。它们不是进程独占的内存所以系统内存紧张时这些缓存会被自动释放给应用程序使用。4.3 写脚本判断内存是否够用的正确姿势在很多自动化发布脚本里我们经常需要判断当前内存是否满足启动某个重服务的条件。这时候不能用 used也不能用 free最靠谱的是用 available。比如用free -m加 awk 提取mem_available$(free -m | awk /^Mem:/{print $7}) echo 当前可用内存: ${mem_available}M if [ $mem_available -lt 2048 ]; then echo 可用内存不足2G放弃启动 exit 1 fi如果你的 Linux 发行版较老free 输出没有 available 这一列可以改用/proc/meminfomem_available$(grep MemAvailable /proc/meminfo | awk {print $2}) mem_available$((mem_available / 1024))这两种方法都能拿到可用的内存值。在脚本里做阈值判断时建议根据服务实际需求来定别一刀切设个 1G 就到处用。我之前见过有脚本把阈值设得太高导致内存明明充足服务却起不来的情况。4.4 不同发行版的输出差异要心里有数free 命令的输出格式在不同发行版和不同版本里是有差异的。CentOS 7 和 Ubuntu 20.04 上输出的单位、缓冲列的名字都不太一样。比如有些老版本需要加-m才会用兆字节显示不带参数时默认显示字节。还有一点部分精简版系统的 free 命令可能没有--si这类选项需要你先man free确认一下帮助信息别在脚本里用了不存在的参数导致解析失败。另外国产的一些 Linux 发行版比如麒麟系统日常命令和标准的 Linux 命令基本一致free、top、vmstat、ps都可以直接用这个不需要担心。之前有朋友在麒麟上跑惯了 Windows 的思路老想找图形界面查看内存其实字符界面下这些命令更高效。4.5 内存查看的扩展cgroup 和容器场景下的注意事项如果你在用 Docker 或者 Kubernetes千万别只盯着宿主机上的 free 看。容器里面的内存限制是独立的宿主机内存状态不能直接代表容器内的情况。在容器里你可以执行cat /sys/fs/cgroup/memory/memory.usage_in_bytes查看当前容器的内存使用量或者通过cat /sys/fs/cgroup/memory/memory.limit_in_bytes查看限制。宿主机 free 正常但容器一直 OOM这种问题要用 cgroup 维度去排查别被大面上的数据迷惑了。我实际处理过一起案例宿主机内存明明还剩 20G但容器里的 Java 服务就是一直重启最后发现是容器限了 1G 内存堆根本不够用。这就是典型的不看 cgroup只在宿主机上排查导致的方向性错误。写在最后关于内存监控我个人的一点体会接触 Linux 这么多年内存这块踩过不少坑。现在我的习惯是先看 free 的 available再看 vmstat 的趋势最后用 ps 定位进程整个过程尽量控制在几分钟内。日常监控不要等出了事才去看命令建议把这些命令提前写成采集脚本定时把 available、swap 使用率、内存占用 TOP 5 进程这些关键指标记录到日志里方便事后回溯。这样出了状况你手里有第一手材料排查起来会顺手很多。最后再分享一个小技巧判断内存是否真的够用优先信任 available 字段它是内核综合考虑了可回收缓存后给应用程序“到底还能用多少内存”的估算值。如果 available 在持续下降那比 used 高不高更能说明问题。以后不要再被 buff/cache 恐吓到了也别急着清缓存多数情况下Linux 比你更知道怎么用这些内存。