PHP mkdir()设权限需用八进制(如0755)、显式启用$recursive=true,实际权限受umask截断(如0777 & ~0022 = 0755),Windows下忽略该参数;推荐创建后用chmod()精确设置。

PHP 的 mkdir() 创建目录时,指定的权限(如 0755)**不会直接生效**,而是会和当前系统的 umask 做位运算(& ~umask),最终得到实际权限。这是 Linux/Unix 类系统通用机制,PHP 完全遵循它。
umask 是怎么截断 mkdir 权限的
umask 是一个“权限掩码”,它从你请求的权限中“拿走”对应位。例如:
- 你写
mkdir('log', 0777) - 系统当前
umask是0022(最常见默认值) - 真实权限 =
0777 & ~0022=0755(即drwxr-xr-x)
简单说:umask 不是“加限制”,而是“强制屏蔽”。哪怕你传 0777,只要 umask 是 0022,组和其他用户的写权限(第 2、3 位的 2)就一定被去掉。
为什么 0755 比 0777 更稳妥
很多场景下,你并不需要所有用户都能写目录。用 0755 能避免因 umask 变动导致权限意外放大:
立即学习“PHP免费学习笔记(深入)”;
-
0755 & ~0022 = 0755(预期一致) -
0777 & ~0002 = 0775(如果 umask 是0002,组可写,但你可能没意识到)
尤其在共享主机或容器环境中,umask 可能被环境预设,硬写 0777 并不等于“真有 777”,反而容易掩盖权限设计问题。
想严格控制权限,有两个可靠办法
仅靠 mkdir() 参数无法绕过 umask,必须额外干预:
-
创建后补 chmod:最常用、最安全
mkdir($path, 0777, true); chmod($path, 0755);
chmod 不受 umask 影响,能精确设置目标权限 -
临时修改 umask:慎用,尤其在 Web 服务器多请求并发时
$old = umask(0); mkdir($path, 0777, true); umask($old);
注意:此操作会影响同一进程内后续文件操作,且线程/worker 共享 umask,不适合常驻进程
Windows 下完全不用考虑 umask
Windows 系统忽略 mkdir() 的权限参数,无论传 0777 还是 0644,都无效。权限由 NTFS ACL 或父目录继承决定,PHP 层无法通过该函数控制。



















