PHP报错Permission denied权限问题解决
前言
PHP写文件、读文件、上传文件,突然报"Permission denied"?这是Linux文件权限问题,最常见就是文件或目录的所有者不对、权限不够。本文讲怎么排查和解决。
一、报错长啥样
Warning: fopen(/data/test.txt): failed to open stream: Permission denied in /www/test.php on line 5
意思:PHP没权限操作这个文件/目录。
二、常见原因
原因1:文件/目录权限不够
PHP没有读或写的权限。
原因2:文件/目录所有者不对
PHP用www用户跑,但文件是root创建的,www没权限。
原因3:SELinux开着
CentOS默认开SELinux,即使权限对了也不让访问。
原因4:目录权限不够
要写文件的话,目录本身也要有写权限。
三、排查步骤
第一步:看报错的文件路径
报错信息里会告诉你是哪个文件:
Permission denied: /data/upload/test.jpg
就是 /data/upload/ 这个目录的问题。
第二步:看文件权限
ls -l /data/upload/
输出类似:
-rw-r--r-- 1 root root 1024 Oct 9 10:00 test.txt
看第一个字段:
-rw-r--r--表示所有者能读写,其他人只能读
看所有者:
root root表示所有者和组都是root
第三步:看PHP用什么用户跑
ps aux | grep php-fpm
输出里会看到:
www 1234 0.0 0.5 123456 7890 ? S 10:00 0:00 php-fpm: pool www
PHP是用 www 用户跑的。
如果文件所有者是root,那www用户就没权限写。
四、解决方法
方法1:改文件所有者
把文件/目录的所有者改成PHP的用户:
# 改单个文件
chown www:www /data/upload/test.txt
# 改整个目录(包括里面的文件)
chown -R www:www /data/upload/
推荐这个方法,最安全。
方法2:改权限
给所有人加权限:
# 文件加写权限
chmod 666 /data/upload/test.txt
# 目录加写权限
chmod 777 /data/upload/
注意: 777太不安全了,尽量用方法1改所有者。
方法3:看SELinux
CentOS开了SELinux的话,即使权限对了也不行。
检查SELinux:
getenforce
输出 Enforcing 就是开着。
临时关掉:
setenforce 0
永久关掉:
vi /etc/selinux/config
把:
SELINUX=enforcing
改成:
SELINUX=disabled
重启服务器生效。
或者只给目录加SELinux权限:
chcon -R -t httpd_sys_rw_content_t /data/upload/
五、常见场景
场景1:上传图片报错
用户上传图片,报Permission denied。
原因: uploads目录所有者不对。
解决:
chown -R www:www /www/wwwroot/你的站/uploads/
场景2:写日志报错
PHP写日志文件,报Permission denied。
原因: 日志目录没权限。
解决:
chown -R www:www /var/log/你的应用/
场景3:session不存
PHP session存不进去。
原因: session目录没权限。
解决:
chown -R www:www /var/lib/php/session/
场景4:缓存目录没权限
ThinkPHP/Laravel缓存写不进去。
原因: runtime目录没权限。
解决:
chown -R www:www runtime/
六、常用命令
看文件权限
ls -l 文件名
看目录权限
ls -ld 目录名
改所有者
chown 用户:组 文件
chown -R 用户:组 目录
改权限
chmod 755 目录
chmod 644 文件
七、权限数字含义
| 数字 | 含义 |
|---|---|
| 7 | 读+写+执行 (4+2+1) |
| 6 | 读+写 (4+2) |
| 5 | 读+执行 (4+1) |
| 4 | 只读 |
常用:
- 目录:755
- 文件:644
- 上传目录:775(或改所有者)
八、常见坑
坑1:只改了文件,没改目录
要写文件的话,目录本身也要有写权限。
解决: 目录也要改所有者。
坑2:递归改权限
chmod -R 777 目录
太危险了,所有人都能写。
解决: 优先改所有者,不要随便777。
坑3:SELinux偷偷开着
CentOS7以后默认开SELinux,权限对了也不行。
检查:
getenforce
坑4:父目录没权限
比如 /data/upload/ 有权限了,但 /data/ 没权限,还是进不去。
解决: 从根开始一层一层检查。
总结
记住:
- 报错先看是哪个文件/目录
- 看文件所有者是不是PHP的用户(一般是www)
- 不是就
chown -R www:www 目录 - 还不行就检查SELinux
- 尽量改所有者,不要随便777
最常用:
chown -R www:www /你的目录/
遇到问题加QQ23979811 协助处理