Yii3项目上线后“Permission denied”错误主因是runtime和storage目录权限及所有权配置不当:public需755,runtime/storage需775且属Web服务器用户组(如www-data),.env文件权限必须为600,并需实测写入验证。

本地能跑通的Yii3项目一上服务器就报错“Permission denied”或“failed to open stream”,多半是文件权限没设对,不是代码问题也不是PHP版本问题。
确认关键目录权限是否符合生产环境要求
Yii3项目上线后,public/目录必须可被Web服务器读取和执行,runtime/和storage/目录必须可写,否则日志写不进、缓存生成失败、表单CSRF token验证直接崩。
登录服务器,进入项目根目录,执行:ls -ld public runtime storage
如果看到类似drwxr-xr-x(即755)或更严格的权限(如750),说明public权限没问题;但runtime和storage若显示drwxr-xr-x或drwx------,就必然出错——它们必须允许Web服务器用户(通常是www-data或nginx)写入。
执行以下命令修正:
chmod 755 public → chmod 775 runtime storage
【注意:storage目录权限必须是775,不能是755;否则migration、log、cache全部失效】
修复Web服务器用户对runtime和storage的实际所有权
光改权限不够。Linux下文件能否写入,取决于“权限位+所有者+所属组”三者共同作用。即使权限是775,如果目录所有者不是Web服务器用户,且不在其所属组里,照样拒绝写入。
先查Web服务器运行用户:
ps aux | grep nginx 或 ps aux | grep apache → 找到worker进程的USER列,常见为www-data(Ubuntu/Debian)、nginx(CentOS/RHEL)或apache。
假设查得是www-data,执行:
sudo chown -R $USER:www-data runtime storage
sudo chmod -R g+rw runtime storage
这一步把runtime和storage的组设为www-data,并赋予组内成员读写权限。后续所有由Web服务器触发的写操作(如日志追加、缓存生成)就能成功。
【切勿执行chown -R www-data:www-data —— 这会导致你本地无法用sudo以外的权限修改文件,调试极其痛苦】
检查.env文件权限防止敏感信息泄露
Yii3默认读取.env文件加载数据库密码、APP_KEY等,如果该文件权限太宽,会被Nginx/Apache直接返回给浏览器,造成密钥泄露。
执行:ls -l .env
若显示-rw-r--r--(644)或更宽松,立即收紧:
chmod 600 .env
这一步必须做,且只能是600。其他权限值(如644、640)在Nginx配置不当或路径解析异常时,存在被直接下载的风险。
验证PHP进程能否真实写入runtime目录
别信ls -l结果,要实测。在runtime目录下手动创建一个测试文件:
php -r "file_put_contents('runtime/test_write.txt', 'ok');"
如果报错failed to open stream: Permission denied,说明前面步骤仍有遗漏。
此时重点排查:
① SELinux是否启用(CentOS/RHEL)→ 执行sestatus,若为enabled,临时关闭测试:sudo setenforce 0;
② AppArmor(Ubuntu)是否限制了PHP进程 → 查/var/log/syslog是否有DENIED记录;
③ Nginx配置中是否误加了disable_symlinks或secure_link指令,间接阻断了路径访问。
只要test_write.txt成功生成,且内容为"ok",即可确认写入通道已打通。


















