十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Linux free命令详解:从字段含义到内存排查实战

Linux free命令详解:从字段含义到内存排查实战 一台服务器突然变慢负载看着不高但你敲 free -h 的时候发现 available 只剩几百兆Swap 开始频繁变化这时候基本可以断定内存是罪魁祸首。free 命令是 Linux 系统管理里最常用也最容易被低估的命令输出只有几行却把物理内存、内核缓存、Swap 使用的整体状态全摆在台面上。这篇实操篇会从输出字段讲到参数组合再从缓存机制讲到排查内存问题的完整思路适合刚上手 Linux 的初学者也适合每天和服务器打交道的运维、开发同学。看完之后你不只会敲 free还能拿着输出结果判断这台机器到底该不该加内存。1. free 命令到底能告诉我们什么1.1 一个输出示例和五个核心字段先看实际输出。在 CentOS 7、Ubuntu 22.04 这类主流发行版上直接执行 free 或者 free -h看到的内容大致是$ free -h total used free shared buff/cache available Mem: 30Gi 5.6Gi 1.2Gi 1.0Gi 24Gi 24Gi Swap: 8.0Gi 0.0B 8.0Gi现在的 free 命令默认以人类可读的方式展示单位是 Gi、Mi。第一行 Mem 是物理内存整体统计第二行 Swap 是交换分区或交换文件的统计。绝大多数情况下第二行容易被忽略但如果 Swap 的 used 持续上涨问题通常比物理内存不足更严重。五个核心字段分别是 total、used、free、shared、buff/cache、available。total 是这台机器可见的总内存包含内核预留和硬件占用通常比物理内存标称值小一点。used 在传统理解里是“已经被程序占用的内存”但这个数字有迷惑性因为它计入了可以随时回收的缓存部分。free 是真正剩余、一点没被动用的内存运行了一段时间的服务器上这个数值通常很小。shared 是 tmpfs 等共享内存占用的空间多进程间共享的页面会统计在这里。buff/cache 是内核为块设备和文件系统准备的缓存它既可以被应用复用也可以在内核需要时回收。available 是比 free 更值得看的字段它估算“在不触发 Swap、不严重性能下降的前提下还有多少内存可以分配给新程序”。这个值不是简单的 free 加 buff/cache而是内核根据回收成本动态估算的。这也是很多人只看 free 字段导致误判的原因。1.2 used、free、available 三者之间的关系很多新手会直接拿 used 去除以 total算出来“内存用了 80%”然后慌慌张张去加内存。实际上这个比例参考价值有限。Linux 的内存管理默认会尽量利用空闲内存做缓存所以一个运行了半年的 web 服务器used 可能看起来非常接近 100%但系统依然非常流畅。原因就是 buff/cache 中的大部分页面属于 page cache一旦某个进程需要内存内核能迅速回收并转给业务。要判断内存是否真的紧张优先级应该是available 是否长期低于某个阈值Swap 是否开始被写入内存回收线程是否频繁活动。available 是一个动态估算值它的存在就是为了避免你被裸的 free 字段误导。如果 available 持续不足比如低于总内存的 10% 或固定值再结合业务实际表现去判断是否加内存而不是看到 used 高就急着扩容。1.3 为什么 “free 内存很小” 不能直接判定内存不足我遇到过很多次开发同事截图 free 命令说内存不够用了截图里 free 只剩几十 MB。但如果他顺手看一眼 available会发现还有十几个 G。这个误判在缓存密集的应用场景里尤其常见比如数据库、文件服务器、静态资源代理。Linux 内核把磁盘读取过的文件页留在内存里下次访问直接命中能省下大量 I/O。这是性能优化不是异常。判断内存是否不足我自己的经验是看三点available 是否趋近于 0、Swap 的 used 是否持续增长、系统日志里是否有 OOM 记录。这三个里面任何一个亮红灯才真正说明内存不够。若只是 free 字段小不用管它那是缓存干得好。2. free 命令的参数选择与监控技巧2.1 按场景选择显示单位-b、-k、-m、-g、-hfree 默认显示单位是 KiB也就是 1024 字节。但生产环境里你直接敲 free第一眼可能反应不过来 12345678 是多少 G。所以实际操作中 -h 是最常用的参数直接自动选一个合适的单位比如 2.3Gi、512Mi人一眼能看明白。但 -h 不适合脚本解析。脚本里需要按固定单位做阈值判断时建议用 -mMB或 -gGB输出是纯数字不用做单位换算。注意这里 free 单位基于 1024不是 1000。-m 显示的是 MiB-g 显示的是 GiB。某些存储场景需要精确值时用 -b 拿到字节数。我的建议是人看的时候用 -h脚本判断用 -m 或者 -b。单位选择的核心是避免阅读歧义也避免脚本里正则匹配失败。不要在一个命令里同时混用多个单位不然会遇到后续解析困难的问题。2.2 组合参数实现持续监控-s 与 -c有些场景需要观察内存变化趋势比如业务发布后缓存被冲掉、内存慢慢涨上来这时可以结合 -s 参数让 free 每隔几秒刷新一次。例如free -h -s 3它会每 3 秒打印一遍当前输出有点像 top 的刷新行为。再配合 -c 可以设置退出前的刷新次数避免在脚本里写死循环free -h -s 2 -c 5这个命令会以 2 秒间隔输出 5 次然后自动退出非常适合放在监控脚本或 CI 流程里抓取瞬时内存状态。实际使用中如果你想记录内存变化曲线直接把它重定向到文件也是一行命令的事。不过要提醒一下-s 参数持续输出会占用一个终端如果是远程排查建议配合 timeout 或者 screen 使用。2.3 -t 与 -w两个容易被忽略的增强参数-t 参数会在输出的最后多一行 Total把物理内存和 Swap 的 total、used、free 简单相加。这个值在评估整机“可用虚拟内存总量”时有点参考意义但别太当真因为物理内存和 Swap 本质上是不同层次的东西。我一般在写报告或者给人讲内存概况时用 -t 快速给个总数。-w 参数会切换宽模式把 buff/cache 拆成 buffers 和 cache 两列$ free -w -h total used free shared buffers cache available Mem: 30Gi 5.6Gi 1.2Gi 1.0Gi 100Mi 24Gi 24Gi Swap: 8.0Gi 0.0B 8.0Gi这种输出更接近老版本 free 或者 /proc/meminfo 的字段含义。buffers 主要是块设备读写时的缓冲区cache 更多是文件系统页缓存和可回收 slab。做深入排查时我习惯用 -w方便和 /proc/meminfo 里的 Buffers、Cached、SReclaimable 对应上。2.4 脚本里到底该用哪种格式之前有同事写监控脚本用 free -h 然后拿 awk 去取 used 字段结果有一天内存从 800M 涨到 2.1G单位从 M 变成了 G字符串解析直接错乱。free -h 的输出单位不是固定的同一个字段可能一会儿 Mi 一会儿 Gi脚本能不碰就别碰。稳妥的做法是取数时用 -m 或 -b单位固定再用 shell 的算术逻辑套阈值。示例total_mem$(free -m | awk /^Mem:/{print $2}) avail_mem$(free -m | awk /^Mem:/{print $7}) if [ $avail_mem -lt 512 ]; then echo available memory below 512Mi fi这里强调一下新版 procps-ng 的 free 命令 Mem 行第七列才是 available老版本没有这一列所以脚本里最好先确认工具版本。跨发行版跑脚本最稳的是读 /proc/meminfo 里的 MemAvailable避免被 free 版本差异坑到。3. buff/cache 到底是怎么回事能不能手动清3.1 page cache、buffer 与 reclaimable 内核内存buff/cache 不是一个简单概念。buffers 对应块设备缓冲主要是存储设备读写时临时放数据的页面cache 对应文件系统页缓存包括普通文件内容、目录项、inode 信息等可回收部分。这些缓存的存在是为了让读过的内容不再回去读磁盘内核用空闲内存来换 I/O 性能。从 /proc/meminfo 里可以看到更细的分类比如 Cached、SReclaimable、SUnreclaim、KernelStack 等。free -w 显示的 cache 大致对应 Cached 加 SReclaimableshared 对应 Shmembuffers 对应 Buffers。理解这个对应关系后你再去看 free 的输出就不是看热闹而是看门道。需要特别说明的是SUnreclaim 是“不可回收”的内核内存这部分不会自动释放如果它异常增大问题往往出在内核模块或驱动上不是普通进程能解决的。平时看 free -w 时cache 列包含的是可回收部分不用太慌。3.2 Linux 的“内存拿来不用才是浪费”哲学Windows 用户刚切到 Linux 时最容易不适应的一点就是“缓存占得太多了”。在 Linux 看来空闲物理内存如果放着不用等于浪费。既然应用暂时没申请内核就把这些页面拿来缓存磁盘数据提升文件读写速度。一旦应用真的申请内存缓存页可以马上被回收不会让业务等太久。这个设计决策不是 bug而是特性。很多人看见 free 的 used 很高就担心恰恰说明没有理解缓存的价值。真正需要警惕的不是 buff/cache 高而是 available 低。available 已经把可回收缓存算进去了它才体现“还能给新进程用多少”。内核也不是无脑缓存它有一套水位线机制空闲内存低于某个阈值时会主动回收尽量避免内存耗尽。3.3 手动清理缓存的正确姿势与风险网上有很多“清理 Linux 内存缓存”的帖子命令大概是sync echo 3 /proc/sys/vm/drop_cachessync 先强制把脏页写入磁盘然后写 drop_caches 让内核释放 page cache、dentries 和 inodes。这种方式偶尔用来测试缓存命中率或者模拟冷启动场景是合理的但我不建议当作常规运维手段。原因有两点第一清掉缓存后短期内所有文件访问都要重新读磁盘I/O 压力反而暴增第二Linux 内核自动回收比你手动清理更聪明它会根据回收成本决定先清哪些页。如果确实要清优先考虑 echo 1只清 page cache而不是 echo 3。echo 2 会清 dentries 和 inodes可能导致目录操作短暂变慢。生产环境里我只会在一台机器即将做基准测试、需要清空缓存变量时才执行这个操作。日常遇到 available 低应该去查进程而不是把缓存清掉假装问题消失了。注意执行 drop_caches 不需要重启服务但它不是日常维护命令。除非你明确知道自己在干什么否则不要把它写进定时任务。3.4 用 /proc/meminfo 对照 free 输出free 的实现本质上就是读取 /proc/meminfo 再加工展示所以你觉得 free 输出信息不够细时可以直接看原始文件cat /proc/meminfo里面能看到的字段比 free 多得多比如 MemTotal、MemFree、MemAvailable、Buffers、Cached、SwapTotal、SwapFree、Dirty、Writeback 等。Dirty 表示有多少脏页还没写回磁盘如果这个值长期很大说明磁盘 I/O 在拖后腿。Writeback 表示正在回写的数据量通常比较大时说明存储压力高。排查思路可以这样先 free -h 快速判断整体再 cat /proc/meminfo 看缓存内部细节。例如 available 很低但 Cached 很高说明可回收缓存可能已经被消耗得差不多如果 Dirty 涨得很快则重点查是哪个进程在频繁写文件。4. 用 free 命令开启内存问题排查4.1 先看 available 和 swap再决定要不要救火遇到服务器响应慢或者告警我习惯三步走先 free -h 看 available 是否够用再 free -h -s 1 连续刷三次看 Swap 会不会涨最后 dmesg -T | grep -i -E out of memory|oom 查有没有被杀进程。这个顺序能快速区分“内存真的不够”和“只是缓存很大”。如果 available 低而且 Swap 的 used 明显增长说明物理内存已经扛不住压力内核开始把冷内存页换到磁盘上。Swap 本身不是洪水猛兽但频繁的换入换出会让系统响应变得迟滞因为磁盘比内存慢好几个数量级。此时再去看哪个进程吃内存才有意义。4.2 结合 ps 定位进程级内存占用free 只给整体视角要查谁是“内存大户”得配合 ps。我常用的命令ps aux --sort-%mem | head -10或者用 top 之后按 ShiftM 按内存排序。top 里有个 RES常驻内存字段很关键它代表进程实际驻留在物理内存中的字节数VIRT 是虚拟内存数值可能非常大但虚的很多共享库和匿名的映射会被重复计算参考价值有限。排查内存问题时观察进程的 RES 变化比单看某个瞬间更有意义。比如一个 Java 进程 RES 缓慢上涨又不回落很可能是堆内存或本地缓存没有释放。这时候可以再用 jmap 或者 /proc/PID/smaps 进一步分析但第一步永远是从 free 的总览开始缩小范围。4.3 内存泄漏、Swap 抖动与 OOM 信号内存泄漏的典型特征进程 RES 持续上升free 的 available 持续下降重启进程后内存立刻松动。而 Swap 抖动是另一个信号可用 free -s 2 观察 Swap used 是否先升后降如果每次刷新都在变化说明内存压力导致内核反复换页系统会显得卡顿。当内存消耗突破内核容忍极限时Linux 的 OOM Killer 会被触发它会按评分杀掉进程。这时 dmesg 里会有 out of memory 字样以及被杀进程的 PID 和分数。free 在这时候的意义是确认“物理内存确实被耗尽”而不是某进程异常。配合 dmesg 看证据再决定是限制进程内存还是扩容这样才能避免误杀。4.4 在虚拟机、容器里 free 输出怎么解读虚拟机里的 free 输出通常就是宿主机分配给虚拟机的内存总量一般等于启动参数设定的值。但在容器里情况复杂一些。比如 Docker 默认共享宿主机内核容器内执行 free 看到的是宿主机全部内存不是容器限额。这在排障时特别容易迷惑容器内 available 明明很低但你的配额可能只有 2G宿主机却有 32G。要查容器真实内存限额应该看 cgroup 限制。比如 Docker 容器内部执行cat /sys/fs/cgroup/memory.max老版本可能是 /sys/fs/cgroup/memory/memory.limit_in_bytes。或者干脆在宿主机上 docker stats 看容器实时占用。理解这套机制后你就不会因为容器里 free 输出大而误判了。5. 常见误区与速查表5.1 误区一把 buff/cache 当成“已用内存”这是我见到最多的问题。很多监控系统直接取 used 字段做告警结果一台缓存密集型服务器长期“内存 99%”天天误报。实际上要告警应该用 available或者用 used 减掉 buff/cache 再算业务真实占用。如果监控指标里只有 used 没有 available一定要去找平台团队改指标定义否则会被狼来了耗尽精力。5.2 误区二在脚本里解析 free -h 的输出前面已经提到free -h 的单位会变化导致脚本解析不稳定。更隐蔽的问题是不同发行版 procps-ng 版本输出列名可能不同有的有 available有的没有。跨机器执行同样的 awk 命令可能拿到完全不一样的字段。脚本里的正则尽量要匹配行首关键字比如 /^Mem:/不要用行号这样即使多一列也能少踩坑。5.3 误区三随意 drop_caches 导致性能抖动很多网帖把 echo 3 /proc/sys/vm/drop_caches 说成“一键清理内存”但这个操作在生产环境里有明显副作用。清完 page cache 以后所有热门文件都要重新读盘数据库、静态资源服务在清缓存后的几十秒到几分钟内I/O 延迟可能明显上升。我见过有人为了“把内存释放出来”每天定时清理缓存结果业务响应反而更差了。正确做法是定位到底哪个进程消耗了内存而不是拿缓存开刀。5.4 速查表free 命令常见参数与场景对照场景推荐命令说明看一眼整体内存free -h自动切单位适合人看脚本取数free -m单位固定为 MiB方便数学计算持续观察变化free -h -s 33 秒刷新一次手动 CtrlC 结束定时抓取 N 次free -m -s 2 -c 5每 2 秒抓一次共 5 次后退出深挖缓存细节free -w -h拆开 buffers 和 cache统计内存Swap 总量free -t -h多一行 Total速查表之外还有一个经验free 命令的 -h 参数在比较老的 RHEL、CentOS 6 上可能不支持那就要用 free -m 代替。平时写自动化脚本可以提前探测版本或者直接用 /proc/meminfo 作为通用数据源。最后再分享一个小技巧。我现在排查内存问题时很少单敲一次 free 就下结论而是会用 free -h -s 1 -c 3 连续看三秒的数据。因为单次输出只能代表瞬间内存压力往往是波动的连续几轮对比下来available 是稳还是往下掉Swap 动不动很快就能看出趋势。这个方法帮我排掉过不少“假告警”。如果你每次遇到内存问题都习惯先 free -h那不妨记住能判断缓存、能看 available、会结合进程定位free 这个看起来最简单的命令其实能顶半个内存监控系统。
返回列表