ThinkPHP部署后“Permission denied”核心是Web服务器用户、组、路径未对齐;须先用ps和systemctl确认真实运行用户,再按顺序执行chown、chmod、namei排查及SELinux/open_basedir适配。

ThinkPHP部署后报“Permission denied”,核心不是权限数字没设够,而是用户、组、路径三者没对齐——Web服务器进程(如www-data)必须能逐级进入目录、读取代码、写入runtime,缺一环就失败。
先确认Web服务器实际运行用户
别凭经验猜,执行命令查真实身份:
-
Apache:运行
ps aux | grep apache2或ps aux | grep httpd,看USER列(通常是www-data或apache) -
Nginx + PHP-FPM:运行
ps aux | grep php-fpm,再用systemctl show php-fpm.service | grep -E 'User|Group'确认服务配置 - 验证该用户是否存在:
id -u www-data && id -g www-data,返回数字才有效;若提示“no such user”,需先安装对应服务
五步精准赋权(顺序不能乱)
进入项目根目录后,按以下顺序执行:
-
重置所有权:执行
chown -R deploy:www-data .——deploy是你日常操作的普通用户,www-data是Web组;组必须正确,否则public下静态资源无法被读取 -
锁死代码层:运行
find . -path "./app" -o -path "./config" -o -path "./route" | xargs chmod -R 640——这些目录只读,禁止PHP进程写入 -
放开入口与静态资源:执行
chmod 750 public、chmod 640 public/index.php、chmod -R 750 public/static——index.php需+x才能被Apache解析 -
runtime必须可写且隔离:运行
chmod -R 770 runtime/,再find runtime/ -type f -exec chmod 660 {} \;——目录770确保deploy和www-data组都能读写,文件660防内容泄露 -
上传目录单独强化:若
config/filesystem.php中'root'指向public/storage,则执行chmod -R 770 public/storage,并确认该路径已从Git排除
排查路径与父级权限陷阱
即使runtime本身770,也可能因上层某一级目录缺少x(执行)权限而进不去:
立即学习“PHP免费学习笔记(深入)”;
- 用
namei -l /var/www/html/runtime查每级目录的owner/group/perm,快速定位卡在哪一层 - 确保从根目录到runtime的每一级(如
/var、/var/www、/var/www/html)都对www-data有x权限 - 检查Nginx/Apache的
root或DocumentRoot是否和ThinkPHP里RUNTIME_PATH定义的物理路径一致,不一致会导致PHP往错误位置写入
绕过SELinux或open_basedir限制
某些环境会额外加锁:
- Ubuntu/CentOS启用SELinux时,运行
chcon -R -t httpd_sys_rw_content_t /path/to/runtime或临时禁用:setenforce 0 - 检查php.ini或虚拟主机配置中是否有
open_basedir,确保runtime路径在允许范围内;测试时可临时注释该行 - Windows下右键
runtime→ 属性 → 安全 → 编辑 → 添加IIS_IUSRS或当前用户,赋予“修改”权限



















