尧图精选

Linux df命令详解:从磁盘空间查看到inode监控与脚本告警

🕒 发布时间:2026/10/24 0:59:44 📁 来源:尧图网络
1. 项目概述与命令定位1.1 为什么运维和开发都绕不开df命令Linux下查看磁盘空间我第一个想到的命令永远是df。无论是在线处理服务器告警、排查数据库写入失败还是给客户做季度巡检df都是冲在最前面的那个工具。它全称disk free作用就一句话——报告文件系统上还有多少可用空间、已经用了多少、挂载在哪里。命令行打一个df所有挂载点的容量情况一目了然。有些同学习惯用ls -lh或者进目录里du -sh一个个看不是说不行而是效率完全不在一个量级。df站在文件系统层面一次扫完所有挂载点du钻进具体目录里一层一层数文件。两者的定位完全不同。我用一个生活化的类比解释df是仓库门口的盘点表告诉你整个仓库还剩多少货架空位du是货架管理员告诉你某一个货架上具体堆了多少货物。日常排查问题时通常先用df确认大方向再配合du定位具体目录。这篇文章适合三类人看刚入行、还在背命令的运维新手需要经常登录服务器看磁盘情况的开发人员以及做系统交付、给客户出巡检报告的实施工程师。文章不整那些花架子全部围绕真实场景展开看完你不仅能熟练使用df还能明白每个输出字段背后的含义遇到磁盘异常的时候知道怎么着手查。1.2 df命令到底能解决什么问题先从需求角度梳理一下df命令在真实工作中的价值主要体现在五个方面。第一是日常巡检。登录服务器最开始看的往往就是磁盘df -h敲一下几秒钟就知道所有分区的水位。第二是故障排查。服务突然写不进日志、数据库报no space left on device不用猜df一查就知道是不是磁盘满了。第三是容量规划。做备份方案或者扩容前需要知道当前磁盘消耗速度和剩余空间df的Used和Avail列就是最直接的参考。第四是inode监控。很多新手不知道磁盘空间有剩余但文件创建失败极有可能是inode耗尽了df -i能立刻看出来。第五是文件系统类型确认。新接手的服务器不知道某个挂载点是ext4还是xfs还是nfsdf -T直接告诉你。这些场景不是孤立出现的往往叠加在一起。举个例子晚上收到告警说某个服务不可用登上去先df -hT看空间再df -i看inode两个输出对比基本能锁定问题是容量还是文件系统层面。这也是我为什么会把df归为高频三板斧命令之一——它上手门槛低信息密度大出错率小。2. 常用参数详解与应用场景2.1 先把最常用的几个参数吃透df命令本身不带参数的时候输出以512字节块为单位显示信息虽然完整但对人不友好。相信我没有人愿意在脑子里把31457280换算成15GB。所以实际使用中参数几乎总是和df一起出现。我按使用频率从高到低把核心参数逐个讲清楚。-h参数人类可读模式。这个参数把原始块数自动换算成K、M、G单位是日常使用频率最高的。df -h输出的Size列直接显示20G、Used列显示8.5G一眼就能看出水位。贴一下实际输出$ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 20G 8.5G 11G 46% / tmpfs 7.8G 0 7.8G 0% /dev/shm /dev/sdb1 493G 231G 262G 47% /data-T参数显示文件系统类型。新手容易忽略这个参数但它对你了解服务器非常关键。加上-T后输出会多一列Type清楚地告诉你每个挂载点是ext4、xfs、vfat还是nfs。为什么重要因为不同文件系统有不同特性比如ext4有保留块机制、xfs在某些场景下对删除大文件更友好、NFS网络挂载有IO延迟问题。后续做调优或排查时知道类型才能选对方向。-i参数查看inode使用情况。这是整个df命令里最容易被忽视却最能救命的一个参数。它的原理是换个视角看文件系统——df默认统计的是数据块的使用量加上-i后统计的是inode节点的使用情况。每个文件不管大小都要占用一个inode所以文件数量极大时即使磁盘空间还很充裕inode也可能先耗尽。$ df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda1 1310720 310521 1000199 24% / /dev/sdb1 32768000 1024 32766976 1% /data-l参数只看本地文件系统。如果不加这个参数df默认连网络挂载点比如NFS、CIFS一起显示。在某些内网环境里NFS挂载响应慢df会卡在那里等网络超时。加上-l只显示本机物理磁盘能避免这种阻塞。这个坑我在后面排查部分会展开讲。-P参数强制POSIX输出格式。df默认输出中如果挂载点路径特别长会对齐做换行处理这在脚本解析时是灾难。加上-P后每个挂载点严格一行输出所有列的位置固定配合awk解析就非常舒服。写自动化脚本时我几乎总是用df -P而不是裸df。-x参数排除指定文件系统类型。比如临时目录tmpfs、共享内存shm这些经常变化又不重要的挂载点可以用df -x tmpfs过滤掉让自己只关注真正的磁盘分区。和-t配合使用效果更好-t指定只看某种类型-x指定不看某种类型。我常用的组合是df -hT -x tmpfs -x devtmpfs这样输出干净利落全是业务相关的分区。2.2 参数背后那些容易被忽视的细节很多人用df只记住了参数字母不知道参数背后的计算逻辑导致面对输出时产生疑问。先说块大小的问题。df自身的统计单位默认是1024字节块但不同的Unix实现有差异部分系统默认是512字节块。这也是为什么裸敲df看到的数字都特别大。加-h只是让df自动选取合适的单位做换算实际底层统计并没有变。了解这一点你就明白为什么df -k强制以KB显示和df -m强制以MB显示在某些脚本里是必不可少的因为-h的输出单位不固定脚本没法统一解析。再说Avail列为什么不等于Size减去Used。你可能会发现某个分区Size是20GUsed是8.5GSize减Used等于11.5G但Avail列显示的只有11G少了0.5G。这不是df算错了而是ext4文件系统默认会留5%的块给root用户专用防止普通用户把磁盘彻底写满导致系统无法写入关键日志。也就是说Avail列统计的是普通用户实际可用的空间root用户可用的空间其实还能再多一点。生产环境的根分区这个保留机制非常有用关键时刻能救命。但如果是数据盘5%的保留空间就比较浪费很多公司会在格式化时用mkfs.ext4 -m 0把保留比例调成0这些知识配合df输出理解才会真正深入人心。df命令还有一个隐藏知识点它显示的是文件系统的统计不是目录的统计。同样的空间挂载在不同位置df从不同目录看过去结果完全不一样。比如df -h /和df -h /data如果/data是独立分区两者输出就是两个完全不同的文件系统如果/data只是根分区下的一个目录那么两者指向同一个文件系统输出几乎相同。3. 实操输出逐一拆解3.1 一次完整的df -hT输出分析实战环境里我最常用的命令是df -hT一次拿到容量、文件系统类型、挂载点三组信息。下面是一台真实业务服务器的输出$ df -hT Filesystem Type Size Used Avail Use% Mounted on /dev/vda1 ext4 99G 71G 23G 76% / devtmpfs devtmpfs 7.8G 0 7.8G 0% /dev tmpfs tmpfs 7.8G 4.0K 7.8G 1% /dev/shm tmpfs tmpfs 7.8G 1.5M 7.8G 1% /run tmpfs tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup /dev/vdb1 xfs 493G 200G 293G 41% /data一行一行看。第一列Filesystem是设备文件路径/dev/vda1对应根分区/dev/vdb1对应数据盘。第二列Type区分文件系统类型console的系统盘是ext4数据盘是xfs。第三到第六列是总容量、已用、可用、使用率最后一列Mounted on是挂载点。tempfs和devtmpfs是内存文件系统它们的数据真实是放在内存里的所以Size显示为物理内存大小关机即清空。看到这些挂载点Used特别小不用紧张这是正常的。这个输出里真正值得关注的是根分区76%的使用率。经验来看根分区超过85%就要开始考虑清理或扩容了因为根分区承担着系统日志、临时文件、应用写入等职责写满后整个系统行为会变得非常奇怪。3.2 如何通过df快速识别资源分布形态df不只能告诉你还剩多少空间配合文件系统类型它能帮你快速判断一台服务器的资源布局。举个实际例子我接手过一台测试环境服务器df -hT的输出让我第一眼就看出问题在哪里$ df -hT Filesystem Type Size Used Avail Use% Mounted on /dev/sda1 ext4 50G 49G 1.0G 98% / /dev/sdb1 ext4 500G 10G 490G 2% /data根分区98%快满了而数据盘只用了2%。一看就知道这台机器的业务数据全堆在了根分区里数据盘完全闲置。登录进去查果然发现MySQL的数据目录、NFS挂载缓存全部配置在默认路径下压根没往/data放。这种问题如果你只进目录里du可能要查半天但df一眼就让资源分布失衡的问题暴露出来。另一种常见形态是根分区不大但占用正常数据盘很大且水位高说明数据落盘规划到了独立分区这是相对健康的架构。还有一种是大量tmpfs挂载点出现且Used很高这通常意味着有应用把临时文件写到了/dev/shm里重启后文件会消失但运行期间可能把内存撑爆。df在高内存消耗的服务器上能帮你发现这类隐性风险。3.3 通过df判断文件系统空间的计算口径关于df -h输出里Size、Used、Avail三列的关系我在培训时经常遇到疑惑这里展开讲透。文件系统内部管理空间时会划分出数据块、inode表、超级块等元数据区域。数据块负责存文件内容inode负责存文件属性超级块存全局信息。df展示的是数据块的分配情况不统计元数据自身占用的空间。因此你在文件系统里创建再多的空文件df -h的Used列可能只涨一点点但df -i的IUsed会明显增加——这就是两个参数要配合看的本质原因。另外还要理解1K块的概念。ext4文件系统的块大小通常为4KB这是数据读写的原子单位。一个小到只有1字节的文件在磁盘上也占据一个4KB的块。df统计时按块计算所以大量小文件会让Used显得虚高。反过来想如果一个分区里塞满了小文件删除它们之后df的Used下降幅度可能远小于文件总大小因为释放的是块资源。这也是为什么很多公司在跑大量小文件的业务时需要专门评估inode和块大小的配置。关于Avail列还有一个隐藏细节是配额的影响。如果文件系统启用了quota用户配额机制df显示的是整个文件系统的总量而用户实际能写入的空间受配额限制。曾经有同事说df显示还有200G怎么一写文件就报错查了半天最后发现是用户配额限制在了100G。如果你管理的服务器有多个团队共用目录遇到这种矛盾情况记得查一下quota。4. 常见问题排查与处理实录4.1 df显示磁盘已满但文件总和却对不上这是运维领域一个经典老坑。现象是df -h显示Use%已经100%但你进到目录里用du -sh把所有内容加起来发现远小于分区总容量。明明文件不多磁盘却满了问题出在哪最典型的原因是文件被删除了但仍有进程持有它的文件句柄。Linux下一个文件被进程打开后即使你rm把它从目录中摘除只要进程不释放句柄占用的磁盘空间就不会真正释放。df统计的是文件系统实际分配的块所以它会一直显示空间被占用。实际动手排查# 先确认哪些进程打开了已删除文件 $ lsof | grep deleted java 1234 app 45u REG 8,1 5013454848 /opt/logs/app.log (deleted)看到这行就明白了一个5GB的日志文件虽然被rm了但java进程还握着句柄空间不放。解决方式也不难重启该进程让句柄释放或者用 /proc/1234/fd/45这种方式强制清空句柄指向的文件内容。用后者不用重启但注意需要确认fd编号。遇到这种情况df和du的结果会长期不一致很容易让人误判。这是df必须和lsof搭配使用的一个代表性场景。还有一种情况是保留块在作祟。ext4文件系统默认预留5%空间给root普通用户看到的Avail是扣除保留块后的值root用户反而还能写入。如果你用普通用户写入报错但df显示还有一点空间先看看是不是保留块机制导致的边界情况。4.2 df结果与进程行为矛盾空间够却写不进去还有一种让人头疼的现象df显示Avail有几十G但应用写文件就是失败报Disk quota exceeded或No space left on device。这种矛盾的排查顺序我有固定套路。第一步排除配额限制上文提过quota用户限制可能远小于文件系统总量。第二步看是否有软链接把路径重定向到了别的分区比如你以为写/data实际/data/log是一个软链接指向了/opt/log而/opt所在分区早就满了。第三步检查文件描述符上限有些写入错误不是磁盘问题而是进程的fd耗尽。第四步用dmesg查内核日志看看有没有IO错误或文件系统只读切换的痕迹。我实际遇到过一个隐蔽案例某台服务器df显示一切正常但应用频繁报磁盘写入失败。查到最后发现是/etc/fstab里挂载参数用了noatime和datawriteback的组合没问题真正的原因是那块盘属于云厂商的共享盘底层IO被邻居干扰导致长时间卡顿应用写超时。df只反映空间分配不反映IO健康度这个特性决定了它不能作为唯一磁盘健康指标。配合iostat和dmesg一起看才能定位这类空间没问题但行为异常的情况。4.3 inode耗尽导致无法创建文件另一个高频经典问题是inode耗尽。现象是df -h显示空间还有几百G但touch一个新文件都报错No space left on device。如果你不知道inode这个概念会在这里卡很久。原理方面前面已经讲过inode是文件系统的门牌号每个文件必占一个。小文件数量极大的目录比如邮件队列、消息缓存、临时文件堆积目录最容易把inode吃光。排查命令$ df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/vda1 655360 655360 0 100% /IUse%显示100%确定是inode耗尽了。接下来就是找谁生的这么多文件。先用一个大范围扫描看看情况# 统计挂载点下各个目录的文件数量找到最夸张的目录 $ for d in / /var /var/spool /tmp /opt; do echo $d find $d -xdev -type f 2/dev/null | wc -l done定位到文件数量巨大的目录后一般是清掉无用的缓存文件或者归档旧数据。经历过一次邮件服务器inode打满之后我现在每台机器都会在监控系统里同时配空间和inode两个指标单独盯一个就可能在黎明前翻车。4.4 df命令本身卡住不返回结果还有一种情况是df命令敲下去命令行直接hang住几分钟不输出。绝大多数情况是网络挂载点的问题——NFS/CIFS服务端无响应df在尝试连接时被阻塞。在纯内网环境里非常常见。碰到这种场景我一般直接df -l只看本地文件系统命令就立刻回来了。如果需要具体确认是哪个挂载点出了问题可以用time df -h挨个看或者检查/etc/mtab里有没有网络挂载。长期管理的服务器我会在写脚本时统一加上df -l的写法宁可少看几个远程挂载也不让脚本被一个失联的NFS拖死。关于df卡住还有一个冷门原因文件系统本身进入异常状态。比如ext4在断电后以只读方式挂载df确实能显示但如果有损坏的元数据df在统计过程中也可能异常变慢。这时候dmesg里通常会有明确的内核报错优先看日志会比反复执行df更有效。4.5 df综合排障速查表现象可能原因排查方向磁盘显示100%但du文件总和小已删除文件被进程占用lsof grep deleted空间剩很多但无法写文件inode耗尽df -i确认IUse%空间剩很多但写入报权限错误配额限制quota查询/repquotadf命令卡住长时间无输出网络挂载失联df -l排除远程挂载Use%很高但Avail不为0接近保留块阈值确认ext4保留块机制df -h和df -i呈现完全相反的紧张度大文件或小文件扎堆du find定位文件分布目录写入慢但df显示正常IO层异常iostat dmesg这张表是我自己排查时逐渐攒出来的覆盖了最常见的7类诡异场景。遇到磁盘相关问题先套这张表定位方向绝大多数问题在五分钟内能有眉目。5. 脚本化运用与监控实践5.1 用df命令构建磁盘水位告警手动敲df只能看到当下状态真正要防患于未然得把它做成定时巡检脚本。这是我运维多年沉淀下来的一个基础版磁盘告警脚本框架简单但实用#!/bin/bash # 磁盘空间监控脚本超过阈值触发告警 THRESHOLD85 ADMIN_EMAILopsexample.com df -P | awk -v threshold$THRESHOLD NR1 { # 过滤掉虚拟文件系统只关注真实磁盘 if ($1 ~ /^\/dev\//) { usage$5 # 去掉%号转成数字比较 gsub(/%/, , usage) if (usage threshold) { printf 磁盘告警: %s 挂载点 %s 使用率 %s%%\n, $1, $6, $5 } } } /tmp/disk_alert.txt # 如果告警文件非空发送邮件通知 if [ -s /tmp/disk_alert.txt ]; then mail -s [Alert] Disk Usage High on $(hostname) $ADMIN_EMAIL /tmp/disk_alert.txt fi这段脚本的核心逻辑都在awk里。用df -P保证一行一个文件系统awk按列解析$5列就是使用率。gsub把百分号去掉后比较数字大小大于阈值就输出告警信息。做了一点过滤只关注真实设备文件避免tmpfs、devtmpfs这些内存文件系统误报。实际生产环境我会把阈值分级空间使用率超过80%给普通通知超过90%提高告警等级超过95%直接电话告警。因为不同服务器角色对磁盘水位容忍度完全不同——缓存节点可能长期保持90%以上依然运行正常而数据库服务器到85%就要开始处理。阈值设计不能一刀切。5.2 df与du配合完整定位大文件目录df定位了哪个分区紧张下一步就要用du定位哪个目录在吃空间。这是排查磁盘问题的标准组合拳。我不推荐直接在根分区上跑du -sh /因为全盘扫描会非常慢正确做法是分层下钻。经验做法是先看根目录下各个一级目录的开销# 在根分区目录下看各一级目录的占用 $ du -h --max-depth1 -x / 2/dev/null | sort -hr | head -20 1.2G /log 8.6G /opt 5.2G /var ...注意这里的-x参数它让du不要跨越文件系统边界避免把其他挂载点的空间也统计进来。sort按人类可读的数字排序head取前20行。看到最大的目录后再往里下钻一层。$ du -h --max-depth1 -x /opt 2/dev/null | sort -hr | head -10 5.4G /opt/app 2.1G /opt/backup ...这样一层层下去配合df给出的分区紧张程度很快就能定位到罪魁祸首。就算遇到海量小文件场景也能用for循环配合find统计文件数快速判断是不是inode问题。在生产服务器上执行大规模du扫描时IO开销是真实存在的高峰期可能拖慢业务。我的经验是优先在业务低谷做深度扫描。如果紧急情况必须立刻查可以考虑ionice给du降IO优先级# 降低IO优先级扫描 $ ionice -c 3 du -h --max-depth1 -x / 2/dev/null | sort -hr | head -205.3 用crontab把df巡检固化下来告警脚本写好了剩下就是定时执行。我通常放在crontab里服务器时间凌晨两点左右跑一次因为凌晨业务流量低IO争抢少df和du的结果也更接近真实状态。# crontab -e 添加如下配置 # 每天凌晨2点执行磁盘巡检 0 2 * * * /opt/scripts/disk_check.sh /dev/null 21这里有两个细节值得提醒。第一是脚本路径务必使用绝对路径crontab环境里PATH变量继承不完整直接用相对路径非常容易踩坑。第二是告警脚本自身要预留磁盘空间否则磁盘满时脚本写不了日志反而误事。稳妥做法是把脚本日志放在根分区而非数据盘因为根分区即使紧张也不太会瞬间写满。巡检频率方面普通服务器每天一次足够核心数据库或大数据节点建议每小时一次。我自己管理的MySQL集群用的是一个带lock文件的脚本如果上一次巡检还没跑完就跳过避免多个实例同时跑db操作。磁盘巡检也一样df脚本本身执行很快但里面嵌套的du深度扫描可能耗时较长一定要防止crontab时间重叠导致并发扫描。5.4 与监控系统对接的df采集技巧有些公司会自建监控平台需要定期采集磁盘指标。这时候采集脚本的输出格式很关键。推荐用下面这种key-value格式方便监控端解析$ df -P | awk NR1 $1 ~ /^\/dev\// {print disk_usage_percent{$6} $5} disk_usage_percent{/} 76% disk_usage_percent{/data} 41%监控系统拿到这些数据后可以做趋势分析。比如观察根分区使用率是不是每周稳定上涨推算大概多久会触达预警线提前安排扩容计划。这比单纯看今天的数字有意义得多因为磁盘增长通常不是突发的而是积累的。我自己在预测磁盘用满时间时会在脚本里多采集几天的数据然后取日均增长率来估算。比如今天使用率76%一周前是70%日均增长不到1%那么按照这个斜率还有两周左右到85%预警线。这类经验配合df的历史数据能让你在磁盘写满事故发生前就从容处理。6. 最后的实战心得做了一个小总结也是我踩过几次坑之后的真实感受。用df命令这些年最大的体会是这个命令看似简单但真正用得好的关键是理解文件系统的分层逻辑。你看到了Filesystem列和Mounted on列但其实每个挂载点后面都站着块分配、inode、保留空间、配额这些底层的机制。参数只是开关真正的功力在于能把输出和实际问题对得上号——看到高的Use%能立刻想到是有大文件堆积还是删了没释放看到异常的Avail能想到是不是保留空间卡住了边界看到命令hang住能想到是网络挂载在拖后腿。如果你刚接触这些建议从今天开始把df -hT变成肌肉记忆然后在每台机器上养成同时看df -i的习惯。等你的脚本里开始出现df的告警逻辑你其实就是个有实战经验的运维人了。最后分享一个小技巧每次处理完磁盘问题我都会把当时的df输出截图保存下来跟故障记录放一起。下次再遇到类似症状直接翻历史截图对比能省下大量排查时间。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →