吃掉了部署的/tmp目录
部署失败报 No space left on device,但 df 显示根分区还有大量空间。真凶是 /tmp:它不是磁盘,是 838MB 的 tmpfs,被临时文件塞满后连 shell 和 cron 都开始报错。
💡 你将学到
部署失败报 No space left on device,但 df 显示根分区还有大量空间。真凶是 /tmp:它不是磁盘,是 838MB 的 tmpfs,被临时文件塞满后连 shell 和 cron 都开始报错。
吃掉了部署的/tmp目录
部署脚本跑到一半报错:No space left on device。第一反应是磁盘满了,df -h / 一看根分区还剩一大半,再往下翻,/tmp 显示100%使用,容量838MB。
困惑很典型:空间到底去哪了? 答案是 /tmp 不是磁盘上的目录,而是挂在内存里的 tmpfs。
一、先搞清 /tmp 是什么
多数现代 Linux 发行版把 /tmp 挂成 tmpfs,数据放在内存(或swap)里,重启即消失。好处很实在:临时文件读写快,重启自动清理,不会因为程序忘删临时文件而塞满磁盘。
代价也很实在:容量不是"剩余磁盘",而是挂载时设定的上限(多数发行版按物理内存比例分配,具体看 tmp.mount 或 /etc/fstab);它吃的是内存,df -h / 一切正常,free -h 的可用内存却少得可疑;写满后不只是部署失败,shell、cron、日志、包管理器都会报各种看起来不相关的错。
二、三条命令定位
# 挂载类型和容量上限
df -h /tmp
mount | grep ' /tmp '
# 谁在吃空间
du -sh /tmp/* 2>/dev/null | sort -rh | head -20
# 已删除但进程还占着的文件
lsof +L1 | head -20
第三条最容易被忽略:文件删了但进程还开着句柄,空间不会释放。常见于日志被 rm 掉、写入进程还在跑的场景。
这次是第二条就抓到了:/tmp/pip-* 和 /tmp/deploy-* 下面堆了几百MB解压文件——部署脚本把 wheel 包和代码解压到 /tmp,跑完不清理。
三、为什么会"悄悄崩溃"
脚本的典型流程是:下载、解压到 /tmp/xxx、安装、启动。空间不足发生在解压那一步,tar或pip报错退出,脚本没有 set -e,于是继续往下跑,最后报出来的错误是"服务启动失败"。
这就是最难查的地方:真正的原因在中间,报出来的错误在末尾。
set -euo pipefail # 任何一步失败立刻退出
avail_mb=$(df -Pm /tmp | awk 'NR==2{print $4}')
[ "$avail_mb" -lt 500 ] && { echo "not enough space in /tmp"; exit 1; }
四、正确的位置:别把部署放在 /tmp
/tmp 的名字已经说明定位:临时的。把代码 clone 到 /tmp 想着"先跑起来晚点挪走",结果一定是几周后服务器重启、目录清空、代码没了。
| 位置 | 用途 |
|---|---|
/opt/<app> 或 /srv/<app> |
应用代码,持久、权限清晰 |
/var/lib/<app> |
需要备份的应用数据 |
/var/tmp |
需要跨重启保留的临时文件 |
/tmp |
真正的临时文件,重启即弃 |
如果脚本非要用 /tmp,至少把 TMPDIR 指到别处:
export TMPDIR=/var/tmp/deploy
mkdir -p "$TMPDIR"
pip、tar 和多数构建工具都尊重 TMPDIR,这一行能解决很大一部分"临时文件塞爆 /tmp"的问题。
五、容量要不要调
# 临时调大(重启失效)
mount -o remount,size=2G /tmp
# 永久生效:/etc/systemd/system/tmp.mount.d/override.conf
[Mount]
Options=mount,size=2G,mode=1777
先想清楚一点:tmpfs占的是内存。把 /tmp 调到4GB,等于预留4GB可能被临时文件吃掉的内存,2GB内存的小机器上OOM风险直接拉满。
对服务进程,更干净的做法是 systemd 的 PrivateTmp=true:服务看到自己的 /tmp,与其他服务隔离,退出即清理。
六、让它别再发生
- 部署脚本加清理:
trap 'rm -rf "$TMPDIR"' EXIT。 /tmp加监控:和磁盘一样监控tmpfs使用率。只监控/的机器永远发现不了这个问题。- 定期清理:
systemd-tmpfiles --clean按策略清过期文件。 - 容器里更要注意:容器内
/tmp常是内存盘,跑构建任务更容易撞上限。 - 别在
/tmp下跑长驻服务:目录被清、权限被改、空间被别的进程吃掉,任何一种都会让你半夜起来。
常见问题
Q:df -h / 有空间,为什么还报没空间?
A:因为写的是另一个挂载点,df -h /tmp 单独看。inode用尽也会报同样的错,用 df -i 排除。
Q:文件删了空间没回来?
A:进程还开着句柄,lsof +L1 找到持有者,重启那个进程即可。直接删日志文件是常见起因。
注:不同发行版对
/tmp的挂载方式和默认容量策略不同,具体以/etc/fstab和tmp.mount的实际配置为准;文中的838MB是当时环境的值,不是通用默认。
相关文章
本站文章由编辑人工撰写,收录的工具均经过实测或公开资料核验。文中链接指向工具官网或 GitHub 仓库,仅作信息参考,不构成付费推广。
