登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux tmpfs 满了但磁盘空间还有为什么

来源:17golang原创

时间:2026-09-12 19:11:01 204浏览 收藏

排查服务器写入失败时,最容易被误导的一幕是:根分区还有很多可用空间,应用却提示“磁盘满了”。如果报错路径落在 /tmp/dev/shm/run 或容器的临时目录,满的可能是一个独立的 tmpfs 挂载点。它的容量上限、inode 数量和内存归属,都不等于物理磁盘分区的剩余空间。

先用 findmnt 确认路径是不是 tmpfs,再分别看字节用量和 inode 用量;确认占用文件归属后再清理,确有内存余量时才考虑 remount 调整 size
要点速览
  • tmpfs 是以内存为主、可受 swap 影响的临时文件系统,df -h 显示的是它自己的配额。
  • df -i 满而字节未满时,通常是小文件或目录数量触及 inode 上限。
  • 扩容 tmpfs 只改挂载实例限制,不会增加磁盘;清理前必须确认文件由哪个服务创建。
不少运维或者后端开发都碰到过这种怪事:跑df查根分区或者数据盘的使用率还剩大半,程序往临时路径写文件的时候直接抛磁盘已满的错误,翻了半天监控才发现是tmpfs挂的临时存储目录爆了,剩下的普通磁盘空间再多也用不上。
tmpfs 是 Linux 里完全基于内存/交换分区的临时文件系统,它的可用容量独立于物理磁盘分区,挂载后占用的是内存和交换分区额度,和你物理硬盘剩余空间没有直接关联,所以才会出现物理磁盘很空、tmpfs 先被写满的情况。

先确认:满的是 tmpfs 配额,不是整块磁盘

不要只看根分区的 df -h /。把出现错误的真实路径带入下面的只读检查,先看文件系统类型和挂载边界:

# 把 /tmp 换成应用实际报错的路径
findmnt -T /tmp -o TARGET,SOURCE,FSTYPE,OPTIONS

# 查看该路径所在文件系统的容量,而不是只查看根分区
df -hT /tmp

# 检查同一挂载点的 inode 是否先耗尽
df -i /tmp

如果 FSTYPEtmpfsSizeUsedAvail 就是该实例的限制和使用情况;根分区的 Avail 只是另一个文件系统的指标。若报错路径只是普通目录,继续检查是否有上层 tmpfs 挂载、容器的 mount namespace,或服务实际写入了另一个临时目录。

Linux tmpfs 挂载点与 findmnt df 容量和 inode 指标对应关系示意图
图1:tmpfs 排查指标对应关系示意图,先把挂载点自己的容量与 inode 上限分开记录。

字节没满却写不进去,重点查 inode

tmpfs 不只有字节上限,还可以有 nr_inodes 上限。日志切分、浏览器缓存、构建临时文件或大量短生命周期小文件,可能先用光 inode。此时 df -h 看起来还有空间,但 df -iIUse% 已接近 100%。

再把挂载参数记录下来,确认限制从哪里来:

# 只显示目标 tmpfs 的当前挂载选项,便于核对 size/nr_inodes
findmnt -T /tmp -t tmpfs -o TARGET,FSTYPE,OPTIONS

# 对照所有 tmpfs,避免误把另一个挂载点当成目标
df -hT -t tmpfs
现象优先检查处理方向
Use% 100%size、大文件、删除但仍被进程打开的文件确认归属后清理,或评估 remount
IUse% 100%nr_inodes、小文件数量、目录层级清理文件数量,调整 inode 配额或改变临时文件策略
空间看似足够但进程被杀Shmem、swap、容器 memory limit处理内存压力,不要只扩大 tmpfs

找到真正占用者:先看目录,再决定删不删

确认文件系统类型后,可以只在这个挂载点内统计目录大小,避免把其他磁盘的数据混进来:

# -x 只跨当前文件系统;先按目录找热点,不直接删除
du -xhd1 /tmp 2>/dev/null | sort -h

# 列出近期较大的普通文件,输出前先确认路径属于目标挂载点
find /tmp -xdev -type f -size +100M -printf '%s %p\n' 2>/dev/null | sort -n | tail -20

# 查看 tmpfs/shmem 对系统内存的影响
grep -E '^(MemAvailable|SwapFree|Shmem|SReclaimable):' /proc/meminfo

du 找到的是目录项当前可见的文件;如果某个文件已删除但仍被进程打开,目录里看不到它,却可能继续占用内存。此时应让对应服务按自己的退出或重载流程释放句柄,而不是反复删除无关文件。容器环境还要看容器所在 cgroup 的 memory.currentmemory.stat,因为 tmpfs 的使用会进入内存账本。

清理、扩容还是限流:按占用来源处理

如果占用来自可重建缓存或已经完成的临时产物,先停掉会继续写入的任务,再按服务文档清理指定目录。不要直接执行清空整个 /tmp/dev/shm 的命令,因为其中可能有仍在使用的 Unix socket、共享内存文件或其他服务状态。

确认当前使用量低于目标值且主机、容器都有内存余量时,可以对单个挂载点做 remount;新值不能低于现有使用量:

# 仅示范调整指定挂载点;先确认 TARGET 和内存余量
sudo mount -o remount,size=2G /tmp

# 调整后重新读取实际上限和可用量
df -hT /tmp

这里的 2G 是 tmpfs 的容量上限,不是从磁盘分区划出 2G。扩大它可能增加内存压力;如果根因是 cgroup 的内存限制、服务无界地产生小文件或临时目录选错位置,应该修正服务配置、清理策略或资源限流,而不是持续加大 size

Linux tmpfs 字节配额 inode Shmem cgroup 与清理扩容处理边界示意图
图2:tmpfs 处理决策的约束关系示意图,扩容容量不等于增加主机磁盘空间。

常见问题

tmpfs 会不会完全占满物理内存?

它按需增长,页面可受 swap 影响,但把上限设得过大仍可能造成内存压力。上限不是承诺有同等容量的独立磁盘。

为什么删除文件后空间没有立刻回来?

若进程仍持有已删除文件的打开句柄,空间要等句柄关闭后才释放;先定位进程,再走服务自身的重载或重启流程。

只把根分区扩容能解决吗?

不能直接解决独立 tmpfs 的配额问题。根分区扩容改变的是磁盘文件系统,tmpfs 需要清理、调整挂载参数或改变服务的临时目录。

排查结论

这类“磁盘还有空间但写不进去”的故障,关键不是继续观察根分区,而是沿着“路径 → 挂载点 → bytes/inodes → 占用归属 → 内存/cgroup”逐层确认。内核关于 tmpfs 的说明见 https://cdn.kernel.org/doc/html/latest/filesystems/tmpfs.html,cgroup v2 的内存统计说明见 https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>