PHP mkdir()递归创建目录异常:仅生成一级目录,子目录失败
解决PHP中mkdir递归创建子目录时的Permission Denied问题
这问题我之前做PHP文件上传功能时也踩过坑,咱们先把核心原因和解决方案理清楚:
问题根源分析
你代码里用了mkdir($dirfinal, 0664, true),但只生成了temporales目录,子目录创建失败报权限错误,主要问题出在权限参数的选择上:
- 目录和文件的权限要求不一样:文件的0664(可读可写)没问题,但目录需要**执行权限(x位)**才能让进程进入并在其中创建子目录/文件。你给的0664没有执行权限,导致
temporales目录创建后,PHP进程没法在里面创建基于$idhash的子目录。 - 递归创建的特性:当使用
mkdir的第三个参数true递归创建时,中间目录(也就是temporales)会用你指定的0664权限,而这个权限缺少x位,直接阻断了后续子目录的创建。
具体解决方案
1. 修正mkdir的权限参数
把权限从0664改成目录专用的权限,比如0755(服务器环境下最安全的选择,所有者可读可写可执行,其他用户可读可执行)或者0775(允许同组用户读写):
if (!is_dir($dirfinal)) mkdir($dirfinal, 0755, true);
注意:这里的八进制数必须带前导0,不然PHP会把它当成十进制数解析,导致权限完全错误。
2. 验证父目录的实际权限
有时候系统的umask会影响最终的目录权限,比如默认umask是0022的话,0755会被转换成0755(0755 & ~0022),而0664会变成0644,依然没有执行权限。你可以用chmod手动修正父目录权限:
$parentDir = $target_dir . "temporales/"; if (!is_dir($parentDir)) { mkdir($parentDir, 0755); chmod($parentDir, 0755); // 确保权限生效 } $dirfinal = $parentDir . $idhash; if (!is_dir($dirfinal)) { mkdir($dirfinal, 0755); }
3. 确认PHP进程的运行用户
确保PHP的运行用户(比如Apache的www-data、Nginx的nginx用户)对$target_dir有写权限,并且创建的temporales目录属于该用户或用户组。你可以用命令行查看目录所有者:
ls -l /path/to/your/target_dir
如果所有者不对,可以用chown修改:
chown -R www-data:www-data /path/to/your/target_dir
4. 排查SELinux限制(Linux服务器)
如果是CentOS、RHEL这类开启SELinux的系统,可能会阻止PHP创建目录。可以临时关闭SELinux测试(不建议长期关闭):
setenforce 0
如果问题解决了,就给目录设置正确的SELinux上下文:
chcon -R -t httpd_sys_rw_content_t /path/to/your/target_dir/temporales
总结
最常见的情况就是你给了文件权限而非目录权限,导致父目录无法被进程进入创建子目录。先把权限改成0755,基本就能解决大部分问题。
内容的提问来源于stack exchange,提问作者Gabriel I.
相关产品推荐
相关产品推荐

