答案是 inode 耗尽而非磁盘空间不足,需用 df -i 检查;清理前须终止所有 composer 进程,再执行 composer clear-cache,并手动清理 cache/vcs/ 和 sys_get_temp_dir() 中的残留文件。

先确认是磁盘块满还是 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:
进入 $(composer config --global cache-dir)/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、ph 临时文件常被忽略,却极易吃光 inode。
清理方式:
Linux/macOS:rm -f /tmp/composer_*
Windows:手动清空 %LOCALAPPDATA%\Temp 下以 composer 开头的文件
检查当前路径:php -r "echo sys_get_temp_dir();"
真正卡住的时候,cache/vcs/ 和 sys_get_temp_dir() 里的残留才是最常被漏掉的两个点,尤其在 CI 环境反复执行后。











