composer 报错常因系统临时目录权限或空间不足,设 composer_tmpdir 可快速解决;它专管解压等临时操作,优先级高于默认路径,且不影响 cache-dir。

Composer 默认用系统临时目录(如 /tmp 或 %TEMP%)做解压、下载中转,但这个路径常被清理或权限锁死,导致“Permission denied”“No space left on device”等错误——这不是 Composer 本身坏了,而是它在你没注意的地方反复撞墙。
为什么 COMPOSER_TMPDIR 比改 cache-dir 更快见效
缓存目录(cache-dir)管的是长期存档的 zip 包和元数据;而 COMPOSER_TMPDIR 管的是“正在干活时手边那张临时工作台”,比如解压 ZIP、校验哈希、生成中间文件。很多报错卡在 Extracting archive 或 failed to open stream: Permission denied,其实根本没走到缓存写入那步,是临时区先崩了。
-
COMPOSER_TMPDIR优先级高于系统默认临时路径,只要设对且路径可写,Composer 就不会碰/tmp或%APPDATA%\Local\Temp - 它不干扰
vendor/或cache/的位置,适合在已有项目结构不敢动的前提下快速止血 - Linux/macOS 下必须用
export COMPOSER_TMPDIR="/path/to/tmp"(加在 shell 配置里才持久),Windows PowerShell 要用$env:COMPOSER_TMPDIR="C:\mytmp",cmd 则用set COMPOSER_TMPDIR=C:\mytmp - 路径不能含空格或中文;必须提前
mkdir -p /path/to/tmp && chmod 700 /path/to/tmp(Windows 同样要确保当前用户有“完全控制”ACL)
报 No space left on device 却 df -h 显示空间充足?查 inode
这是 macOS、Docker for Mac/Windows 或低配 VM 上的高频陷阱:Composer 在临时目录每下载一个包就建一堆小文件(.zip + 解压中间目录),/tmp 分区的 inode 很快耗尽。此时 df -h 看磁盘还有 80%,但 df -i /tmp 可能显示 Use% 100%。
- 验证命令:
df -i $(composer config --global cache-dir)或直接df -i /tmp(Linux/macOS);Windows 可用fsutil volume diskfree %TEMP% - 临时缓解:
sudo find /tmp -type f -atime +1 -delete(慎用,可能误删其他进程临时文件) - 根治方式:把
COMPOSER_TMPDIR指向一个 inode 充足的分区,比如 SSD 上的/mnt/ssd/tmp或 Linux 的tmpfs内存盘(sudo mount -t tmpfs -o size=1G tmpfs /mnt/ramdisk)
Windows 下 %APPDATA%\Local\Temp 权限被锁死?绕过比修复更稳
尤其在域控环境或企业策略收紧的 Windows 机器上,%TEMP% 目录 ACL 常被组策略强制锁定,即使你是管理员也改不了。此时硬刚权限不如换条路走。
- 不要试图用
icacls强制赋权——策略下次刷新就回滚,且容易触发安全审计告警 - 直接设
COMPOSER_TMPDIR到用户家目录下新路径:set COMPOSER_TMPDIR=%USERPROFILE%\composer-tmp(cmd)或$env:COMPOSER_TMPDIR="$env:USERPROFILE\composer-tmp"(PowerShell) - 手动创建该目录:
mkdir "%USERPROFILE%\composer-tmp",Windows 默认赋予当前用户完全控制,无需额外操作 - 确认生效:
composer install -v看日志里是否出现Using temp directory: C:\Users\Alice\composer-tmp
COMPOSER_TMPDIR 和 cache-dir 混用时的常见踩坑点
这两个路径完全独立,但容易因配置顺序或环境变量覆盖产生意外行为。
-
COMPOSER_TMPDIR是运行时环境变量,只影响当次命令;cache-dir是配置项,会持久化到~/.composer/config.json。别以为设了后者就不用管前者 - CI/CD 中(如 GitHub Actions)常预设
COMPOSER_CACHE_DIR,但它**不影响**COMPOSER_TMPDIR;不过如果 CI 镜像里/tmp本身不可写,仍需显式设置后者 - Docker 容器内若挂载了
/tmp(如-v /host/tmp:/tmp),但宿主机该路径属主是 root,容器内普通用户依然写不了——此时必须在docker run里通过-e COMPOSER_TMPDIR=/tmp2并挂载对应路径 - 最隐蔽的坑:某些 IDE(如 PHPStorm)终端启动时未加载 shell 配置,
export的COMPOSER_TMPDIR不生效,得在 IDE 设置里单独配置环境变量
临时目录不是“随便放哪都行”的地方,它是 Composer 执行链里最脆弱的一环。很多人花几小时调 vendor 权限,却忽略真正卡住的其实是解压前那几十毫秒的 openat() 调用——盯住 COMPOSER_TMPDIR,比盲目 chmod 或 sudo 有效得多。











