FrankenPHP启动失败报Permission denied的根本原因是vendor/bin/frankenphp权限不足、Web用户无路径访问权、父目录缺x权限、SELinux或open_basedir拦截,须按此四层顺序排查。

FrankenPHP 启动失败报 Permission denied,根本不是二进制没下载完,而是 vendor/bin/frankenphp 文件虽存在但不可执行,或 Web 用户(如 www-data)无权读取/进入其所在路径——必须按顺序检查可执行性、所有权、父级目录 x 权限、SELinux 与 open_basedir 四层。
vendor/bin/frankenphp 权限不足:chmod +x 不是可选操作
FrankenPHP 的二进制由 php artisan octane:install --server=frankenphp 下载并生成脚本,但它默认不设执行位。即使 ls -l vendor/bin/frankenphp 显示文件存在,若权限是 -rw-r--r--(即无 x),系统直接拒绝加载:
- 必须手动运行
chmod +x vendor/bin/frankenphp(仅加所有者执行位即可,无需777) - 若在 CI/CD 或 Docker 构建中执行了
octane:install,需确认该命令是否实际完成——检查vendor/bin/frankenphp是否存在且file vendor/bin/frankenphp返回 “ELF executable” - Windows 用户必须启用 WSL2;原生 Windows 下
frankenphp二进制无法运行,报错就是Permission denied(本质是 exec 失败)
Web 用户无法访问 vendor/bin 路径:namei 比 ls 更快定位断点
frankenphp 启动时由 PHP-FPM 或 Apache 子进程调用,它需要逐级进入 vendor/bin/ 目录。即使 vendor/bin/frankenphp 本身是 755,只要上层某一级(如 vendor 或项目根目录)对 www-data 缺少 x 权限,就会卡在“无法进入目录”:
- 用
namei -l /path/to/project/vendor/bin/frankenphp一次性查看每级 owner/group/perm,快速识别哪一层的www-data没有x - 常见陷阱:项目根目录权限为
750,但属组不是www-data;应改用chown -R $USER:www-data .并确保根目录有750或755 - Apache 的
DocumentRoot和 Octane 的RUNTIME_PATH物理路径必须一致,否则 PHP 进程会尝试往错误路径写日志,触发二次Permission denied
SELinux 或 open_basedir 拦截了二进制加载
某些生产环境(如 CentOS/RHEL)默认启用 SELinux,它会阻止 httpd 或 php-fpm 执行非标准路径下的二进制;而 open_basedir 则可能直接禁止访问 vendor/bin/:
立即学习“PHP免费学习笔记(深入)”;
- 临时验证 SELinux:运行
setenforce 0,再试启动;若成功,说明被拦截,应执行chcon -t httpd_exec_t vendor/bin/frankenphp - 检查
php.ini中open_basedir值,确认包含vendor/bin/所在的绝对路径(如/var/www/html/vendor/bin) - 若使用 Nginx + PHP-FPM,还需检查
php-fpm.conf或 pool 配置里是否有php_admin_value[open_basedir]覆盖了全局设置
真正容易被忽略的是:FrankenPHP 启动失败时,错误日志往往只显示 Permission denied,但没说清是哪个系统调用失败(execve?openat?stat?)。所以别急着 chmod 777,先用 namei 看路径,用 strace -e trace=execve,openat,stat php artisan octane:start --server=frankenphp 2>&1 | grep -E '(denied|no such)' 定位真实失败点。



















