明明 df -h 显示还有几十 GB 空间, 创建一个小小的 txt 文件却被系统怒怼一句:
“No space left on device.”
真正让磁盘“满了”的,根本不是你以为的空间不足,而是一个比 Blocks 更容易被忽略、却致命得多的资源:Inodes。
它是 Linux 中最容易被忽略的性能黑洞,也是无数线上事故的罪魁祸首。
一旦 Inode 用尽——别说大文件,小到 0 字节的新文件都无法创建,监控不报警、磁盘不报红、系统表面一切正常,却已濒临“窒息”。
这篇文章带你做一场完整的“文件系统刑侦剧”:从 复现事故 → 定位真凶 → 现场取证 → 高效清理,最后再给出一套资深运维日常都在用的 Inode 风险防御体系。
看完这篇,你将彻底弄懂: 为什么磁盘还有空间,却依旧“不够用”。
01
开端——“看不见的墙”
想象一下这个场景:您登录到一台 Linux 服务器,准备创建一个临时文件,却遭到了系统的无情拒绝。
[root@anyadb1 ~]# touch /tmp/a_new_file.txttouch: cannot touch '/tmp/a_new_file.txt': No space left on device“空间不足?” 您感到困惑,立刻执行了最直观的检查命令 df -h。
[root@anyadb1 ~]# df -hFilesystem Size Used Avail Use% Mounted on/dev/mapper/klas-root 45G 21G 25G 46% /devtmpfs 4.0M 0 4.0M 0% /devtmpfs 1.7G 0 1.7G 0% /dev/shmtmpfs 4.0M 0 4.0M 0% /sys/fs/cgrouptmpfs 670M 13M 658M 2% /runtmpfs 1.7G 8.0K 1.7G 1% /tmp/dev/sda2 960M 375M 586M 40% /boottmpfs 335M 24K 335M 1% /run/user/0/dev/sr0 4.3G 4.3G 0 100% /run/media/root/Kylin-Server-11结果令人费解
/tmp明明还有 1.7GB 的可用空间,使用率仅为 1%。
这究竟是怎么回事?
我们遇到的,正是一场典型的 Inode 耗尽危机。
02
揭开谜底——磁盘存储的
两个“账户”
要理解这个谜题,我们必须知道 Linux 文件系统如何管理磁盘。
您可以把它想象成一个巨大的图书馆:
数据块 (Data Blocks)
对应图书馆里一排排的书架。
它们是磁盘上用于存储文件实际内容的物理单元。
书架的总容量,就是我们用 df -h 看到的、以 GB 或 TB 为单位的磁盘空间。
索引节点 (Inodes)
对应图书馆前台的图书索引卡。
每一个文件或目录,无论大小,都必须占用一个 Inode。
这张“索引卡”存储了文件的元数据:权限、所有者、大小、时间戳,以及最重要的——指向存储文件内容的“书架”(数据块)的指针。
关键点
在格式化文件系统时,系统会预先分配固定数量的 Inode。
就像图书馆的索引卡柜容量是有限的一样,磁盘上的 Inode 总数也是有限的。
因此,提示“磁盘空间不足”有两种可能:
数据块耗尽您存储的大文件太多,把所有“书架”都占满了。
Inode 耗尽您存储的文件数量太多,把所有“索引卡”都用完了。
即使这些文件都是 0 字节的空文件,它们也必须每人一张索引卡。
03
实战演练——亲手制造一场
Inode 危机
理论千遍,不如实战一次。
让我们基于一个健康的 Kylin V11 (XFS) 系统环境,亲手制造这场危机。
**警告:**以下操作将在您的系统上创建大量文件。请确保您在实验环境或非生产系统上执行,并在实验结束后按照指导进行清理。
步骤 1: 分析“战场”并选择“作案”地点
我们的目标是在根分区 /tmp 上耗尽 Inode。
# 查看当前 Inode 情况[root@anyadb1 ~]# df -i /tmpFilesystem Inodes IUsed IFree IUse% Mounted ontmpfs 1048576 4488 1044088 1% /tmp可见,我们有大约 1044088个空闲 Inode 可供“挥霍”。
为了便于管理,我们选择在 /tmp 下创建一个目录。
mkdir -p /tmp/inode_bomb_dircd /tmp/inode_bomb_dir步骤 2: 高效并行制造“Inode 炸弹”
单进程的 for 循环太慢了。
我们将利用 xargs 的并行处理能力,极速创建数百万个空文件。
# 使用 xargs 的并行能力来创建 500 万个文件# -P 0 告诉 xargs 尽可能多地启动并行进程(通常等于 CPU 核心数)echo "Starting to create 5,000,000 small files in parallel. This will be fast..."time seq 1 5000000 | xargs -P 0 -n 100 touchecho "File creation finished."命令剖析
seq 1 5000000快速生成从 1 到 5,000,000 的数字序列。
xargs -P 0并行处理的关键! 0 告诉 xargs 启动与 CPU 核心数相等的进程数来并行工作。
-n 100这是一个性能优化选项,告诉 xargs 每次“打包”100 个数字传递给一个 touch 命令。
步骤 3: 见证“危机”降临
在脚本运行时,您可以打开另一个终端,用 watch df -i 实时监控 Inode 的消耗。
当 Inode 接近耗尽时,touch 命令会开始报错。此时,我们来交叉验证:
[root@anyadb1 inode_bomb_dir]# touch another_file.txttouch: cannot touch 'another_file.txt': No space left on device[root@anyadb1 ~]# df -h /tmp/Filesystem Size Used Avail Use% Mounted ontmpfs 1.7G 8.0K 1.7G 1% /tmp[root@anyadb1 inode_bomb_dir]# df -i /Filesystem Inodes IUsed IFree IUse% Mounted ontmpfs 1048576 1048576 0 100% /tmp故障现象完美复现
磁盘块空间 (df -h) 依然充裕,但 Inode 空间 (df -i) 已经 100% 耗尽!
谜案的现场已经被我们成功构建。
04
诊断与定位——成为
“文件系统侦探”
现在,我们扮演一个对系统现状一无所知的管理员,来排查这个问题。
接到报告与初步诊断
用户报告无法创建文件,df -h 显示空间正常。
深度诊断
df -i 显示 / 分区的 Inode 使用率达到 100%。
确认问题为 Inode 耗尽。
定位“元凶”目录
我们需要找出哪个目录下藏有海量文件。
方法一:find + dirname + sort 组合 (最直观)这个方法的核心是使用 dirname 命令来获取每个文件所在的目录路径,然后对这些目录路径进行统计。find /tmp -xdev -type f -print0 | xargs -0 -n 1 dirname | sort | uniq -c | sort -nr | head -10方法二:纯 find + awk 脚本 (更高性能)对于海量文件(千万级以上),反复调用 dirname 可能会有性能开销。我们可以使用 awk 来更高效地处理路径字符串,避免启动大量外部进程。find /tmp -xdev -type f -print | awk -F/ '{ # 移除最后一个字段(文件名),剩下的就是目录 $NF=""; # 使用 OFS(默认为空格)重新构建路径,然后打印 print $0}' | sort | uniq -c | sort -nr | head -10预期输出
505913 tmp inode_bomb_dir 21 tmp 1 tmp xargs_test输出清晰地指向了 /tmp 目录。
通过逐层深入,我们最终会锁定罪魁祸首:/tmp/inode_bomb_dir。
注意
当 sort 命令处理大量输入数据时(比如 find 命令找到的数百万个文件名),它无法将所有数据都加载到内存中进行排序。
它会在磁盘上的/tmp目录创建一个或多个临时文件,所有查询前需要删除一部分数据释放inode
# 只需要删除几个文件即可rm /tmp/inode_bomb_dir/1rm /tmp/inode_bomb_dir/205
解决危机——高效清理海量文件
我们已经定位到问题目录,现在需要安全、高效地删除这些文件以释放 Inode。
错误且极度危险的方法
# 千万不要这样做! "Argument list too long" 错误会立即出现[root@anyadb1 inode_bomb_dir]# rm -f /tmp/inode_bomb_dir/*-bash: /usr/bin/rm: Argument list too long正确、高效且安全的方法
方法 A: 使用 find -exec + (简洁高效,强烈推荐)
这是最直接、最安全的选择,因为它既能处理海量文件,又能避免特殊文件名带来的问题。
echo "Deleting files using 'find -exec +'..."time find /tmp/inode_bomb_dir -type f -exec rm -f {} +echo "Deletion complete."工作原理find 会将找到的大量文件名打包,一次性传递给一个 rm -f 命令。
它只会启动极少数的 rm 进程,性能极高。
方法 B: 使用 xargs (可并行,专家之选)
如果您的服务器是多核 CPU,并且 I/O 性能足够好,可以使用 xargs 的并行功能来进一步加速。
echo "Deleting files in parallel using 'xargs'..."# -P 0 表示使用所有可用的 CPU 核心并行删除time find /tmp/inode_bomb_dir -type f -print0 | xargs -0 -P 0 rm -fecho "Deletion complete."real 0m4.347suser 0m1.053ssys 0m11.179s工作原理find -print0 安全地输出文件名,xargs -0 安全地接收它们,并通过 -P 0 将删除任务分配给多个并行的 rm 进程,最大化利用系统资源。
06
危机解除与预防
删除操作完成后,我们再次验证。
[root@anyadb1 ~]# df -i /tmp/Filesystem Inodes IUsed IFree IUse% Mounted ontmpfs 1048576 68 1048508 1% /tmpInode 使用率已恢复正常,系统功能恢复。
预防措施
主动监控将 df -i 加入您的日常系统监控脚本中,设置阈值(如 80%)进行预警。
日志轮转对应用程序日志配置 logrotate 工具,定期归档、压缩和删除旧日志。
优化应用与开发人员沟通,避免应用程序设计产生海量小文件。
07
结论
通过这次从制造故障到解决故障的全过程实战,我们不仅深刻理解了 Inode 与数据块的区别,更重要的是,我们掌握了一套在真实生产环境中应对此类“疑难杂症”的标准化流程:df -h/df -i 对比诊断 -> find/cut/sort 组合定位 -> find -exec + 或 xargs 高效解决。
这套组合拳,是每一位高级 Linux 系统管理员都应熟练掌握的核心技能。
下一次当您再遇到这堵“看不见的墙”时,您将不再束手无策,而是一位能够从容应对的“文件系统侦探”。
写在最后
如果你还想系统性地提升自己的 Shell 自动化编程能力,推荐看看刘峰老师的 Linux 系列课程。
课程内容循序渐进,从基础的 if/for/while 循环,到 sed、awk 等文本处理利器,再到编写生产级的自动化运维脚本,能够帮助你一步到位,构建起完整的 Shell 自动化知识体系,真正实现“让机器为你工作”。
原文:https://mp.weixin.qq.com/s/Ra2rPjhjOtRfUwXXKFzVVA
转载请注明来自海坡下载,本文标题:《n卡无法游戏优化(Linux磁盘惊魂夜明明还有几十 GB)》
京公网安备11000000000001号
京ICP备11000001号
还没有评论,来说两句吧...