第一反应是查目录归属而非改权限;执行ls -ld vendor/等命令,重点看第三列(属主)和第四列(属组),若非当前用户则需用chown修复所有权,而非盲目chmod。

ls -ld vendor/ 能直接看到谁在管这个目录
报 Permission denied 时,第一反应不是改权限,而是看“谁 owns 这个目录”。ls -ld 是最准的快照命令,它只显示目录本身的权限和归属,不递归、不干扰、不误导。
执行这三行,重点盯第三列(属主)和第四列(属组):
-
ls -ld vendor/→ 看 Composer 写文件的地方归谁 -
ls -ld composer.lock→ 看锁文件是否被 root 占着 -
ls -ld $(composer config --global cache-dir)→ 看全局缓存目录是不是落在/root/.composer或权限受限路径
如果任意一行输出里第三列不是你的用户名(比如显示 root 或 www-data),问题就定位了——不是“不能写”,是“不归你管”。
chmod 和 chown 的作用根本不同,别混用
chmod 改的是“允许谁访问”,chown 改的是“谁拥有它”。90% 的 Composer 权限失败,根源是后者出错,不是前者。
常见误操作:
- 看到
Permission denied就跑chmod -R 777 vendor/→ 后果:CI 拒收vendor/bin/phpunit,Git 提示ownership changed,下次composer update可能只写一半 - 用
sudo composer install强行过 →vendor/全变成root:root,后续所有操作都卡住
正确做法只有一条:sudo chown -R $USER:$USER vendor/(或 ./ 修复整个项目目录)。
Windows 下要看 ACL,不是 ls -l
在 Windows(包括 WSL2 外的原生环境)中,ls -l 显示的权限位基本无效,真正起作用的是 NTFS ACL。报 Access is denied 且路径含 %APPDATA%\Roaming\Composer\Cache,大概率是当前 PHP 进程用户(如 IIS_IUSRS 或你的登录账户)没被授予“写入”或“完全控制”权限。
验证方式:
- 运行
composer config --global cache-dir,复制输出路径 - 右键该文件夹 → “属性” → “安全”选项卡 → 查看当前用户是否在列表中、是否有“写入”勾选
修复命令(需管理员 PowerShell):icacls "$env:APPDATA\Roaming\Composer\Cache" /grant "$env:USERNAME:(OI)(CI)F" /t —— 这比删缓存、重装 Composer 管用得多。
umask 和 COMPOSER_HOME 会悄悄影响权限结果
即使 chown 修好了,新生成的文件仍可能不可写,原因常藏在这两个地方:
-
umask设置太严(如077)→ 新建文件默认只有 owner 可读写,组和其他人全拒之门外。检查:umask命令输出,推荐设为002(开发机)或022(生产) -
COMPOSER_HOME被错误指向系统级路径(如/usr/local/composer或/root/.composer)→ 所有全局操作都会撞墙。查:composer config --global home,不对就立刻重设:composer config -g home "$HOME/.composer"
这两个变量不报错,但会让 chown 修好的目录,在下次 composer global require 时又变回 root 所有——这是最隐蔽也最容易反复踩的坑。


















