答案是inode耗尽而非磁盘块用光;需先用df -i(linux/macos)或get-psdrive(windows)确认缓存及/tmp分区inode使用率是否接近100%,再停掉所有composer进程,执行composer clear-cache,并手动清理cache/vcs/和sys_get_temp_dir()中的残留文件。

不是磁盘块真满了,大概率是 inode 耗尽——df -i 一看就清楚。
先确认到底是磁盘块满,还是 inode 满
报 No space left on device 却发现 df -h 还剩几十 GB?那基本就是 inode 耗尽。Composer 缓存里每个包版本都建独立子目录(比如 ~/.composer/cache/files/monolog/monolog/1.27.0/),全是小文件,df -i 的 Use% 接近 100% 就会卡死。
- Linux/macOS:运行
df -i,重点看/tmp和缓存所在分区(比如/home) - Windows:PowerShell 中执行
Get-PSDrive C | Select-Object Used,Free,虽不直接显示 inode,但可辅助排除真实磁盘块是否真满
停掉所有 composer 进程再清理
直接 rm -rf ~/.composer/cache 风险极高:IDE 内嵌的 Composer、后台未退出的 php composer.phar、残留锁文件,都会导致删一半就报 file_put_contents(): No space left on device,甚至损坏缓存索引。
- 查进程:
ps aux | grep composer(Linux/macOS)或tasklist | findstr composer(Windows) - 杀干净:
kill -9 $(pgrep -f "composer")或手动结束对应 PID - 再跑
composer clear-cache——它会校验路径权限、跳过被占用项、安全删除无效/损坏/过期条目
手动精简 cache/files/ 和清空 cache/vcs/
composer clear-cache 不会删“有效但陈旧”的 ZIP 包(比如三年前装过的 monolog/monolog 1.18.0),这类冗余最占空间又最无用;而 cache/vcs/ 是 inode 杀手,clear-cache 默认完全不管它。
- 删 90 天前的 ZIP:
find ~/.composer/cache/files -name "*.zip" -mtime +90 -delete - 删整个旧版包目录(保留每个包最新版):
cd ~/.composer/cache/files && for d in */; do ls -t "$d" | tail -n +2 | xargs -I{} rm -rf "$d{}"; done - 安全清 Git 仓库:
rm -rf $(composer config --global cache-dir)/vcs - 长期方案:禁用它,运行
composer config --global cache.vcs false,之后所有包强制走--prefer-dist
别忘了 sys_get_temp_dir() 这个隐形炸弹
Composer 解压 ZIP、生成 autoload、执行脚本时重度依赖 PHP 的 sys_get_temp_dir() 返回路径。Windows 默认是 C:\Users\用户名\AppData\Local\Temp,Linux/macOS 是 /tmp——这里堆积的 composer_*.zip、php*.phar 文件往往比缓存还难察觉,且极易触发 inode 耗尽。
- Linux/macOS:
find /tmp -name "composer_*" -type f -delete 2>/dev/null - Windows:
del /s /q "%TEMP%\composer_*" 2>nul - 检查是否被其他工具(如 IDE、CI agent)长期占用该目录,必要时改 PHP 的
sys_temp_dir配置
真正卡住你的,从来不是几个 GB 的磁盘块,而是成千上万个没人管的小目录和临时文件。清理前不看 df -i,等于蒙眼扫雷。











