ChatGPT、Codex排查实录:磁盘明明还有40%空间,为什么服务却突然报“No space left on device”?
📅 2026/10/5 10:18:32✍️ 爱科研究院👁 阅读 3,247
线上服务突然开始报错。不是CPU打满。不是内存爆了。也不是数据库挂了。日志里反复出现一句No space left on device第一反应当然是磁盘满了结果你马上执行df -h却发现最主要的磁盘分区只用了60%左右。明明还剩40%空间甚至还有几十GB可用。这时候就很容易怀疑监控是不是错了系统是不是抽风了容器是不是误报如果这时直接让 ChatGPT、Codex“帮我清理一下磁盘。”很可能一上来就查错方向。因为Linux里的“No space left on device”并不一定只代表磁盘容量真的100%用满。真正需要先搞清楚的是系统到底缺的是磁盘Block、inode、可写挂载空间还是被某个进程占着没有真正释放。一、先给核心判断磁盘空间还有不代表“还能创建文件”Linux文件系统真正能不能继续写不只取决于还有多少GB。还取决于inode是否耗尽当前目录所在挂载点是否已满删除文件是否仍被进程占用容器自己的Overlay空间是否已满临时目录或日志目录是不是单独分区文件系统是否进入异常状态。所以看到No space left on device第一件事不是继续盯着df -h。而是要回答到底是“容量没了”还是“文件系统资源没了”二、第一种高频情况inode已经用完了这是最经典的一类。文件系统除了存储数据块还要为每一个文件维护inode。inode可以理解成文件的元数据入口。比如权限。所有者。时间。数据块位置。如果一个磁盘里出现海量小文件就可能出现一种很反直觉的情况磁盘容量还剩很多但inode已经100%用完。比如日志目录里每天生成几十万个小文件。缓存目录不断创建临时文件。某个程序每个请求都写一个独立文件。结果磁盘用了60%。但inode已经100%。这时候系统再创建新文件就可能直接报No space left on device哪怕还有几十GB容量。三、最快先看df -i遇到这种问题我通常会在df -h之后马上执行df -i重点看IUse%如果某个挂载点已经100%那基本就已经找对方向了。例如Filesystem Inodes IUsed IFree IUse% /dev/sda1 6553600 6553598 2 100%这时候真正缺的不是GB。而是inode。所以清理策略也不能只找“大文件”。你真正应该找的是哪个目录里有海量小文件。四、为什么“找大文件”有时候完全没用很多人的清理习惯是找几个10GB日志 删掉这种方法解决的是Block空间。但inode耗尽时真正的问题可能是某个目录下面有300万个2KB文件。总容量不大。但每个文件都要占一个inode。于是你可能删掉一个10GB文件磁盘多出10GB。结果No space left on device仍然存在。因为inode一个都没释放多少。所以如果df -i已经接近100%排查重点应该从“谁占空间最大”切到“谁的文件数量最多”。五、第二种高频情况文件已经删了但空间没有真正释放这个场景也特别容易让人懵。你发现一个日志文件占了20GB。直接rm app.log然后再看df -h结果空间几乎没变。很多人会以为Linux没删成功。其实很可能是文件目录项删了但进程仍然持有这个文件描述符。比如Java进程还在持续写app.log你把文件名删了。文件在目录里已经看不到。但只要进程还握着fd对应的数据块就不会真正释放。于是会出现文件没了。du也找不到。但df空间还是被占着。六、这种deleted-but-open文件怎么查一个非常实用的办法就是lsof L1或者查包含(deleted)的文件。如果看到类似java 12345 app 6w REG ... 20G /logs/app.log (deleted)那就很明显了。文件虽然被删了但Java进程还在占。真正释放空间通常需要正确让程序重新打开日志文件。重载日志。或者在可控情况下重启对应进程。这也是为什么“删文件”不等于“空间已经释放”。七、第三种情况你看的不是出问题的那个挂载点这也是线上特别常见的误判。你执行df -h看到/还有40%。于是觉得磁盘肯定没满。但真正报错的目录可能是/var/log/tmp/data/var/lib/docker这些路径可能挂载在完全不同的文件系统上。比如根分区还有40%。但/var/log单独挂载的分区已经100%。应用写日志时一样会报No space left on device所以不能只看“机器总磁盘还剩多少”。要看报错目录实际属于哪个Filesystem。八、最快的方法先确定报错路径属于哪个挂载点比如报错发生在/data/upload/tmp那就直接围绕这个路径检查。不要泛泛地看整个机器。你真正要确认的是这个目录所在Filesystem的容量。inode。挂载参数。状态。否则很容易出现你一直清理/但真正满的是/data这种低效排查。九、第四种情况容器宿主机有空间但容器自己的写层满了Docker、Kubernetes场景里这个问题更容易出现。你看宿主机磁盘还有很多空间。但容器内部却已经写不动。原因可能是Overlay文件系统。容器可写层。emptyDir。临时卷。日志层。某个特定PVC已经触碰自己的限制。特别是应用大量写/tmp或者不断产生日志、临时文件、缓存。从宿主机总容量看还有空间。但容器当前真正能用的那一层已经满了。所以容器环境里一定要区分Host Disk和Container Writable Layer / Volume这两个不是一回事。十、Kubernetes里还要注意emptyDir和Ephemeral Storage很多服务会把临时文件写到/tmp或者挂一个emptyDir看起来简单方便。但如果文件不断增长。程序不清理。或者一个请求会生成大量临时内容就可能消耗Pod的Ephemeral Storage。最后你看到宿主机磁盘没满。Persistent Volume也正常。但Pod照样因为临时存储问题异常。所以K8s排查时不能只看PVC。还要看Ephemeral Storage使用情况。十一、还有一种很容易被忽略的情况日志轮转“看起来有实际上没生效”很多服务都配置了日志轮转。比如每天一个文件。保留7天。超过大小自动切分。理论上应该很安全。但线上经常出现轮转规则没匹配到。程序自己又持有旧文件。压缩逻辑失败。旧日志根本没删。最后目录里堆了几千个文件。甚至几十万个文件。所以如果一个日志目录突然把inode吃满不能只问“有没有logrotate”而要继续确认它到底有没有真正执行成功。十二、最快排查顺序我建议直接按这7步走以后遇到“磁盘还有空间却报No space left on device”可以直接按这个顺序。第一步锁定报错目录先确认到底哪个路径写失败。第二步看这个路径对应的Filesystem不要只看根分区。第三步df -h看Block空间。第四步df -i看inode。第五步lsof L1检查deleted-but-open文件。第六步统计大目录和小文件数量确认是大文件吃容量还是小文件吃inode。第七步如果在容器里再看Overlay、emptyDir、Ephemeral Storage和PVC这套顺序比“一上来找大文件删”有效得多。十三、具体怎么修要看是哪一类问题如果是inode耗尽清理海量小文件。优化临时文件和日志生成策略。必要时调整文件系统设计。如果是deleted-but-open找到持有文件的进程。正确触发日志重开、reload或者在可控情况下重启进程。如果是某个单独挂载点满了清理对应挂载点。不要去清别的分区。如果是容器写层满了检查写路径是否应该迁移到Volume。减少容器层写入。设置合理清理机制。如果是日志轮转失效修轮转规则。确认程序和logrotate的协作方式。十四、为什么不建议直接“rm -rf 一堆目录”因为线上空间问题最容易引发第二次事故。比如误删正在使用的数据。缓存索引。运行时文件。数据库临时目录。应用依赖文件。所以真正修之前应该先回答这些文件是谁创建的现在谁还在使用删除以后能不能自动重建是否影响正在运行的服务如果只是为了快速腾空间最好也先明确哪一类文件是安全可删除的。而不是见目录大就删。十五、修完以后怎么验证不能只看df -h降下来了。至少还要一起看df -h是否恢复df -i是否恢复deleted-but-open是否清零报错目录是否重新可写日志是否继续正常轮转文件数量是否还在异常增长容器临时存储是否稳定重启后问题会不会再次出现。真正的目标不是“现在能写了。”而是这个资源耗尽路径已经被切断。十六、一个很典型的现场比如你看到根分区60%。第一反应磁盘还有40%。但继续查df -i发现/var/loginode已经100%。再统计文件数某个服务每秒生成几十个独立小日志。一天就是几百万个文件。这时候根因就很清楚不是磁盘容量不够。也不是Kubernetes有问题。而是文件数量把inode提前耗尽了。这类问题如果不先看inode再怎么删几个大文件都解决不了。十七、这种Linux磁盘排查Plus和Pro怎么判断如果你平时只是偶尔让 ChatGPT、Codex分析一次磁盘告警。看看df -h、df -i。帮你读一下lsof。辅助判断Docker、K8s写层问题。这种任务比较集中Plus通常已经够用。关键还是把Evidence给完整报错路径。Filesystem。Block使用率。inode使用率。容器信息。日志目录。文件数量。这些信息比只给一句“服务器磁盘报错了。”有用得多。如果你的日常已经变成持续排查Linux、Docker、Kubernetes、JVM、数据库、网络问题。一次线上事故需要同时分析系统日志。容器日志。磁盘。inode。文件句柄。Pod事件。应用代码。还要让Codex继续改清理逻辑、日志策略、容器配置并做回归这种高频、多轮、长时间工程排障已经成为日常那Pro会更适合。所以Plus还是Pro不看“这个磁盘问题难不难。”而是看ChatGPT、Codex每天是不是已经持续参与完整的线上排障链路。偶发排查、短任务Plus通常够用。持续系统治理、多轮分析和验证再考虑Pro。最后磁盘明明还有40%空间为什么服务却突然报No space left on device因为Linux里的“没空间”不一定只代表GB用完了。还可能是inode没了。错误挂载点满了。文件删了但进程还占着。容器写层满了。临时存储耗尽。日志轮转失效。所以以后遇到这类问题不要只盯着df -h更完整的排查应该是Block → inode → Mount → Open File → Container Layer → Log Rotation一旦把这几个层级拆开很多看起来特别矛盾的“磁盘明明还有空间为什么却写不进去”其实很快就能定位。真正的问题往往不是磁盘到底还剩多少GB。而是当前这个写入路径到底还剩多少真正可用的文件系统资源。持续分享 Codex、大模型开发与 AI 编程实战内容。长期深度使用各类代码大模型也整理了稳定的Plus/Pro会员订阅渠道有需要可自取。