rsync报“no space left on device”但df -h显示空间充足,大概率是inode耗尽或目标路径权限不足;需用df -i检查inode使用率,确认目标目录可写权限,并注意nfs、符号链接等特殊场景。

rsync 报 "no space left on device" 但 df -h 显示空间充足
这大概率不是磁盘容量耗尽,而是 inode 耗尽或目标路径权限不足。Linux 下每个文件(包括空文件、硬链接、目录)都占用一个 inode,df -h 只看 block 使用率,df -i 才看 inode 使用率。
实操建议:
- 立刻运行
df -i /target/path,重点关注Use%列 —— 若接近或等于 100%,就是 inode 耗尽 - 检查目标目录是否可写:
ls -ld /target/path看权限和 owner/group;再用touch /target/path/test.$$ && rm /target/path/test.$$验证实际写入能力 - 常见陷阱:目标是 NFS 挂载点时,
df -i可能不准确,需登录到 NFS 服务端查真实 inode 使用情况
rsync 写入失败时的权限相关错误特征
当 rsync 因权限问题卡在“no space left on device”时,典型伴随现象是:rsync: mkstemp “xxx” failed: Permission denied (13) 或静默失败后目标目录无新文件。这不是磁盘满,而是 rsync 默认用临时文件机制(.filename.XXXXXX)写入,再原子重命名 —— 这要求目标目录对运行用户有 w 权限,且父目录必须有 x(执行)权限才能进入。
实操建议:
- 确认 rsync 进程运行用户(如非 root,常为普通用户或
www-data),再检查目标路径每一级的ls -ld /path/to/target - 特别注意:若目标路径含符号链接,rsync 默认不跟随(
--no-links),但权限检查仍按真实路径走;若链接指向不可写位置,也会触发该错 - 绕过临时文件(不推荐长期用):
rsync --inplace直接覆盖原文件,省去mkstemp步骤 —— 但会丢失原子性,断电/中断可能导致损坏文件
小文件多导致 inode 快速耗尽的识别与清理
Web 缓存、日志归档、Git LFS 对象、PHP session 文件等场景下,百万级小文件极易吃光 inode。即使单个文件仅几 KB,inode 也照占不误。一旦 df -i 显示 100%,新建任何文件(包括 rsync 临时文件)都会失败。
实操建议:
- 定位高 inode 占用目录:
find /target -xdev -type d | while read d; do echo "$(find "$d" | wc -l) $d"; done | sort -nr | head -20 - 常见元凶:
/var/lib/php/sessions、/tmp、/var/log/journal(systemd-journald 日志)、.cache子目录 - 清理前先确认用途:
du -sh /target/dir/* | sort -hr | head看大小,find /target/dir -type f -mmin +1440 | wc -l查 24 小时未访问文件
rsync 命令本身如何规避这类问题
不能指望 rsync 自动修复底层存储问题,但可以调整行为降低触发概率。关键不是加更多参数,而是理解哪些选项真正影响写入路径和临时文件策略。
实操建议:
- 强制指定临时目录(最实用):
rsync -av --temp-dir=/other/disk/tmp/ source/ target/,把临时文件甩到 inode 充足的分区 - 禁用临时文件(仅限可信环境):
--inplace+--no-whole-file组合,避免创建.filename.XXXXXX,但要注意中断风险 - 跳过已存在且大小/时间戳一致的文件:
--size-only或--ignore-times,减少不必要的写入尝试 - 不要用
--delete在 inode 将满的盘上清理 —— 删除操作本身也要分配 inode(用于日志、journal 等),可能雪上加霜
真正麻烦的是那种 /var 分区既小又堆满 session 文件还跑着 rsync 的老系统 —— inode 耗尽后连 rm 都可能失败,得先腾出几十个 inode 才能开始清理。这种时候,别急着敲 rsync,先 find /var/lib/php/sessions -name 'sess_*' -mmin +60 -delete 试两秒,比调参数管用。










