
当 PHP 脚本在 Apache 下运行时,realpath('..') 或 realpath(__DIR__ . '/../') 返回空字符串,通常并非权限缺失,而是因 open_basedir 限制或目录缺少执行(x)权限导致 realpath() 返回 false,而强制转为字符串后显示为空。
当 php 脚本在 apache 下运行时,`realpath('..')` 或 `realpath(__dir__ . '/../')` 返回空字符串,通常并非权限缺失,而是因 `open_basedir` 限制或目录缺少执行(x)权限导致 `realpath()` 返回 `false`,而强制转为字符串后显示为空。
realpath() 函数要求路径中每一级目录都必须对当前 PHP 进程用户(如 www-data)具有执行权限(x)——注意:此处的“执行权限”在 Unix/Linux 中并非运行文件的含义,而是“进入该目录”的必要条件。若任一上级目录(例如 /var/www/www-root 或其父级)缺少 x 权限,realpath() 将直接返回 false,而代码中 '' . false 或 (string)false 会静默转为空字符串,造成“看不见父目录”的错觉。
同时,你的 open_basedir 配置为 /var/www/www-root/data:.,这是一个关键限制:realpath() 在解析路径时,即使目标目录物理存在且权限正确,只要其不在 open_basedir 列出的允许路径内,也会失败(返回 false)。例如,若脚本位于 /var/www/www-root/data/app/,则 .. 指向 /var/www/www-root/data/ ——这仍在白名单内;但 ../.. 指向 /var/www/www-root/,已超出 /var/www/www-root/data 范围,因此被拒绝。
✅ 正确诊断与修复步骤:
-
检查 realpath() 的原始返回值(避免隐式类型转换):
立即学习“PHP免费学习笔记(深入)”;
var_dump(realpath('..')); // 应输出 string 或 bool(false) var_dump(realpath(__DIR__ . '/../'));若输出 bool(false),说明失败,而非路径为空。
-
验证目录执行权限(以 www-data 用户身份):
sudo -u www-data ls -ld /var/www/www-root /var/www/www-root/data
确保每级目录(包括 /var/www/www-root)对 www-data 具有 x 权限(如 drwxr-xr-x 中的 x)。若缺失,修复权限:
sudo chmod +x /var/www/www-root
-
扩展 open_basedir(如业务确需访问父目录):
在 php.ini、Apache <Directory> 或 .htaccess 中调整(注意安全权衡):open_basedir = "/var/www/www-root:/tmp"
或更精确地限定:
open_basedir = "/var/www/www-root/data:/var/www/www-root/shared:/tmp"
⚠️ 注意事项:
- 不要盲目关闭 open_basedir(如设为 ""),这将严重削弱隔离性;
- 避免在生产环境使用 chmod 777,应最小化授权(如 chmod 755 + 正确属主);
- 推荐替代方案:用 dirname(__DIR__) 获取父目录路径(不依赖 realpath),再结合 is_dir() 和 is_readable() 显式校验;
- 若仅需写入文件,优先使用绝对路径(如 '/var/www/www-root/shared/logs/')并确保该路径已在 open_basedir 中显式声明。
总结:realpath() 的“失灵”本质是安全机制的体现——它既受 OS 文件系统权限约束,也服从 PHP 的 open_basedir 沙箱策略。排查时务必区分 false(逻辑失败)与真实空路径,并始终以最小权限原则配置环境。



















