vendor目录设为只读但autoload失败,根本原因是chmod -R 555剥夺目录执行位导致opendir()失败;正确做法是chmod 755 vendor/确保目录可遍历,文件用644,vendor/bin/单独加x,并确保www-data属deploy组。

vendor 目录设为只读但 autoload 失败?别用 chmod -R 555
直接 chmod -R 555 vendor/ 是典型错误操作。PHP 进程需要目录的执行位(x)才能进入子目录遍历,否则 opendir() 就会失败,报错如:Warning: require(/var/www/app/vendor/autoload.php): failed to open stream。更糟的是,某些框架会在 vendor/composer/ 下尝试写 autoload_static.php,直接触发 Permission denied。
正确做法是分层控制:
-
chown -R deploy:deploy vendor/→ 归属部署用户,避免 root 残留 -
chmod 755 vendor/→ 目录必须有执行位,否则无法遍历 -
find vendor/ -type f -exec chmod 644 {} \;→ 所有文件去写权限,保留读+组执行权 -
chmod +x vendor/bin/* 2>/dev/null || true→ 仅放行明确需执行的二进制(如phinx),其余删掉
CI/CD 同步后 PHP-FPM 报 Permission denied?检查属主和组权限
常见现象是 file_put_contents(/var/www/app/vendor/composer/autoload_static.php): Failed to open stream: Permission denied,实际原因是 vendor/composer/ 目录属主为 root,而 PHP-FPM 以 www-data 运行,且该用户未加入 deploy 组。
修复关键点:
- 确保
www-data属于deploy组:usermod -aG deploy www-data - 同步后运行:
chmod -R g+rX vendor/(X表示“仅对目录或已有执行位的文件加x”,比x更安全) - 若用了
rsync或cp -r,加--no-perms --no-owner参数,避免继承源端错误权限
composer install 在生产机上跑出错?根本不能这么干
生产环境禁用 composer install。它会触发缓存写入、autoload 生成、post-install-cmd 脚本执行——这些操作在 PHP-FPM 进程里跑,极易因权限/超时/SELinux 策略失败。更危险的是,若由 www-data 生成 vendor/,后续 CLI 操作可能因 umask 失控;若用 root 装,又留下安全隐患。
实操底线:
- 所有
composer install必须在构建阶段完成(CI/CD 或本地打包),产出完整vendor/和autoload.php,再整体同步 - 生产机上删掉
composer二进制,或chmod -x /usr/bin/composer,防误操作 - CI 中必须带
--no-dev --optimize-autoloader --classmap-authoritative,避免 dev 包混入线上
auth.json 配私有源失败却没报错?路径、字段、域名必须严丝合缝
Composer 静默跳过错误配置,不报错也不提示。90% 的失败是因为 auth.json 没放对位置、字段名写错,或域名 key 和 repositories.url 的 host 不完全一致(含端口)。
必须满足三项:
- Linux/macOS 路径必须是
~/.composer/auth.json,权限600:chmod 600 ~/.composer/auth.json - 字段名只能是
"http-basic",其他如gitlab-token、oauth全无效 - 域名 key 必须与
repositories.url的 host 完全一致,例如"gitlab.example.com:8080"对应"gitlab.example.com:8080",少一个端口都不行
最易被忽略的是 post-install-cmd 的副作用——某些包脚本会悄悄创建可写 symlink 或目录,安装后必须立即用 find vendor/ -type d -exec chmod 755 {} \; 清理,而不是依赖 umask 一次到位。











