chmod -R 555 vendor/会炸锅,因PHP需目录执行位(x)才能opendir()遍历子目录,而555虽含x但误删vendor/bin/脚本执行权,且导致autoload_static.php写入失败;正确做法是chown -R deploy:deploy vendor/、chmod 755 vendor/、文件设644、vendor/bin/单独加x,并确保www-data属deploy组。

生产环境 vendor 目录不能简单设为只读(比如 chmod -R 555 vendor/),否则 PHP 会因缺失目录执行位(x)而无法遍历子目录,直接导致 opendir() 失败、autoload.php 加载中断,报错如:Warning: require(/var/www/app/vendor/autoload.php): failed to open stream。
为什么 chmod -R 555 vendor/ 会炸锅
PHP 进程需要对目录有执行权限(x)才能进入、列出其内容。555 权限虽保留读和执行,但会错误地移除所有文件的执行位——而 vendor/bin/ 下的可执行脚本(如 phinx、php-cs-fixer)必须有 x 才能运行;更关键的是,555 对目录本身不“加 x”(实际是 555 = r-xr-xr-x,x 已存在),但它会让 find、composer 等工具误判路径可写性,引发后续 autoload_static.php 写入失败等连锁问题。
-
opendir()失败:目录无x→ 无法scandir()→ PSR-4 自动加载退化失效 -
file_put_contents(.../autoload_static.php)Permission denied:框架在vendor/composer/下尝试缓存写入,但该目录属主是root,而 PHP-FPM 以www-data运行且未加入部署组 -
rsync或cp -r继承源端权限:本地开发机上chmod错误会被同步到线上,一模一样复现
正确设置 vendor 只读的三步操作
目标是:目录可遍历(r-x)、文件不可写(r--)、二进制可执行(---x)、PHP 进程有组读权限。
-
chown -R deploy:deploy vendor/:确保归属部署用户与组,避免root残留 -
chmod 755 vendor/:根目录必须是755(rwxr-xr-x),保证www-data能进入 -
find vendor/ -type f -exec chmod 644 {} \;:所有文件设为644(rw-r--r--),去写权限 -
chmod +x vendor/bin/* 2>/dev/null || true:仅给vendor/bin/下明确需执行的文件加x,其余跳过 -
chmod -R g+rX vendor/:X是“智能执行位”,只对目录或已有x的文件生效,比x更安全
CI/CD 同步后 PHP-FPM 仍报 Permission denied?检查这三点
常见现象是 file_put_contents(/var/www/app/vendor/composer/autoload_static.php): Failed to open stream: Permission denied,本质不是权限数字错了,而是权限模型没对齐。
-
usermod -aG deploy www-data:确保www-data用户属于deploy组,否则g+rX白设 - 同步命令加
--no-perms --no-owner:用rsync -av --no-perms --no-owner ...或cp -r --no-preserve=mode,ownership ...,避免继承错误权限 - 确认
vendor/composer/目录权限是755且属组为deploy:用ls -ld vendor/composer/验证,不是750或700
composer install 绝对不能在生产机上跑
它会触发 post-install-cmd、生成缓存、写 autoload_static.php,这些操作由 PHP-FPM 进程执行,极易因权限/超时/SELinux 失败;若用 root 跑,又会留下 root:root 文件,后续 CLI 操作受 umask 影响失控。
- 所有依赖安装、autoload 优化、classmap 生成,必须在构建机(CI/CD)完成
- 部署包里应已含完整
vendor/和vendor/composer/autoload_classmap.php - 生产机只做解压、
chown/chmod、systemctl reload php-fpm,不碰composer命令
真正容易被忽略的点是:权限控制不是“设完就完”,而是要让 www-data 在 deploy 组里、vendor/ 目录有 x、vendor/bin/ 下可执行文件单独加 x、同步过程不带权限——四者缺一不可。漏掉任意一个,都可能在某个边缘请求里突然报错,且日志里只显示“failed to open stream”,根本看不出是权限链断在哪一环。


















